Destructible Meshes(Fracture)

groot616·2024년 4월 21일
1

언리얼5공부복습용

목록 보기
16/22

Fracture Mode

Fracture Mode 를 이용하면 메시를 파괴가능하게(물리적으로 충돌 발생시 조각내기) 변경할 수 있다.
스태틱 메시를 하나 선택하고, 좌측 상단의 Fracture 를 클릭한다.
New를 누르고, 저장할 폴더를 선택 후 Create Geometry Collection 을 클릭한다.
이제 우측에서 여러 Fracturing 을 진행할 수 있다.
Uniform 을 선택하면 위와 같은 창이 뜨는데, Min Voronoi SitesMax Voronoi Sites 로 랜덤하게 최소와 최대의 조각개수를 정해줄 수 있다.
Fracture 을 누르면 메시에 선이 생겨 파괴시 선을 따라 파괴 가능하게 한다.

우측의 Fracture Hierarchy 에서 아무부분이나 선택후 다시 Fracture 하는 것도 가능하다.

우측의 Details 패널에서 Simulate PhysicsEnable Gravity 활성화를 확인하고 에셋을 공중에 띄우고 실행하면 떨어지고 파괴되는 것을 확인할 수 있다.
Details 패널에서 Show bone Colors 체크를 비활성화하고 실행할 경우 정상적인 메쉬로 출력된다.

FieldSystem

이제 무기를 이용한 파괴가 가능하도록 바꿔야 한다.
먼저 적절하게 폴더를 생성하고 FieldSystemActor 를 생성한다.
Physics Field 를 생성하기 위해 노드를 추가한다.
Enable FieldPhysics Field 를 활성화시키는 bool 타입 변수이므로 반드시 활성화 시켜주어야 한다.
Physics TypeEnum 은 열거형 타입으로 다양한 타입의 Physics Field 상수를 가지고 있다.
우선 필요한 것은 외부의 힘에 의한 파괴이므로 External Strain 을 선택한다.
이제 어디에 어느정도의 힘을 가해야하는지와 같은 정보가 있어야 파괴가능하게 만들 수 있다.
중심에서 멀어질수록 힘이 점점 약해지는 Radial Falloff 를 사용할 것이다.
우측의 Components 패널에서 Radial Falloff 를 추가해 준다.
노드를 추가해주고, Set Radial Falloff 함수 노드를 호출해준다.

  • Field Magnitude
    해당 Physics Field 가 가하는 물리적인 힘의 크기(자기장과 같이 중심에서 바깥으로 힘이 가해진다는 느낌)
  • Min/Max Range
    Field Magnitude에 최종적으로 곱을 통해 장의 크기를 정해주는 parameter인 것 같음.
  • Default Value
    Field의 반경보다 멀리 있을 경우 Field Magnitude 의 기본값을 설정하
  • Sphere Radius
    Field의 반지름
  • Center Position
    장의 Center 위치
  • Falloff Type
    장의 type. 선형적, 제곱, 로그 등 적용 가능
    컴파일후 파괴 가능한 물건 옆에 배치하면 파괴되는 것을 확인할 수 있다.


    좀더 디테일하게 표현하기 위해 부서진 파편이 땅에 떨어지는것 뿐만 아니라 날라가는 것까지 표현할 수 있다.
    똑같이 Add Transient Field 노드를 추가해주고
    우측의 Components 패널에서 Radial Vector 를 추가하고, Set Raidal Vector 함수를 호출해준다.
    Center PositionGet Actor Location 노드를 통해 벡터값을 얻어오고, Field Magnitude 값을 정해주고 Field Node 와 연결시킨다.
    Field Magnitude 값은 에셋의 Damage Threshold 탭에서 최대값 확인후 적절히 값을 할당한다.
    마지막으로 Set Radial Vector 함수가 파괴가능한 오브젝트에만 적용되도록 수정하기 위해 좌측의 Components 패널에서 MetaData Filter 를 추가해준다.
    우측 Details 패널의 Field 에서 Object TypeDestruction 으로 변경해주면 된다.
    마지막으로 노드를 이어주면 끝.


    결과가 기존에 파괴되던것 보다 더 약하게 날라갈 경우, 오브젝트 클릭후 우측 Details 패널에서 Enable Clustering 비활성화시키면 해결 가능. 다만 이때 BP_FieldSystem 에서 Field Magnitude 값을 적절히 변경시켜줘야함.

무기에 적용

