해머를 장착한 상태에서 앞으로 Aura를 날리는 스킬을 추가할 것이다. SubAction에 Box 충돌체와 나이아가라 이펙트를 추가하여 스킬이 발동하면 충돌체와 나이아가라 이펙트가 앞으로 나간다. 일섬 스킬과 같이 충돌을 추가하여 데미지를 전달한다.

 

 

목차

     

     


     

     

     
    Plugins
     
      Weapon
     
        Resource
     
          Icon128.png
    weapon_thumbnail_icon.png
     
        Source
     
          Weapon  
          SWeaponCheckBoxes.h .cpp
    SWeaponDetailsView.h .cpp

    SWeaponDoActionData.h .cpp
    SWeaponEquipmentData.h .cpp
    SWeaponHitData.h .cpp

    SWeaponLeftArea.h .cpp
    Weapon.Build.cs
    WeaponAssetEditor.h .cpp
    WeaponAssetFactory.h .cpp
    WeaponCommand.h .cpp 
    WeaponContextMenu.h .cpp
    WeaponModule.h .cpp
    WeaponStyle.h .cpp 
     
       

     

     
    Source
      U2212_06
        Characters
        CAnimInstance.h .cpp
    CEnemy.h .cpp 
    CPlayer.h .cpp
    ICharacter.h .cpp
        Components
        CMontagesComponent.h .cpp 
    CMovementComponent.h .cpp 
    CStateComponent.h .cpp
    CStatusComponent.h .cpp  
    CWeaponComponent.h .cpp 
        Notifies
        CAnimNotifyState_BeginAction.h .cpp 
    CAnimNotify_CameraShake.h .cpp 
    CAnimNotifyState_EndAction.h .cpp
    CAnimNotify_EndState.h .cpp
    CAnimNotifyState.h .cpp
    CAnimNotifyState_CameraAnim.h .cpp
    CAnimNotifyState_Collision.h .cpp 
    CAnimNotifyState_Combo.h .cpp
    CAnimNotifyState_Equip.h .cpp
    CAnimNotifyState_SubAction.h .cpp
        Utilities
        CHelper.h
    CLog.h .cpp
        Weapons
        CAura.h .cpp 생성
    CCamerModifier.h .cpp
    CGhostTrail.h .cpp
    CDoAction_Combo.h .cpp
    CSubAction_Fist.h .cpp
    CSubAction_Hammer.h .cpp
    CSubAction_Sword.h .cpp

    CAttachment.h .cpp
    CDoAction.h .cpp
    CEquipment.h .cpp
    CSubAction.h .cpp
    CWeaponAsset.h .cpp
    CWeaponStructures.h .cpp
        Global.h
    CGameMode.h .cpp
    U2212_06.Build.cs
        U2212_06.uproject
     

     

     

     

     

    해머스킬 구현하기

     

     


     

    Hammer_Skill_Montage 생성

     

    SubAction 할당


     

     

    CAura 생성  &  BP_CAura 생성

     

    새 C++ 클래스 생성 - Actor - CAura 생성 

     

     

    CAura.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "Weapons/CWeaponStructures.h"
    #include "NiagaraDataInterfaceExport.h"
    #include "CAura.generated.h"
    
    UCLASS()
    class U2212_06_API ACAura
    	: public AActor, public INiagaraParticleCallbackHandler
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "Damage")
    		FHitData HitData;
    
    	UPROPERTY(EditDefaultsOnly, Category = "Damage")
    		float DamageInterval = 0.1f;
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UNiagaraComponent* Niagara;
    
    	UPROPERTY(VisibleAnywhere)
    		class UBoxComponent* Box;//나이아가라 충돌체
    
    public:	
    	ACAura();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnSystemFinished(class UNiagaraComponent* PSystem);//Collision을 없애주는 역할의 함수
    
    public:
    	void ReceiveParticleData_Implementation(const TArray<FBasicParticleData>& Data, UNiagaraSystem* NiagaraSystem);
    
    private:
    	TArray<class ACharacter*> Hitted;
    	FTimerHandle TimerHandle;
    };

     

     

     

    CAura.cpp

    더보기
    #include "Weapons/AddOns/CAura.h"
    #include "Global.h"
    #include "NiagaraComponent.h"
    #include "GameFramework/Character.h"
    #include "Components/BoxComponent.h"
    
    ACAura::ACAura()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UNiagaraComponent>(this, &Niagara, "Niagara", Root);
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	UNiagaraSystem* niagara;
    	CHelpers::GetAsset<UNiagaraSystem>(&niagara, "NiagaraSystem'/Game/sA_StylizedSwordSet/Fx/NS_Ulti_lv1.NS_Ulti_lv1'");
    	Niagara->SetAsset(niagara);
    }
    
    void ACAura::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Niagara->SetNiagaraVariableObject("Mesh_Scale", this);//Niagara 안에서 지정한 이름 "Mesh_Scale" 사용.
    	Niagara->OnSystemFinished.AddDynamic(this, &ACAura::OnSystemFinished);
    }
    
    void ACAura::OnSystemFinished(UNiagaraComponent* PSystem)
    {
    	Destroy();//Box Collision 소멸
    }
    
    void ACAura::ReceiveParticleData_Implementation(const TArray<FBasicParticleData>& Data, UNiagaraSystem* NiagaraSystem)
    {
    	CLog::Print(Data[0].Position);
    }

     

     

     

     

     

    ※ 참고) Niagara Component 사용

     

    CAura.cpp에서 위의 코드를 사용하는 부분 캡처

    Spawn된 Box 충돌체를 없애주는 역할의 코드들.

     

     

     

     

    BP_CAura_Hammer

    CAura 기반 블루프린트 클래스 생성 - BP_CAura_Hammer 생성

     

    Damage

    • HitData
      • Montage: HIReaction_Stop_Montage 할당
      • PlayRate, Power, Launch, Stop Time 등등을 기호에 맞게 설정해준다.

     

    Aura.cpp에서 할당한 Niagara System Asset이 할당되어서 들어온다. 따라서 굳이 눌러서 넣어줄 필요가 없다. 


     

     

     

     

    CSubAction_Hammer 

     

    CSubAction_Hammer.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "Weapons/CSubAction.h"
    #include "Weapons/CWeaponStructures.h"
    #include "CSubAction_Hammer.generated.h"
    
    UCLASS(Blueprintable)
    class U2212_06_API UCSubAction_Hammer : public UCSubAction
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "Aura")
    		TSubclassOf<class ACAura> AuraClass;
    
    	UPROPERTY(EditDefaultsOnly, Category = "Aura")
    		FVector AuraLoction;//Aura를 Spawn시킬 위치 변수
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "Action")
    		FDoActionData ActionData;
    
    	UPROPERTY(EditDefaultsOnly, Category = "Add-On")
    		TSubclassOf<class ACGhostTrail> GhostTrailClass;
    
    public:
    	void Pressed() override;
    
    	void Begin_SubAction_Implementation() override;
    	void End_SubAction_Implementation() override;
    
    private:
    	class ACGhostTrail* GhostTrail;
    };

    변수 추가

    • TSubclassOf<class ACAura> AuraClass;
    • FVector AuraLoction;
      • Aura를 Spawn시킬 위치 변수

     

     

     

     

    CSubAction_Hammer.cpp

    더보기
    #include "Weapons/SubActions/CSubAction_Hammer.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    #include "Components/CMovementComponent.h"
    #include "Weapons/CAttachment.h"
    #include "Weapons/CDoAction.h"
    #include "Weapons/AddOns/CGhostTrail.h"
    
    void UCSubAction_Hammer::Pressed()
    {
    	CheckFalse(State->IsIdleMode());
    	CheckTrue(State->IsSubActionMode());
    
    	Super::Pressed();
    
    
    	State->SetActionMode();
    	State->OnSubActionMode();
    
    	GhostTrail = CHelpers::Play_GhostTrail(GhostTrailClass, Owner);
    
    	ActionData.DoAction(Owner);
    }
    
    void UCSubAction_Hammer::Begin_SubAction_Implementation()
    {
    	Super::Begin_SubAction_Implementation();
    
    	FActorSpawnParameters params;
    	params.Owner = Owner;
    	params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;//AlwaysSpawn는 있는없든 무조건 Spawn시키라는 의미.
    
    	FTransform transform;
    	transform.SetLocation(Owner->GetActorLocation());
    	transform.AddToTranslation(AuraLoction);//보정 위치
    	transform.SetRotation(FQuat(Owner->GetActorRotation()));//캐릭터의 전방방향을 캐릭터의 회전방향으로 설정.
    
    	Owner->GetWorld()->SpawnActor<ACAura>(AuraClass, transform, params);	
    }
    
    void UCSubAction_Hammer::End_SubAction_Implementation()
    {
    	Super::End_SubAction_Implementation();
    
    	State->SetIdleMode();
    	State->OffSubActionMode();
    
    	Movement->Move();
    	Movement->DisableFixedCamera();
    
    	if (!!GhostTrail)
    		GhostTrail->Destroy();
    }

    void UCSubAction_Hammer::Begin_SubAction_Implementation()

    • FActorSpawnParameters params;
      params.Owner = Owner;
      params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;//AlwaysSpawn는 있는없든 무조건 Spawn시키라는 의미.

      FTransform transform;
      transform.SetLocation(Owner->GetActorLocation());
      transform.AddToTranslation(AuraLoction);//보정 위치
      transform.SetRotation(FQuat(Owner->GetActorRotation()));//캐릭터의 전방방향을 캐릭터의 회전방향으로 설정.

      Owner->GetWorld()->SpawnActor<ACAura>(AuraClass, transform, params);

     


     

     

     

    BP_CSubAction_Hammer   -  Aura Class 및 위치 할당, 몽타주 할당

     

    BP_CSubAction_Hammer   

    Aura

    • Aura Class: BP_CAura 할당
    • Aura Location: 0.0, 0.0, -90.0 할당
      • 바닥에 붙은 느낌을 주기 위해 보정위치인 Aura Location의 z값을 -90.0으로 설정한다.

    Action

    • Action Data
      • Montage: Hammer_Skill_Montage 할당

     

     

     

    DA_Hammer  -  SubAction Class에 BP_CSubAction_Hammer 할당

     

     


     

     

    실행화면

     

     

     

     


     

     

     

     

     

    나이아가라 충돌체 크기 조절 및 충돌 구현하기

     


     

     

    나이아가라 에셋 수정  -  NS_Ulti_lv1

     

    NS_Ulti_lv1

    NS_Ulti_lv1

     

    시스템 세팅 - Object 추가

     

    이름을 Mesh_Scale로 변경

    - 나이아가라 파티클 매쉬의 Export Particle Data to BlueprintCallback Handler로 이것을 사용하기 때문에 이름을 기억해두어야 한다.

    - CAura.cpp 내의 BeginPlay()에서 SetNiagaraVariableObject("Mesh_Scale")로 데이터를 할당한다. 이 때 Mesh_Scale를 문자열로 기입한다.

     

     

     

     

    파티클 업데이트 - Export Particle Data to Blueprint 추가

    • Condition To Export Data체크
    • Vector to Send (As Struct Position)
      • Link Inputs: 서로 간에 연결해서 입력받는 변수들
      • 동적 입력: 외부에서 여기에다 넣어주는 값
      • 파티클: 
        • 초기: 파티클 Spawn 될 때의 초기값.
        • 초기가 안 붙어있으면 업데이트된 값. ex. 위치 - 위치의 업데이트된 값.
        • PRESOLVE: 처리되기 이전 값.
        • 여기서는 Scale 사용
    • Export Particle Data Interface
      • 익스포트
        • Callback Handler: Mesh_Scale 할당

     

    Scale값이 Mesh_Scale를 통해 외부로 나간다.

     

     

    파티클 크기 확인하기

    • 나이아가라 파티클로 사용한 매쉬를 찾아 열어준다.
    • 대략 크기를 확인한다. 위의 경우 421 x 185 x 291 이다.
    • 이 크기값을 활용해서 Box 충돌체의 크기를 결정한다.
      • BP_CAura_Hammer Box 충돌체의 크기를 x: 210.5, y: 92.5, z:144.5로 설정해준다.

    Spawn 되는 파티클의 크기 '파티클 매쉬의 크기 x Scale' 이다. 

     

     

     

     

     

     

    블루프린트 예시 - 다음 블루프린트를 코드로 구현할 것이다.


     

     

    BP_CAura_Hammer  -  Box 충돌체 크기 변경하기 

     

    BP_CAura_Hammer  

    Box

    • Shape
      • Box Extent:  210.0, 92.5, 145.5
      • Spawn 되는 Box의 크기는  '파티클 매쉬의 크기 x Scale' 이다.  =  Spawn 되는 파티클의 크기는 '파티클 매쉬의 크기 x Scale' 이다. 

     


     

     

    CAura 코드 추가

     

     

    CAura.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "Weapons/CWeaponStructures.h"
    #include "NiagaraDataInterfaceExport.h"
    #include "CAura.generated.h"
    
    UCLASS()
    class U2212_06_API ACAura
    	: public AActor, public INiagaraParticleCallbackHandler
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "Damage")
    		FHitData HitData;
    
    	UPROPERTY(EditDefaultsOnly, Category = "Damage")
    		float DamageInterval = 0.1f;
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USceneComponent* Root;
    
    	UPROPERTY(VisibleAnywhere)
    		class UNiagaraComponent* Niagara;
    
    	UPROPERTY(VisibleAnywhere)
    		class UBoxComponent* Box;//나이아가라 Box 충돌체
    
    public:	
    	ACAura();
    
    protected:
    	virtual void BeginPlay() override;
    
    private:
    	UFUNCTION()
    		void OnSystemFinished(class UNiagaraComponent* PSystem);//Collision을 없애주는 역할의 함수
    private:
    	//충돌 이벤트 2개
    	UFUNCTION()
    		void OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
    
    	UFUNCTION()
    		void OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
    
    public:
    	void ReceiveParticleData_Implementation(const TArray<FBasicParticleData>& Data, UNiagaraSystem* NiagaraSystem);
    
    private:
    	TArray<class ACharacter*> Hitted;//Hitted되는 목록
    	FTimerHandle TimerHandle;//Hitted 목록을 TimberHandle을 이용해서 데미지를 주기 위해 사용하는 변수
    };

    부모 클래스 추가

    • public INiagaraParticleCallbackHandler
      • void ReceiveParticleData_Implementation 사용을 위해 추가한다.

     

     

     

     

    CAura.cpp

    더보기
    #include "Weapons/AddOns/CAura.h"
    #include "Global.h"
    #include "NiagaraComponent.h"
    #include "GameFramework/Character.h"
    #include "Components/BoxComponent.h"
    
    ACAura::ACAura()
    {
    	CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
    	CHelpers::CreateComponent<UNiagaraComponent>(this, &Niagara, "Niagara", Root);
    	CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
    
    	UNiagaraSystem* niagara;
    	CHelpers::GetAsset<UNiagaraSystem>(&niagara, "NiagaraSystem'/Game/sA_StylizedSwordSet/Fx/NS_Ulti_lv1.NS_Ulti_lv1'");//나이아가라 에셋 할당.
    	Niagara->SetAsset(niagara);
    }
    
    void ACAura::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Niagara->SetNiagaraVariableObject("Mesh_Scale", this);//Niagara 안에서 지정한 이름 "Mesh_Scale" 사용.
    	Niagara->OnSystemFinished.AddDynamic(this, &ACAura::OnSystemFinished);
    
    	Box->OnComponentBeginOverlap.AddDynamic(this, &ACAura::OnComponentBeginOverlap);
    	Box->OnComponentEndOverlap.AddDynamic(this, &ACAura::OnComponentEndOverlap);
    
    	//타이머 설정. 일정시간 동안 Damage를 준다. 
    	FTimerDelegate delegate = FTimerDelegate::CreateLambda([&]()
    		{
    			for (int32 i = Hitted.Num() - 1; i >= 0; i--)
    				HitData.SendDamage(Cast<ACharacter>(GetOwner()), this, Hitted[i]);
    		});
    
    	GetWorld()->GetTimerManager().SetTimer(TimerHandle, delegate, DamageInterval, true, 0);
    }
    
    void ACAura::OnSystemFinished(UNiagaraComponent* PSystem)
    {
    	GetWorld()->GetTimerManager().ClearTimer(TimerHandle);//끝날 때 TimerHandle 제거
    
    	Destroy();//Box 충돌체 소멸
    }
    
    void ACAura::ReceiveParticleData_Implementation(const TArray<FBasicParticleData>& Data, UNiagaraSystem* NiagaraSystem)
    {
    	Box->SetRelativeScale3D(Data[0].Position);
    
    
    	FVector location = Box->GetScaledBoxExtent();
    	location.Y = 0;//Y=0을 만든 이유는? 캐릭터 기준에서 기준선에 맞추기 위해서이다. 캐릭터 중앙 기준은 Y=0이다.
    
    	CLog::Log(location);
    
    	Box->SetRelativeLocation(location);
    }
    
    void ACAura::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
    {
    	CheckTrue(GetOwner() == OtherActor);
    
    	ACharacter* character = Cast<ACharacter>(OtherActor);
    	if (!!character)
    		Hitted.AddUnique(character);
    }
    
    void ACAura::OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
    {
    	CheckTrue(GetOwner() == OtherActor);
    
    	ACharacter* character = Cast<ACharacter>(OtherActor);
    	if (!!character)
    		Hitted.Remove(character);
    }

    함수 재정의

    • void ReceiveParticleData_Implementation(const TArray<FBasicParticleData>& Data, UNiagaraSystem* NiagaraSystem);
      • _Implementation을 붙여 NiagaraDataInterfaceExport.h 내의 void ReceiveParticleData() 함수를 재정의한다.

     

     

     

     

    ※참고: NiagaraDataInterfaceExport.h 내의 void ReceiveParticleData(const TArray<FBasicParticleData>& Data, UNiagaraSystem* NiagaraSystem)

     


     

     

    location.Y = 0 이 적용 전

     

    void ACAura::ReceiveParticleData_Implementation에서 location.Y = 0 적용 전

    • 캐릭터 중앙 기준이 아닌 y: 92.5값이 적용된다.

     

     


     

     

     

    실행화면