일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- gameplay ability system
- map design
- 게임 개발
- Multiplay
- ability task
- attribute
- rpc
- animation
- Replication
- local prediction
- gameplay tag
- 유니티
- os
- gas
- listen server
- UI
- photon fusion2
- MAC
- 게임개발
- 언리얼 엔진
- nanite
- gravity direction
- dirty cow
- Aegis
- gameplay effect
- ret2libc
- unity
- 언리얼엔진
- CTF
- Unreal Engine
Archives
- Today
- Total
Replicated
[Drag Down] 점프 공격하기 본문

몽타주 만들고

DDGA_JumpPushingCharacter 생성(GameplayAbility 상속)
일반 공격 코드 재활용 좀 할 거다
점프 상태에서 일반 공격 키 누르면 공격이 나갈 거다
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "DDGA_JumpPushingCharacter.generated.h"
/**
*
*/
UCLASS()
class DRAGDOWN_API UDDGA_JumpPushingCharacter : public UGameplayAbility
{
GENERATED_BODY()
public:
UDDGA_JumpPushingCharacter();
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
private:
UFUNCTION()
void OnMontageCompleted();
UFUNCTION()
void OnPushingEventReceived(FGameplayEventData Payload);
UFUNCTION()
void OnTraceResultCallback(const FGameplayAbilityTargetDataHandle& TargetDataHandle);
void ProcessPush(const FGameplayAbilityTargetDataHandle& TargetDataHandle);
void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;
void CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancel) override;
UPROPERTY()
TObjectPtr<UAnimMontage> PushingMontage;
UPROPERTY()
TObjectPtr < class UAbilityTask_PlayMontageAndWait > MontageTask;
UPROPERTY()
TObjectPtr < class UAbilityTask_WaitGameplayEvent > EventTask;
UPROPERTY()
TObjectPtr<ACharacter> AvatarCharacter;
float Power;
float ZPower;
bool bIsTraced;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "GA/DDGA_JumpPushingCharacter.h"
#include "DDGA_JumpPushingCharacter.h"
#include "AbilitySystemComponent.h"
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
#include "Abilities/Tasks/AbilityTask_WaitGameplayEvent.h"
#include "Abilities/Tasks/AbilityTask_WaitDelay.h"
#include "GA/AT/DDAT_MultiTrace.h"
#include "GA/TA/DDTA_MultiTrace.h"
#include "Misc/DateTime.h"
#include "DragDown.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
UDDGA_JumpPushingCharacter::UDDGA_JumpPushingCharacter()
{
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
static ConstructorHelpers::FObjectFinder<UAnimMontage> PushingMontageRef(TEXT("/Script/Engine.AnimMontage'/Game/Animation/Montage/AM_Manny_JumpPushingCharacter.AM_Manny_JumpPushingCharacter'"));
if (PushingMontageRef.Succeeded())
{
PushingMontage = PushingMontageRef.Object;
}
bIsTraced = false;
Power = 400.0f;
ZPower = 800.0f;
}
void UDDGA_JumpPushingCharacter::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
bIsTraced = false;
AvatarCharacter = Cast<ACharacter>(ActorInfo->AvatarActor.Get());
// Montage task
MontageTask = UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this,
NAME_None,
PushingMontage, // UAnimMontage* 타입
1.0f, // 플레이 속도
FName("Start"), // Start Section
false // Stop when ability ends
);
MontageTask->OnCompleted.AddDynamic(this, &UDDGA_JumpPushingCharacter::OnMontageCompleted);
MontageTask->ReadyForActivation();
if (AvatarCharacter)
{
AvatarCharacter->LaunchCharacter(FVector(0.0f, 0.0f, 300.0f), false, true);
}
// Wait task
EventTask = UAbilityTask_WaitGameplayEvent::WaitGameplayEvent(
this,
FGameplayTag::RequestGameplayTag(FName("Event.PushTrigger"))
);
EventTask->EventReceived.AddDynamic(this, &UDDGA_JumpPushingCharacter::OnPushingEventReceived);
EventTask->ReadyForActivation();
}
void UDDGA_JumpPushingCharacter::OnMontageCompleted()
{
bool bReplicatedEndAbility = true;
bool bWasCancelled = false;
EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicatedEndAbility, bWasCancelled);
}
void UDDGA_JumpPushingCharacter::OnPushingEventReceived(FGameplayEventData Payload)
{
UDDAT_MultiTrace* TraceTask = UDDAT_MultiTrace::CreateTask(this, ADDTA_MultiTrace::StaticClass());
TraceTask->OnComplete.AddDynamic(this, &UDDGA_JumpPushingCharacter::OnTraceResultCallback);
TraceTask->ReadyForActivation();
}
void UDDGA_JumpPushingCharacter::OnTraceResultCallback(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
if (bIsTraced) return;
bIsTraced = true;
UE_LOG(LogDD, Log, TEXT("OnTraceResultCallback"));
if ( AvatarCharacter )
{
AvatarCharacter->LaunchCharacter(FVector(0.0f, 0.0f, 300.0f), false, true);
}
UAbilitySystemComponent* ASC = CurrentActorInfo->AbilitySystemComponent.Get();
if (ASC)
{
FScopedPredictionWindow ScopedPrediction(ASC, !AvatarCharacter->HasAuthority());
ProcessPush(TargetDataHandle);
}
}
void UDDGA_JumpPushingCharacter::ProcessPush(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
int32 Idx = 0;
while (UAbilitySystemBlueprintLibrary::TargetDataHasHitResult(TargetDataHandle, Idx))
{
ACharacter* Character = nullptr;
FHitResult HitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(TargetDataHandle, Idx);
if (HitResult.GetActor())
{
Character = Cast<ACharacter>(HitResult.GetActor());
}
if (Character)
{
if (AvatarCharacter == nullptr)
{
UE_LOG(LogDD, Log, TEXT("UDDGA_PushingCharacter::ProcessPush - No AvatarCharacter"));
return;
}
FVector LaunchDirection = AvatarCharacter->GetController()->GetControlRotation().Vector(); // 내가 바라보는 방향
FVector LaunchVelocity = LaunchDirection * Power;
LaunchVelocity.Z = 0.0f;
LaunchVelocity.Z += ZPower;
Character->LaunchCharacter(LaunchVelocity, true, true);
}
UE_LOG(LogDD, Log, TEXT("HitResult : %s"), *HitResult.GetActor()->GetName());
++Idx;
}
}
void UDDGA_JumpPushingCharacter::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled)
{
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
bIsTraced = false;
}
void UDDGA_JumpPushingCharacter::CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancel)
{
if (MontageTask && MontageTask->IsActive())
{
MontageTask->EndTask();
}
if (EventTask && EventTask->IsActive())
{
EventTask->EndTask();
}
// for Local Prediction Role Back
bIsTraced = false;
Super::CancelAbility(Handle, ActorInfo, ActivationInfo, bReplicateCancel);
}
외부 컴포넌트는 참조 안하고 간단하게 가자
void UDDGA_PushingCharacter::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
bIsTraced = false;
AvatarCharacter = Cast<ACharacter>(ActorInfo->AvatarActor.Get());
if ( AvatarCharacter )
{
if (AvatarCharacter->GetCharacterMovement()->IsFalling())
{
if (UAbilitySystemComponent* ASC = ActorInfo->AbilitySystemComponent.Get())
{
ASC->TryActivateAbilityByClass(UDDGA_JumpPushingCharacter::StaticClass());
}
bool bReplicatedEndAbility = true;
bool bWasCancelled = false;
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
return;
}
사용은 기본 밀기 어빌리티를 공중에서 쓰면 어빌리티 흐름을 넘기는 방식으로 구현하였다
'언리얼 엔진 > Drag Down (캡스톤 디자인)' 카테고리의 다른 글
[Drag Down] 회피 만들기 (0) | 2025.04.01 |
---|---|
** [Drag Down] RPC In Local Prediction (feat. Root Motion) / (서버->클라이언트 애니메이션 동기화 문제) ** (0) | 2025.03.31 |
** [Drag Down] Local Prediction으로 인한 리슨 서버 이중 처리 문제 with 캐릭터 밀기 물리 처리, 상태 기반 연속 공격 시스템 ** (0) | 2025.03.29 |
** [Drag Down] GAS Prediction 기반 AnimNotify 처리 ** (1) | 2025.03.27 |
** [Drag Down] GAS Local Prediction ** with 밀기 애니메이션 (0) | 2025.03.26 |