Blueprint로 구현하는 것이 편리하므로 Weapon클래스에서 선언과 필요한 값들만 const 참조를 통해 받고, Blueprint로 구현한다.

  • Weapon.h
// Weapon.h
protected:
...
	UFUNCTION(BlueprintImplementableEvent)
	void CreateFields(const FVector& FieldLocation);
...

BoxTrace에 의해 충돌 판별시 CreateFields를 호출하도록 한다.

  • Weapon.cpp
// Weapon.cpp
void AWeapon::OnBoxOverlap(...)
{
	...
    if(CollisionBoxHit.GetActor())
    {
    	...
        CreateFields(CollisionBoxHit.ImpactPoint);
    }
}
  • BP_Weapon
    먼저 cpp 클래스에서 생성한 Event Create Field 노드를 추가해준다.
    BP_FieldSystem 과 동일하게 좌측의 Components 패널에서 Field System , Radial Falloff , Radial Vector , Meta Data Filter 를 추가해준다.
    Meta Data Filter 를 클릭하고 우측의 Details 패널에서 Object TypeDestruction 으로 변경한다.
    Radial Falloff 에 대해서 BP_SystemField 와 동일하게 구상해주되, Center Position 은 c++ 클래스에서 ImpactPoint를 참조하므로 Field Location 과 연결시켜준다.
    Radial Vector 도 똑같이 구현해준다.
    레벨에 위치한 BP_FieldSystem 을 삭제하고, Enable Clustering 을 다시 활성화시켜준 뒤, Generate Overlap Event 를 활성화해준다.
    BoxTrace를 쉽게 하기 위해 Fracture Mode 에서 생성한 파일을 열고
    Collisions 쪽에서 Implicit TypeCapsule 로 변경한다.
    Hit Event가 발생하는지 확인하기 위해 DrawDebugSphere 노드를 추가해주고 확인한다.
    Enable Clustering 을 활성화했으므로 Field Magnitude 값을 다시 적절히 조정해서 공격하면 물체가 파괴되는 것을 확인할 수 있다.

Actor Class로 파괴가능한 오브젝트 생성

필요한 것은 Actor이므로 Actor class를 생성한다.

  • BreakableActor.h
// BreakableActor.h
...
class UGeometryCollecitonComponent;
...
private:
	UPROPERTY(VisibleAnywhere)
	UGeometryCollectionComponent* GeometryCollection;
    ...
  • BreakableActor.cpp
// BreakableActor.cpp
...
#include "GeometryCollection/GeometryCollectionComponent.h"
void ABreakableActor::ABreakableActor()
{
	// Tick 필요없으므로 false로 변경
	PrivaryActorTic.bCanEverTick = false;	
	GeometryCollection = CreateDefaultSubobject<UGeometryCollectionComponent>(TEXT("GeometryCollection"));
    SetRootCommponent(GeometryCollection);
    // Collision Preset
    GeometryCollection->SetGenerateOverlapEvents(true);
}
  • Study.Build.cs
// Study.Build.cs
...
public class Study : ModuleRules
{
	public Study(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "GeometryCollectionEngine" });
        ...
    }
}

BreakableActor 기반 블루프린트 클래스를 생성한다.
우측의 Rest Collection 에 사용할 Geometry Collection 을 넣어주면 된다.
카메라와의 collision을 없애기 위해 코드를 추가한다.

  • Breakable.cpp
// Breakable.cpp
ABreakable::ABreakable()
{
	...
    GeometryCollection->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
}

Breakable도 Interface를 사용할 수 있다.
HitInterfaceGetHit 함수에 UFUNCTION(BlueprintNativeEvent) 매크로를 사용하여 코드에 구현한 기능과 블루프린트에서 추가한 기능 둘다 사용할 수 있도록 변경할수도 있다.

  • BlueprintCallable
    블루프린트에서 c++로 구현한 기능 호출만 가능
  • BlueprintImplementableEvent
    코드상에서 선언만 하고 블루프린트에서 구현
  • BlueprintNativeEvent
    c++에서 구현한 기능과 블루프린트에서 override 가능함


    먼저 HitInterface.h 에 UFUNCTION 매크로를 추가해준다.
  • HitInterface.h
// HitInterface.h
...
public:
	UFUNCTION(BlueprintNativeEvent)
    void GetHit(const FVector& ImpactPoint);

다른 부분에서 override할 수 있도록 코드를 수정해준다.

  • Enemy.h
