티스토리 뷰
언리얼엔진4를 이용한 1인 RPG게임 개발중 대쉬 스킬을 표현하기 위해 구현한 고스트 트레일 입니다.
트레일에 상용될 메터리얼과 그 메터리얼에 값 변경 파라미터 이름, 투명도 커브 데이터를 넣어 주면 초기 설정은 끝이 됩니다.
실제 사용은 애니메이션 노티파이로 이벤트를 받아서 고스트 트레일 액터를 생성하는 방식으로 처리 하였습니다.
투명도 커브의 시간이 끝이되면 자동으로 Destroy 되는데요 Actor의 생성과 파괴가 부담스럽다면 Object pool 을 만들어 관리하면 될 듯 합니다.
<GhostTrail.h>
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "GameFramework/Character.h" #include "Components/TimelineComponent.h" #include "GhostTrail.generated.h" class UPoseableMeshComponent; class UMaterialInterface; class UMaterialInstanceDynamic; UCLASS() class PROJECTA_API AGhostTrail : public AActor { GENERATED_BODY() public : /** Ghost trail material */ UPROPERTY(EditDefaultsOnly, Category = "Material") UMaterialInterface* GhostTrailMaterial; /** Ghost trail fade opacity parameter name */ UPROPERTY(EditDefaultsOnly, Category = "Opacity") FName ScalarParameterName = FName(TEXT("Opacity")); /** Ghost trail mesh opacity curve */ UPROPERTY(EditDefaultsOnly, Category = "Opacity") UCurveFloat* OpacityCurve; /** Ghost trail pose character */ UPROPERTY(BlueprintReadWrite, Category = "Character", meta = (ExposeOnSpawn = "true")) ACharacter* CharacterRef; /** BeginPlay starts automatically */ UPROPERTY(EditDefaultsOnly, Category = "Trail Activation") bool bAutoActive; protected: /** Ghost trail mesh */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Mesh") UPoseableMeshComponent* PoseableMeshComp; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Default") USceneComponent* SceneRootComp; /** Ghost trail mesh opacity timeline */ UPROPERTY() FTimeline OpacityTimeline; /** Ghost trail dynamic material */ UPROPERTY() UMaterialInstanceDynamic* DynamicMatInstance; public: AGhostTrail(); protected: virtual void BeginPlay() override; public: virtual void Tick(float DeltaTime) override; UFUNCTION(BlueprintCallable, Category = "GhostTrail") void BeginGhostTrailEffect(); protected: UFUNCTION() void HandleTimelineUpdate(float Value); UFUNCTION() void HandleTimelineFinished(); }; | cs |
<GhostTrail.cpp>
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | #include "GhostTrail.h" #include "Components/PoseableMeshComponent.h" #include "Components/SkeletalMeshComponent.h" #include "Materials/MaterialInstanceDynamic.h" AGhostTrail::AGhostTrail() { PrimaryActorTick.bCanEverTick = true; bAutoActive = true; SceneRootComp = CreateDefaultSubobject<USceneComponent>(TEXT("RootComp")); RootComponent = SceneRootComp; PoseableMeshComp = CreateDefaultSubobject<UPoseableMeshComponent>(TEXT("PoseableMeshComp")); PoseableMeshComp->SetupAttachment(RootComponent); } void AGhostTrail::BeginPlay() { Super::BeginPlay(); if(bAutoActive) BeginGhostTrailEffect(); } void AGhostTrail::Tick(float DeltaTime) { Super::Tick(DeltaTime); OpacityTimeline.TickTimeline(DeltaTime); } void AGhostTrail::BeginGhostTrailEffect() { if (OpacityCurve && CharacterRef && GhostTrailMaterial) { PoseableMeshComp->SetSkeletalMesh(CharacterRef->GetMesh()->SkeletalMesh); PoseableMeshComp->CopyPoseFromSkeletalComponent(CharacterRef->GetMesh()); DynamicMatInstance = UMaterialInstanceDynamic::Create(GhostTrailMaterial, this); TArray <FSkeletalMaterial> materials = CharacterRef->GetMesh()->SkeletalMesh->Materials; for (int32 Index = 0; Index != materials.Num(); ++Index) { PoseableMeshComp->SetMaterial(Index, DynamicMatInstance); } FOnTimelineFloat TimelineUpdateCallback; FOnTimelineEventStatic TimelineFinishedCallback; OpacityTimeline.SetLooping(false); TimelineUpdateCallback.BindUFunction(this, FName{ TEXT("HandleTimelineUpdate" })); TimelineFinishedCallback.BindUFunction(this, FName{ TEXT("HandleTimelineFinished") } ); OpacityTimeline.AddInterpFloat(OpacityCurve, TimelineUpdateCallback); OpacityTimeline.SetTimelineFinishedFunc(TimelineFinishedCallback); OpacityTimeline.PlayFromStart(); } } void AGhostTrail::HandleTimelineUpdate(float Value) { DynamicMatInstance->SetScalarParameterValue(ScalarParameterName, Value); } void AGhostTrail::HandleTimelineFinished() { Destroy(); } | cs |
'프로그래밍 > Unreal Engine4' 카테고리의 다른 글
Line of Sight 컴포넌트 (C++) (0) | 2019.01.30 |
---|---|
파라곤 Anim Distance Matching (0) | 2018.10.22 |
VIVE (SteamVR) Load Streaming Level 문제 (0) | 2018.10.22 |
GENERATED_BODY , GENERATED_UCLASS_BODY 매크로 (0) | 2018.07.10 |
파라곤 이동 중지,시작거리 예측 (0) | 2018.05.16 |