본문 바로가기
Unreal/[UE4] 플랫포머 제작 연습(C++)

4. 사라지는 발판

by 잡템 2023. 11. 11.

오늘은 예정대로 사라지는 발판의 구현을 시도했다. 처음은 전체적으로 투명해지는 오브젝트를 만들어보고싶어서

BlendMode를 Translucent로 해서 투명도 조절가능한 오브젝트를 만드는 방향으로 시도해보려했으나

좌: Translucent , 우 : Opaque

이렇게 비교하면 확연히 눈에띄듯 투명도조절로 오브젝트를완전히 투명하게할수있는건 좋은데 문제가 오브젝트의 그림자가 생기질않아 이질감이 많이든다.. 오브젝트에 머테리얼을 기본과 투명도 조절 두개를 두고 스왑하는 방법도 고려했으나 순간적으로 머테리얼 교체하면서 생기는 위화감에 대해 해결할 방법이 생각나는게 없어서 이 방법은 포기했다.

 

다른 방법으로는 Dissolve 효과를 주는 방법을 선택했다. 뭔가 녹아내는것처럼 오브젝트가 불타없어지거나 하는 효과를 줄때 사용하는방법인데 이쪽은 자료를 찾아봤을때 영상에서 기본 질감을 그대로 두고도 할수있는 영상이 많아 쉽게할 수 있는 자료도 어딘가 있을거같아서 선택했다.

 

머티리얼 노드는 이런식으로 구성했으며 참고자료의경우 Multiply의 결과를 베이스컬러가아니라 이미시브 컬러에 연결해서 Translucent 랑 동일하게 나와서 방법을 찾다가 그냥 베이스컬러에 일단 연결해봤는데 결과가 잘나온것같다.

해당 머티리얼은 Opaque나 Translucent가 아닌 Masked로 설정했다.

 

코드는 다음과같이 구성했다.

//헤더
public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
	void DissolveObject(float DeltaTime);

private:
	UPROPERTY(VisibleAnywhere)
	UStaticMeshComponent* Mesh;
	UPROPERTY(VisibleAnywhere)
	float Time;
	UPROPERTY(VisibleAnywhere)
	bool bIsTimeStop;
	UPROPERTY(VisibleAnywhere)
	bool bIsActive;

	UPROPERTY(EditAnywhere,BlueprintReadOnly,Category=Dissolve, Meta=(AllowPrivateAccess=true))
	float ActiveTime;
	UPROPERTY(EditAnywhere,BlueprintReadOnly,Category=Dissolve, Meta=(AllowPrivateAccess=true))
	float DeActiveTime;
	UPROPERTY(EditAnywhere,BlueprintReadOnly,Category=Dissolve, Meta=(AllowPrivateAccess=true))
	float DissolveAmount;
	UPROPERTY(EditAnywhere,BlueprintReadOnly,Category=Dissolve, Meta=(AllowPrivateAccess=true))
	float DissolveSpeed;
	UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category=Dissolve, Meta=(AllowPrivateAccess=true))
	bool bIsDissolve;
    
//CPP
void ADissolvePlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if(!bIsTimeStop)
		Time += DeltaTime;

	if(Time >= ActiveTime && !bIsDissolve)
	{
		//타이머를 정지
		bIsTimeStop = true;
		bIsDissolve = true;
		Time =0.f;
	}
	else if(Time >= DeActiveTime && bIsDissolve)
	{
		//타이머를 정지
		bIsTimeStop = true;
		bIsDissolve = false;
		Time =0.f;
	}

	DissolveObject(DeltaTime);
}

void ADissolvePlatform::DissolveObject(float DeltaTime)
{
	if(!bIsTimeStop)
		return;

	if(bIsDissolve)
	{
		DissolveAmount = FMath::FInterpTo(DissolveAmount,1.f,DeltaTime, DissolveSpeed);
		if(DissolveAmount >=0.95f)
		{	
			DissolveAmount = 1.f;
			bIsTimeStop = false;
			if(bIsActive)
			{
				SetActorHiddenInGame(true);
				bIsActive = false;
			}
			//콜리전 비활성화
			SetActorEnableCollision(false);
		}
		Mesh->SetScalarParameterValueOnMaterials("DissolveAmount",DissolveAmount);

	}
	else
	{
		DissolveAmount = FMath::FInterpTo(DissolveAmount,0.01f,DeltaTime, DissolveSpeed);
		if(!bIsActive)
		{
			SetActorHiddenInGame(false);
			bIsActive = true;			
		}
		
		//일정이상 오브젝트가 나타나면 콜리전 활성화
		if(!GetActorEnableCollision() && DissolveAmount <= 0.5f)
			SetActorEnableCollision(true);

		if(DissolveAmount <=0.05f)
		{
			DissolveAmount = 0.01f;
			bIsTimeStop = false;
		}
		Mesh->SetScalarParameterValueOnMaterials("DissolveAmount",DissolveAmount);
	}
}

 

Dissovle상태를 조절하는 파라미터 이름을 DissolveAmount라고 지었으며 0이되면 오브젝트가 아예 까맣게 변해버려서

최소치를 0.01 최대치를 1로 조정했다.

 

원래는 DissolveAmount를 따로 변수로 안두고 Mesh에서 현재 DissolveAmount의 값을 받아와서 보간처리하려 했으나 따로 함수가 존재하지않는것같아서 변수를 따로두고 초기값을 직접 설정해줬다.

 

Dissolve 진행도에따라 오브젝트와 콜리전을 활성화 비활성화해서 오브젝트가 일정이상 투명해지면 충돌하지않고 사라지게 작업했다.

생각보다 결과가 잘나온것같다 만족스럽다.

 

발판은 3종류로 마무리하고 다음은 버튼 UI와 2단점프를 추가해볼 예정이다.

 

Reference

https://gamefx.co.kr/bbs/board.php?bo_table=tip_01&wr_id=658

https://wergia.tistory.com/143