// Enemy.h
// Enemy.cpp 에서도 void AEnemy::GetHit_Implementation(...)로 수정
...
public:
	...
    virtual void GetHit_Implementation(const FVector& ImpactPoint) override;
    ...
}
  • Weapon.cpp
// Weapon.h
...
void AWeapon::OnBoxBeginOverlap(...)
{
	...
    if(CollisionBoxHit.GetAtor())
    {
    	...
        if(HitInterface)
        {
        	HitInterface->Execute_GetHit(CollisionHitBox.GetActor(), CollisionBoxHit.ImpactPoint);
        }
        ...
    }
}
...

Breakable.h에서도 interface를 사용하도록 수정

  • Breakable.h
// Breakable.h
...
#include "Interfaces/HitInterface.h"
...
UCLASS()
class STUDY_API ABreakable : public AActor, public IHitInterface
{
	...
    public:
    virtual void GetHit_Implementation(const FVector& ImpacePoint) override;
	...
}

BP_Breakable 에서 Event Get Hit 노드를 생성할 수 있고, 우클릭후 Add Call to Parent Function을 이용하면 c++ 버전도 호출 가능하다.

사운드 추가

필요한 사운드 에셋을 import 하고 Meta Sound 를 생성한다.
BP_Breakable 에서 Play Sound at Location 노드를 추가해주고 방금 생성한 SFX_PotBreak 를 넣어주면 파괴시 사운드가 재생된다.
일반적으로 게임에서 파괴된 오브젝트는 일정시간이 지난 뒤 사라진다. Set Life Span 노드를 추가해 구현해준다.


파괴 가능한 오브젝트를 여러개 배치하고 하나만 파괴했을 때, 연쇄작용으로 근처의 오브젝트들 또한 파괴될 수 있다. 하지만 GetHit에 의한 파괴만 사라지고 연쇄작용으로 인해 파괴된 오브젝트는 사라지지 않는다.
이를 해결하기 위해 우측의 Details 패널에서 On Chaos Break Event 에 있는 +를 눌러 Event노드를 추가한다.
위에 있는 Set Life Span 노드를 연결시켜준 뒤
우측 Details 패널에서 Notify Breaks 를 활성화시켜주고 실행하면 연쇄적으로 파괴된 오브젝트들도 같이 사라지는 것을 확인할 수 있다.

파괴시 아이템 스폰

항아리 파괴시 아이템이 스폰되는 것을 구현한다.
먼저 필요한 에셋들을 다운받아 import 한다
보물 에셋은 Epic Games의 무료마켓에서 받고, 사운드의 경우 Soundimage 여기에서 적당한 것을 다운한다.
사용할 Meta Sound 를 미리 생성해준다.
Item.cpp에서 파생된 Treasure 클래스를 생성한다.

  • Treasure.h
// Treasure.h
...
protected:
	virtual void OnSphereBeginOverlap(UPrimitiveComponent* OverlappedComponent, 
    AActor* OtherActor, 
    UPrimitiveComponent* OtherComp, 
    int32 OtherBodyIndex, 
    bool bFromSweep, 
    const FHitResult& SweepResult) override;
...
private:
	UPROPERTY(EditAnywhere, Category = "Sound")
	USoundBase* PickupSound;
...
  • Treasure.cpp
// Treausre.cpp
...
#include "Characters/WraithCharacter.h"
...
void ATreasure::OnSphereBeginOverlap(...)
{
	// 부모버전의 OnSphereBeginOverlap을 사용하지 않을 것이므로 Super사용x
    AWraithCharacter* WraithCharacter = Cast<AWraithCharacter>(OtherActor);
    if(WraithCharacter)
    {
    	if(PickupSound)
        {
    		UGameplayStatics::PlaySoundAtLocation(this, PickupSound, GetActorLocation());
        }
        // Treasure pickup시 파괴
    	Destroy();
    }
}

Treausre.cpp 기반 블루프린트를 생성한다.
Satic Mesh 를 할당해주고
생성해둔 SFX_Treasure 를 넣어준다.
우선 정상적으로 작동하는지 확인하기 위해 월드에 BP_Treasure 를 배치하고 실행시켜본다.

Blueprint를 이용한 구현

