Fracture Mode
Fracture Mode
를 이용하면 메시를 파괴가능하게(물리적으로 충돌 발생시 조각내기) 변경할 수 있다.
스태틱 메시를 하나 선택하고, 좌측 상단의Fracture
를 클릭한다.
New를 누르고, 저장할 폴더를 선택 후Create Geometry Collection
을 클릭한다.
이제 우측에서 여러Fracturing
을 진행할 수 있다.
Uniform
을 선택하면 위와 같은 창이 뜨는데,Min Voronoi Sites
와Max Voronoi Sites
로 랜덤하게 최소와 최대의 조각개수를 정해줄 수 있다.
Fracture
을 누르면 메시에 선이 생겨 파괴시 선을 따라 파괴 가능하게 한다.
우측의Fracture Hierarchy
에서 아무부분이나 선택후 다시Fracture
하는 것도 가능하다.
우측의Details
패널에서Simulate Physics
와Enable Gravity
활성화를 확인하고 에셋을 공중에 띄우고 실행하면 떨어지고 파괴되는 것을 확인할 수 있다.
Details
패널에서Show bone Colors
체크를 비활성화하고 실행할 경우 정상적인 메쉬로 출력된다.
FieldSystem
이제 무기를 이용한 파괴가 가능하도록 바꿔야 한다.
먼저 적절하게 폴더를 생성하고FieldSystemActor
를 생성한다.
Physics Field
를 생성하기 위해 노드를 추가한다.
Enable Field
는Physics Field
를 활성화시키는 bool 타입 변수이므로 반드시 활성화 시켜주어야 한다.
Physics Type
은Enum
은 열거형 타입으로 다양한 타입의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 Position
을Get Actor Location
노드를 통해 벡터값을 얻어오고,Field Magnitude
값을 정해주고Field Node
와 연결시킨다.
Field Magnitude
값은 에셋의Damage Threshold
탭에서 최대값 확인후 적절히 값을 할당한다.
마지막으로Set Radial Vector
함수가 파괴가능한 오브젝트에만 적용되도록 수정하기 위해 좌측의Components
패널에서MetaData Filter
를 추가해준다.
우측Details
패널의Field
에서Object Type
을Destruction
으로 변경해주면 된다.
마지막으로 노드를 이어주면 끝.
결과가 기존에 파괴되던것 보다 더 약하게 날라갈 경우, 오브젝트 클릭후 우측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 Type
을Destruction
으로 변경한다.
Radial Falloff
에 대해서BP_SystemField
와 동일하게 구상해주되,Center Position
은 c++ 클래스에서 ImpactPoint를 참조하므로Field Location
과 연결시켜준다.
Radial Vector
도 똑같이 구현해준다.
레벨에 위치한BP_FieldSystem
을 삭제하고,Enable Clustering
을 다시 활성화시켜준 뒤,Generate Overlap Event
를 활성화해준다.
BoxTrace를 쉽게 하기 위해Fracture Mode
에서 생성한 파일을 열고
Collisions 쪽에서Implicit Type
을Capsule
로 변경한다.
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를 사용할 수 있다.
HitInterface
의GetHit
함수에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 Override
를Always 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 class
가BP_Treasure
인 것을 확인할 수 있다.
최상위 부모 블루프린트 클래스임을 알아보기 쉽게BP_Treasure
를BP_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(); } }
컴파일 후 실행하면 더이상 장착시 이펙트 발생이 되지 않는 것을 확인할 수 있다.