반응형
이번 포스팅은 이전에 만든 Dissolve 마테리얼과 Refraction 마테리얼을 조작하는 C++ 컴포넌트를 작성해서 키보드를 누르면 클록킹 발동, 해제를 구현하겠습니다.
우선 Actor Component C++ 클래스를 생성합니다.
UCpt_Cloaking.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Cpt_Cloaking.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CLOAKINGTUTORIAL_API UCpt_Cloaking : public UActorComponent
{
GENERATED_BODY()
public:
//! SKMesh
UPROPERTY()
class USkeletalMeshComponent* m_pSkeletal_Mesh;
UPROPERTY()
class USkeletalMeshComponent* m_pSkeletal_Mesh2Pass;
//! Material Instance 저장용 Array
UPROPERTY()
TArray<class UMaterialInstanceDynamic*> m_pSpawnMaterial;
public :
UPROPERTY(EditAnywhere)
float m_fCloakingAmount_Max = 1.5f; //! 마테리얼의 Amount의 Max값입니다.
UPROPERTY(EditAnywhere)
float m_fCloakingAmount_Min = -0.5f; //! 마테리얼의 Amount의 Min값입니다.
UPROPERTY(EditAnywhere)
float m_fCloakingSpeed = 0.3f; //! 클로킹 변할때 속도 조절값입니다.
private:
bool m_bInit = false; //! Check Init
bool m_bIsCloaking = false; //! 클로킹 발동중 체크
int m_nState_Cloaking = -1; //! 클로킹 상태 체크(0 = 무상태, 1 = 클로킹 발동중, 2 = 클로킹 해제중)
float m_fCurrAmount = 0.0f; //! 클로킹 수치 변수 현재값
float m_fDestAmount = 0.0f; //! 클로킹 수치 변수 목표값
public:
UCpt_Cloaking();
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
void Init(class USkeletalMeshComponent* pMainMesh, class USkeletalMeshComponent* p2PassMesh);
UFUNCTION(BlueprintCallable, Category = "Event")
void Active_Cloaking();
UFUNCTION(BlueprintCallable, Category = "Event")
void DeActive_Cloaking();
bool GetIsCloaking() { return m_bIsCloaking; }
};
UCpt_Cloaking.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Cpt_Cloaking.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Materials/MaterialInterface.h"
#include "Kismet/KismetMaterialLibrary.h"
#include "Components/SkeletalMeshComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "Kismet/GameplayStatics.h"
UCpt_Cloaking::UCpt_Cloaking()
{
PrimaryComponentTick.bCanEverTick = true;
}
// Called when the game starts
void UCpt_Cloaking::BeginPlay()
{
Super::BeginPlay();
}
void UCpt_Cloaking::Init(class USkeletalMeshComponent* pMainMesh, class USkeletalMeshComponent* p2PassMesh)
{
//! Init variables
//! 변수들을 초기화합니다.
m_bInit = false;
m_bIsCloaking = false;
m_nState_Cloaking = 0;
m_fCurrAmount = 0.0f;
m_fDestAmount = 0.0f;
m_pSkeletal_Mesh = pMainMesh;
m_pSkeletal_Mesh2Pass = p2PassMesh;
//! 인자 값으로 들어온 SKMesh를 점검합니다.
if (m_pSkeletal_Mesh != nullptr && m_pSkeletal_Mesh2Pass != nullptr)
{
m_bInit = true;
}
//! SKMesh에 들어있는 마테리얼들을 추출해서 m_pSpawnMaterial List에 추가합니다.
TArray<UMaterialInterface*> pMaterials = m_pSkeletal_Mesh->GetMaterials();
for (int i = 0; i < pMaterials.Num(); i++)
{
UMaterialInstanceDynamic* pSpawnMaterial = UKismetMaterialLibrary::CreateDynamicMaterialInstance(m_pSkeletal_Mesh->GetWorld(), pMaterials[i]);
m_pSkeletal_Mesh->SetMaterial(i, pSpawnMaterial);
m_pSpawnMaterial.Add(pSpawnMaterial);
}
//! 위와 마찬가지로 2Pass용 SKMesh의 마테리얼을 추출합니다.
TArray<UMaterialInterface*> pMaterials2 = m_pSkeletal_Mesh2Pass->GetMaterials();
for (int i = 0; i < pMaterials.Num(); i++)
{
UMaterialInstanceDynamic* pSpawnMaterial = UKismetMaterialLibrary::CreateDynamicMaterialInstance(m_pSkeletal_Mesh2Pass->GetWorld(), pMaterials2[i]);
m_pSkeletal_Mesh2Pass->SetMaterial(i, pSpawnMaterial);
m_pSpawnMaterial.Add(pSpawnMaterial);
}
}
void UCpt_Cloaking::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
//! 상태 변수 기반으로 클록킹 값 업데이트합니다.
if (m_nState_Cloaking != 0)
{
m_fCurrAmount += DeltaTime * m_fCloakingSpeed;
float fLerp = 0.0f;
if (m_nState_Cloaking == 1)
{
fLerp = UKismetMathLibrary::Lerp(m_fCloakingAmount_Min, m_fDestAmount, m_fCurrAmount);
}
else
{
fLerp = UKismetMathLibrary::Lerp(m_fCloakingAmount_Max, m_fDestAmount, m_fCurrAmount);
}
//! SKMesh에서 추출한 마테리얼의 값을 조작합니다.
for (int i = 0; i < m_pSpawnMaterial.Num(); i++)
{
m_pSpawnMaterial[i]->SetScalarParameterValue("Amount", fLerp);
}
if (m_fCurrAmount >= 1.0f)
{
m_fCurrAmount = 0.0f;
m_nState_Cloaking = 0;
}
}
}
//! 클로킹 발동
void UCpt_Cloaking::Active_Cloaking()
{
if (m_bInit == false) return;
if (m_bIsCloaking == true) return;
if (m_nState_Cloaking != 0) return;
m_bIsCloaking = !m_bIsCloaking;
m_nState_Cloaking = 1;
m_fDestAmount = m_fCloakingAmount_Max;
}
//! 클로킹 해제
void UCpt_Cloaking::DeActive_Cloaking()
{
if (m_bInit == false) return;
if (m_bIsCloaking == false) return;
if (m_nState_Cloaking != 0) return;
m_bIsCloaking = !m_bIsCloaking;
m_nState_Cloaking = 2;
m_fDestAmount = m_fCloakingAmount_Min;
}
위 코드 다 작성하시면 컴파일을 하여 오류가 없는지 점검합니다.
Cpt_Cloaking 컴포넌트를 기본 3인칭 샘플 프로젝트의 캐릭터 클래스에 추가해보겠습니다.
AThirdPersonCharacter.h
class ACloakingTutorialCharacter : public ACharacter
{
GENERATED_BODY()
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class UCpt_Cloaking* m_pCloaking;
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
헤더파일에 UCpt_Cloaking 컴포넌트 변수를 위와 같이 작성합니다.
AThirdPersonCharacter.cpp
#include "CloakingTutorialCharacter.h"
#include "......."
#include "Kismet/GameplayStatics.h"
#include "Cpt_Cloaking.h"
ACloakingTutorialCharacter::ACloakingTutorialCharacter()
{
...
...
//! 클로킹 컴포넌트 생성
m_pCloaking = CreateDefaultSubobject<UCpt_Cloaking>(TEXT("Cloaking"));
}
void ACloakingTutorialCharacter::BeginPlay()
{
Super::BeginPlay();
//! 클로킹 컴포넌트 초기화 변수 호출
m_pCloaking->Init(GetMesh(), m_p2PassMesh);
}
void ACloakingTutorialCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//! 키보드 R 누르면 클로킹 발동/해제를 합니다.
if (UGameplayStatics::GetPlayerController(GetWorld(), 0)->WasInputKeyJustPressed(EKeys::R) == true)
{
if (m_pCloaking->GetIsCloaking() == true)
{
m_pCloaking->DeActive_Cloaking();
}
else
{
m_pCloaking->Active_Cloaking();
}
}
}
위 처럼 코드를 작성하고 컴파일하여 기능 테스트하면 끝입니다.
다음 포스팅은 Cascade이펙트 추가와 포스트 프로세스로 효과를 추가하여 더욱 이펙트를 이쁘게 만드는 것에 대해 포스팅하겠습니다.
반응형
'Unreal > Shader & VFX' 카테고리의 다른 글
[Tutorial] Cloaking Effect 4장 : 파티클 및 후처리 Part - 2 -End- (0) | 2019.08.01 |
---|---|
[Tutorial] Cloaking Effect 4장 : 파티클 및 후처리 Part - 1 (0) | 2019.07.31 |
[Tutorial] Cloaking Effect 2장 : Refraction 효과 (0) | 2019.07.29 |
[Tutorial] Cloaking Effect 1장 : Dissolve 효과 (2) | 2019.07.27 |
Cloaking Effect - 은신 이펙트 (0) | 2019.07.26 |
WRITTEN BY
- CatDarkGame
Technical Artist dhwlgn12@gmail.com
,