정상적으로 작동된다면 다시 돌아가서 Spawn Actor from Class 노드를 추가해주고, spawn 대상을 방금 만든 BP_Treausre , Collision Handling OverrideAlways Spawn, Ignore Collisions 로 설정한다.

  • Always Spawn, Ignore Collisions
    액터를 생성하고, 충돌을 항상 무시한다. 생성된 액터는 충돌을 감지하지 않고 그자리에 생성된다.
  • Try to Adjust Location, But Always Spawn
    충돌이 발생하면 충돌을 피하기 위해 액터의 위치를 조정하려고 시도하지만, 불가능한 경우에도 액터를 생성한다.
  • Try to Adjust Location, Don't Spawn if Still Colliding
    충돌이 발생하면 충돌을 피하기 위해 액터의 위치를 조정하려고 시도하고, 불가능한 경우 액터를 생성하지 않는다.
  • Do Not Spawn
    액터를 생성하지 않는다.


    BP_Treasure 의 mesh가 충돌하지 않게 해야하므로 Collision 관련 설정을 변경한다.


    추가로 영상과 다르게 무한루프 오류가 발생할 수도 있다. 무언가를 파괴한 상태에서 또다시 파괴하려고 시도하는 경우 무한루프에 빠진다는것 같다.
    이를 해결하기 위해 bool type 변수를 추가해주고 기본값을 false로 설정해준다.
    GetHit event 발생시 bBroken값을 참조하여 이미 파괴된 상태인 경우 return, 그렇지 않은 경우 bBroken값을 true로 변경한 뒤 spawn되도록 변경한다.
    실행하면 정상적으로 작동하는 것을 확인할 수 있다.
    BP_Treasure 의 위치를 조금 조정해주면 좀더 깔끔하게 작동되는 것을 확인할 수 있다.
    Make Transform 노드를 이용하는 방법도 있다.

c++를 이용한 구현

BP_Treasure 에서 Static Mesh 를 설정하였으므로 c++에서는 이에 대한 정보가 없다.
c++에 기반한 spawn이 아닌 블루프린트에 기반한 spawn이 필요하다.
SpawnActor 의 경우 템플릿 함수이고 <> 에 따라 어떤 c++ 클래스가 spawn될지 정해진다.
SpawnActor 의 parameter에 UClass* 타입의 parameter가 있는데 이는 <> 와 동일한 역할을 한다. 이를 통해 블루프린트 클래스를 이용할 수 있다.
먼저 UClass* 타입의 변수를 하나 생성한다.

  • Breakable.h
// Breakable.h
private:
	// 블루프린트에서 사용할 클래스
	UPROPERTY(EditAnywhere)
    UClass* TreasureClass;
    // 무한루프 방지용
    bool bBroken = false;
...
  • Breakable.cpp
// Breakable.cpp
...
#include"Items/Treasure.h"
...
void ABreakableActor::GetHit_Implementation(const FVector& ImpactPoint)
{
	if(bBroken) return;
	bBroken = true;
	UWorld* World = GetWorld()
    if(World && TreasureClass)
    {
    	FVector Location = GetActorLocation();
        Location.Z -= 40.f;
    	World->spawnActor<ATreasure>(TreasureClass, Location, GetActorRotation());
    }
}

BP_Breakabel 에서 Treasure Class 를 선택하고 실행하면 정상적으로 동작되는 것을 확인할 수 있다.
<추가>
Trasure Class 에 BP_Treasrue를 찾기엔 너무 많을 경우 TSubclassOf<> 사용시 <> 내부에 있는 것들만 표시되게 할 수 있다.

  • Breakable.h
// Breakable.h
private:
	...
    // 전방선언 해도 되고 <>안에 class 사용해도 가능
    UPROPETY(EditAnywhere)
    TSubclassOf<class ATreasure> TreasureClass;
    ...

컴파일 후 확인해보면 Treasure 관련한 것들만 나타나는 것을 확인할 수 있다.


이제 파괴시 파변들에 충돌이 발생하는 불편함을 해결해야 한다.
단순히 Static Mesh 가 캐릭터와의 충돌을 무시하게 하면, 파괴전에도 캐릭터와의 충돌을 무시하게 되므로 Capsule Component 를 이용해 파괴전엔 충돌가능하도록 해야한다.

  • Breakable.h
// Breakable.h
...
class UCapsuleComponent;
...
private:
	...
    // 충돌을 위한 capsule component
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	UCapsuleComponent* Capsule;
  • Breakable.cpp
// Breakable.cpp
...
#include "Components/CapsuleComponent.h"
...
ABreakable::ABreakable()
{
	...
    Capsule = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule"));
    Capsule->SetupAttachment(GetRootComponent());
    Capsule->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
    Capsule->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Block);
}

