cpp의 Tick은 함수이기 때문에 내부에 변수를 추가하여도 다음 Tick때는 존재하지 않는 변수이다.

그렇기 때문에 Actor의 객체에 변수를 추가하여야한다.

Item.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"

UCLASS()
class TEST01_API AItem : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AItem();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

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

// 멤버변수 RunningTime
private:
	float RunningTime;
};

 

 

Item.cpp

void AItem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	// 1프레임당 걸리는 시간을 계속 누적한다. 즉 선형적인 값
	RunningTime += DeltaTime;

	// 사인함수에 선형적으로 증가하는 값을 넣었기 때문에 위아래로 흔들리는 사인함수의 그래프를 얻을 수 있다.
	float DeltaZ = FMath::Sin(RunningTime);

	CUSTOM_DEBUG_MESH_SingleFrame(GetActorLocation(), GetActorForwardVector() );
	AddActorWorldOffset(FVector(0.f ,0.f , DeltaZ));

	
}

 

큰 진폭 : ( 2 * FMath::Sin(RunningTime);)

빠른 주기 (FMath::Sin(RunningTime * 5.f);)

 

 

 

 

 

CustomDbugMacro.h

#pragma once
#include "DrawDebugHelpers.h"

// 매크로의 구성 
#define DRAW_SPHERE(Location) if (GetWorld()) DrawDebugSphere(GetWorld(), Location, 25.f, 20, FColor::Red, true, 60.f)
#define DRAW_LINE(Location, Vector) if (GetWorld()) DrawDebugLine(GetWorld(), Location, Location +Vector *100, FColor::Red, true, -1.f, 0U, 1.f )
#define DRAW_POINT(Location, Vector) if (GetWorld()) DrawDebugPoint(GetWorld(), Location + Vector * 100, 25.f, FColor::Red, true, -1.0f, 0U)
#define CUSTOM_DEBUG_MESH(Location, Vector) if (GetWorld()) {\
	DRAW_SPHERE(Location);\
	DRAW_LINE(Location, Vector);\
	DRAW_POINT(Location, Vector);\
	}

#define DRAW_SPHERE_SingleFrame(Location) if (GetWorld()) DrawDebugSphere(GetWorld(), Location, 25.f, 20, FColor::Red, false, -1.f)
#define DRAW_LINE_SingleFrame(Location, Vector) if (GetWorld()) DrawDebugLine(GetWorld(), Location, Location +Vector *100, FColor::Red, false, -1.f, 0U, 1.f )
#define DRAW_POINT_SingleFrame(Location, Vector) if (GetWorld()) DrawDebugPoint(GetWorld(), Location + Vector * 100, 25.f, FColor::Red, false, -1.0f, 0U)
#define CUSTOM_DEBUG_MESH_SingleFrame(Location, Vector) if (GetWorld()) {\
	DRAW_SPHERE_SingleFrame(Location);\
	DRAW_LINE_SingleFrame(Location, Vector);\
	DRAW_POINT_SingleFrame(Location, Vector);\
	}

 

DrawDebug...의 파라미터에 대해 궁금한 것이있어 찾아봣다.

  1. WorldContextObject: 함수가 호출되는 컨텍스트를 나타내는 UObject나 UActorComponent입니다.
  2. Center: 스피어의 중심 위치를 나타내는 FVector입니다.
  3. Radius: 스피어의 반지름을 나타내는 부동 소수점 값입니다.
  4. Segments: 스피어의 그리드 분할 수를 나타내는 정수 값으로, 스피어를 얼마나 부드럽게 그릴지 결정합니다. 더 많은 세그먼트는 더 부드러운 외형을 제공하지만, 계산 비용이 증가합니다.
  5. Color: 스피어를 그릴 때 사용할 색상을 나타내는 FLinearColor입니다.
  6. bPersistentLines: 이 값이 true이면, 스피어는 한 프레임에서 다음 프레임으로 그려진 라인과 함께 유지됩니다. false이면, 각 호출마다 스피어가 새로 그려집니다.
  7. LifeTime: 스피어가 지속되는 시간을 나타내는 값으로, bPersistentLines가 false인 경우에만 적용됩니다. 일정 시간이 지나면 스피어가 사라집니다.
  8. DepthPriority: 스피어의 렌더링 깊이를 나타내며, 더 높은 값은 더 앞에 렌더링됩니다.