캡슐의 크기를 적당히 조절해준다.
마지막으로 파괴 이벤트 발생 이후 Capsule의 Collision에서 pawn을 무시하도록 하면 된다.
간혹 카메라가 파편때문에 돌아가는 경우 카메라도 동일하게 설정해주면 된다.

다양한 아이템 spawn

항아리 파괴시, 여러 아이템들이 나오도록 하고, 가치에 따라 골드량을 표시한다.
먼저 아이템별 골드 가치를 저장하기 위한 변수를 하나 선언한다.

  • Treasure.h
// Treasure.h
...
private:
	...
	// Treasure 종류에 따른 골드가치
	UPROPERTY(EditAnywhere, Category = "Treasure Properties")
    int32 Gold;
	...

BP_Treausre 에서 Gold값을 지정해주고
실제 게임처럼 보이도록, yaw 축 기준으로 회전하도록 만든다.
BP_Treasure 우클릭후 Child Blueprint Class 를 생성해준다.
우측을 보면 Parent classBP_Treasure 인 것을 확인할 수 있다.
최상위 부모 블루프린트 클래스임을 알아보기 쉽게 BP_TreasureBP_BaseTreasure 로 변경하고, 필요한 만큼 자식클래스를 생성한다.


TArray를 사용하여 랜덤한 Treasure를 파괴시 얻을 수 있도록 코드를 작성한다.

  • Breakable.h
// Breakable.h
private:
	...
    UPROPERTY(EditAnywhere, Category = "Breakable Properties")
    TArray<TSubclassOf<class ATreasure>> TreasureClasses;
    // 삭제
    // TSubclassOf<class ATreasure> TreasureClass;
...
  • Breakable.cpp
// Breakable.cpp
void ABreakable::GetHit_Implementation(const FVector& ImpactPoint)
{
	UWorld* World = GetWorld();
    // TreasureClass => TreasureClasses.Num() > 0 으로 변경
    if(World && TreasureClasses.Num() > 0)
    {
    	FVector Location = GetActorLocation();
        Location.Z -= 40.f;
        const int32 Selection = FMath::RandRange(0, TreasureClasees.Num() - 1);
        World->SpawnActor<ATreasure>(TreasureClasses[Selection], Location, GetActorRotation());
    }
}

컴파일 후 BP_Breakable 에서 스폰할 블루프린트 클래스들을 넣어준다.
실행시 랜덤한 아이템들이 스폰되는것을 확인할 수 있다.

다양한 파괴가능 오브젝트 생성

다양한 BP_Treasure 를 생성한것과 같이 다양한 BP_Breakable 을 생성하는 것도 가능하다.
동일하게 Fracture mode 에서 파괴가능하도록 설정하고, BP_Treasrue 의 자식 블루프린트 클래스를 생성한 뒤, 메쉬와 Geometry collection을 할당해주면 된다.
Fracture mode 를 통해 파괴시 파편이 나뉘도록 설정해주고
Geometry Collection 도 생성해주고
기본 BP_Breakable->BP_BaseBreakable로 변경후 자식 블루프린트 클래스인 BP_PotMedium 생성
BP_PotMedium 에서 Geometry Collection 할당
미디엄 사이즈의 항아리이므로, 큰 아이템들은 스폰되지 않도록 제외시킨다.

Niagara Systems

우클릭후 Niagara System 을 클릭하면 생성할 수 있다.
New System from selected emitter(s) 를 선택한다.

  • New System from selected emitter(s)
    사용 가능한 이미터 목록이 표시되고, 프로젝트에 있는 기존 이미터와 템플릿 이미터가 모두 포함되어 있음. 신규 시스템에 포함할 이미터를 선택하고 +를 눌러 추가가능. 기존 이미터를 선택하면 시스템은 이 이미터롭부터 상속되나, 템플릿 이미터를 선택하면 시스템은 상속받지 않음.
  • New system from a template or behavior example
    여러 이펙트 시스템이 있는 템플릿 목록에서 선택 가능하며 아트 책임자나 크리에이티브 디렉터가 조정할 수 있음. 해당 옵션은 niagara에서 FX시스템이 어떻게 제작되는지에 대한 샘플을 제공.
  • Coopy existing system
    기존 시스템 목록이 표시되고, 선택후 Finish를 선택하여 사용 가능
  • Create empty system
    빈 프로젝트 생성
    필요한 emitter 를 선택하고 +를 누른다. 모두 선택했다면 Finish 를 누른다.
  • 시스템
    왼쪽 노드는 시스템 노드를 의미. Niagara System 은 이펙트 빌드에 필요한 모든 요소가 담긴 컨테이너이다. 시스템에서 다양한 빌딩 블록을 쌓아 전체적인 이펙트를 만들 수 있음. 시스템 단계의 행동을 수정한 뒤, 이펙트에 속하는 모든 요소에 적용할 수 있음.
  • 이미터
    Niagara System 에서 파티클이 생성되는 노드. 파티클의 생성 방식, 시간 경과에 따라 파티클에서 발생하는 현상, 파티클의 외관 및 행동을 제어. 이미터는 스택으로 구성되는데, 스택은 여러 그룹이 있고, 그룹 내에 개별 동작을 수행하는 모듈을 추가할 수 있음.
    상세한 건 Niagara System API 참조
    Spawn Rate 를 선택하고 적절하게 조절한다.
    Particle Spawn 을 선택하고 필요에 따라 적절하게 값들을 조절한다.
    Shape Location 을 선택하고 값을 적절하게 조절한다.
    Add Velocity 를 선택하고 입자들이 날라다니지 않도록 속도를 조절하고 Cone Angle 을 늘려서 더 넓은 원뿔 모양이 되도록 한다.
    Particle Update 는 파티클 시뮬레이션이 계속되는 동안 각 파티클에 적용되는 것들인데 여기에 있는 Gravity Force 체크를 해제하면 게임에서 아이템이 젠되었을 때 보이는 이펙트를 만들 수 있다.
    Drag 의 값을 설정하면 파티클 입자가 공기저항에 의해 감속되는 정도를 설정 가능하다.
    Scale Color 는 색 조정이 가능하다.
    그외에도 Particle Update 옆의 + 를 통해 필요한 것들을 추가할 수 있다. Vortex Velocity 를 추가하고, 파티클에 소용돌이를 추가함과 동시에 속도를 증감시켜 파티클이 소용돌이처럼 회전하도록 만들 수도 있다.
    월드에 생성한 Niagara System 을 드래그에서 배치시키면 인게임에서 어떻게 적용되는지 확인할 수 있다.


    이제 생성한 Niagara System 을 여러곳에 적용시킬 수 있다.

Blueprint에서 적용방법

BP_Item 파일을 열고, 우측의 Components 패널에서 Add 를 누른 뒤 Niagara Particle System Component 를 검색하여 추가한다.
우측의 Details 패널에서 Niagara System Asset 탭에 생성한 Niagara System 을 적용시키고 컴파일하면 끝.

c++에서 적용방법

Niagara Component 를 사용하기 위해서는 Build 파일에 나이아가라 모듈을 포함시켜야 한다.

  • Study.Build.cs
// Study.Build.cs
...
	PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "GeometryCollectionEngine", "Niagara"});
...
  • Item.h
// Item.h
...
class UNiagaraCVomponent;
...
protected:
	// 무기에 장착한 나이아가라 이펙트
    // 상속된 클래스에서도 사용가능해야함
	UPROPERTY(EditAnywhere)
    UNiagaraComponent* EmbersEffect;
...
  • Item.cpp
// Item.cpp
...
#include "NiagaraComponent.h"
...
AItem::AItem()
{
	...
    EmbersEffect = CreateDefaultSubobject<UNiagaraComponent>(TEXT("EmbersEffect"));
    EmbersEffect->SetupAttachment(GetRootComponent());
}

컴파일 후 실행시 Components 패널에 Embers Effect 가 추가된 것을 확인할 수 있다.
클릭 후 우측의 Details 패널에서 나이아가라 시스템 에셋을 넣고 실행하면 정상적으로 동작하는 것을 확인할 수 있다.
BP_BaseTreasure 에 적용시 모든 보물들에게 Niagara System이 적용된 것을 확인할 수 있다.


무기에 Niagara System을 적용시키면 무기를 주워도 이펙트가 계속 발생되는 문제점이 생겨 이를 해결해야 한다.

  • Weapon.cpp
// Weapon.cpp
...
#include "NiagaraComponent.h"
...
void AWeapon::EquipWeapon()
{
	...
    if(EmbersEffect)
    {
    	EmbersEffect->Deactivate();
    }
}

컴파일 후 실행하면 더이상 장착시 이펙트 발생이 되지 않는 것을 확인할 수 있다.

0개의 댓글