bPersistentLines 값이 False라면 이전 프레임에 그려진 것은 지워지게 된다. 

LifeTime값을 -1로 주어 이전 프레임것이 남겨지는 시간이 없도록 세팅하므로서 이동할 때 이전프레임의 디버그 구체가 남지 않는다.

 

Item.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Item/Item.h"
#include "test01/CustomDebugMacro.h"

... 생략

void AItem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	// 프레임당 속도
	float Movement = 50.f;
	
    // 입력에 그냥 속도를 주게되면 프레임당 속도가 나온다. 즉 120프레임에서는 더 빠르며 30 프레임에서는 
	// 느린 이동속도를 보이게 된다. 
    
    // cm/frame * frame/s = 초당 이동거리 cm/s
	float FramePerMovement = Movement * DeltaTime;

	CUSTOM_DEBUG_MESH_SingleFrame(GetActorLocation(), GetActorForwardVector() );
	AddActorWorldOffset(FVector(FramePerMovement,0.f , 0.f));

	
}

 

DeltaTime은 이전 프레임부터 현재 프레임까지의 걸린시간 (frame/s)

이동속도는 프레임당 이동거리                                              (cm/frame) 

둘을 곱하면 초당 이동거리 (cm/s) 를 얻는다. 이를 대입하면 아무리 프레임이 빨라져도 동일한 이동속도를 구할 수 있다.

 

 

 

 

 

 

 


 

블루프린트를 사용한 위치 확인

 

 


C++를 사용한 위치 디버깅

// Fill out your copyright notice in the Description page of Project Settings.


#include "Item/Item.h"
#include "DrawDebugHelpers.h"

// 매크로의 구성 
#define DRAW_SPHERE(Location) if (GetWorld()) DrawDebugSphere(GetWorld(), Location, 25.f, 20, FColor::Red, false, 60.f)

// Sets default values
AItem::AItem()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// 액터가 스폰 되었을 때 실행되는 함수
void AItem::BeginPlay()
{
	Super::BeginPlay();
    // 아웃풋 콘솔에 표기되는 로그
	UE_LOG(LogTemp, Warning,TEXT("wow"));
    
	/* 
		UWorld* world = GetWorld();
		if (world) {
			DrawDebugSphere(world, location, 20.f, 32, FColor::Cyan,false ,60.f);
	
		}
	*/
	FVector Location = GetActorLocation();
	DRAW_SPHERE(Location);


	
}

// 매 프레임마다 동작하는 함수
void AItem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if (GEngine) {
    	// Actor가 가지는 이름
		FString Name = GetName();
        // GetName은 FStringdlrl 이므로 *Name으로 TCHAR로 변환
		 FString Message = FString::Printf(TEXT("Name is %s"), *Name);
		// FString Message = FString::Printf(TEXT("DeltaTime is %f"), DeltaTime);

		GEngine->AddOnScreenDebugMessage(1, 60, FColor::Cyan, Message);
	
	}
}

 

 

 

FString의 operator*

/**
 * Get pointer to the string
 *
 * @Return Pointer to Array of TCHAR if Num, otherwise the empty string
 */
UE_NODISCARD FORCEINLINE const TCHAR* operator*() const UE_LIFETIMEBOUND
{
	return Data.Num() ? Data.GetData() : TEXT("");
}

 

 


결과

 

흰색 구체는 BluePrint로 그린 것이고 빨간색이 C++로 그린 구체

+ Recent posts