초보 코린이의 성장 일지

UE4 Tool Bar, Player 본문

언리얼

UE4 Tool Bar, Player

코오린이 2023. 4. 26. 17:33

툴바 마지막 단계로 LineTrace를 쏴서 객체에 대한 정보를 나타내 보겠다.

1. 새 클래스를 하나 생성해준다.

더보기
#include "ButtonCommand.h"
#include "Misc/MessageDialog.h"
#include "Misc/FileHelper.h"
#include "Serialization/BufferArchive.h"
#include "DesktopPlatformModule.h"
#include "Interfaces/IMainFrameModule.h"
#include "StaticMesh_Detail.h"
#include "Editor.h"
#include "LevelEditorViewport.h"
#include "CStaticMesh_Copied.h"

FButtonCommand::FButtonCommand()
	: TCommands("ToolBar_Buttons", FText(), NAME_None, FEditorStyle::GetStyleSetName())
{
	Command = MakeShareable(new FUICommandList());
}

FButtonCommand::~FButtonCommand()
{
	if (Command.IsValid())
		Command.Reset();
}

void FButtonCommand::OnClicked_LoadMesh()
{
	// 배치될 위치
	FTransform transform;
	FVector direction = (hitResult.TraceEnd - hitResult.TraceStart); // 시작 지점에서 끝지점 바라보는 방향
	direction.Normalize();

	// 모델이 생성된곳이 LineTrace와 Hit가 되면, 그 지점이 겹치게 되므로 Radius를 뺴줘서 적당한 거리를 벌려 배치해준다.
	FVector location = hitResult.TraceStart + direction * (hitResult.Distance - data.Radius);
	transform.SetLocation(location);

	// 카메라 회전값 사용하여 배치.
	FRotator rotator = FRotator(0, direction.Rotation().Yaw, 0);
	transform.SetRotation(FQuat(rotator));

	ACStaticMesh_Copied* actor = world->SpawnActorDeferred<ACStaticMesh_Copied>
		(
			ACStaticMesh_Copied::StaticClass(),
			transform, // 배치될때 충돌이 되는지 확인하기 위함
			nullptr,
			nullptr,
			ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn // 조정해서 Spawn 시키기
			);

	actor->SetPositions(data.Positions);
	actor->SetIndices(data.Indices);
	actor->SetNormals(data.Normals);
	actor->SetUvs(data.Uvs);
	actor->SetColors(data.Colors);

	actor->FinishSpawning(transform); // 최종 배치될 위치
}

1. 만들어준 클래스를 배치해 주기 위해 작성.

2. 카메라를 회전값을 사용.

3. Spawn 위치를 조정해준다.

 

1. Mesh를 생성해서 처리하는 부분은 OnConstruction에서 처리하게 될 것이다.

2. GameStart되기 전에 호출이 되는 부분이다.

 

더보기
#pragma once

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

UCLASS()
class U2212_05_API ACStaticMesh_Copied : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(VisibleDefaultsOnly)
		class UProceduralMeshComponent* Mesh;

	UPROPERTY(VisibleDefaultsOnly)
		class UMaterialInstanceConstant* Material;

public:
#if WITH_EDITOR // 값들 입력 함수
	FORCEINLINE void SetPositions(TArray<FVector> InPositions) { Positions = InPositions; }
	FORCEINLINE void SetIndices(TArray<int32> InIndices) { Indices = InIndices; }
	FORCEINLINE void SetNormals(TArray<FVector> InNormals) { Normals = InNormals; }
	FORCEINLINE void SetUvs(TArray<FVector2D> InUvs) { Uvs = InUvs; }
	FORCEINLINE void SetColors(TArray<FColor> InColors) { Colors = InColors; }
#endif

public:
	ACStaticMesh_Copied();

	void OnConstruction(const FTransform& Transform) override;

protected:
	virtual void BeginPlay() override;

private:
	TArray<FVector> Positions;
	TArray<int32> Indices;
	TArray<FVector> Normals;
	TArray<FVector2D> Uvs;
	TArray<FColor> Colors;
};
#include "CStaticMesh_Copied.h"
#include "Global.h"
#include "ProceduralMeshComponent.h"
#include "Materials/MaterialInstanceConstant.h"

ACStaticMesh_Copied::ACStaticMesh_Copied()
{
	// 드래그를 때는 순간 호출되게끔 하기 위해 사용 (실제는 Int형인데 Bool로 받아들인다)
	bRunConstructionScriptOnDrag = false;

	CHelpers::CreateComponent(this, &Mesh, "Mesh");

	CHelpers::GetAsset<UMaterialInstanceConstant>(&Material, "MaterialInstanceConstant'/Game/M_StaticMesh_Inst.M_StaticMesh_Inst'");
	Mesh->SetMaterial(0, Material);
}

// 정보들을 가지고 배치만 해주면된다.
void ACStaticMesh_Copied::OnConstruction(const FTransform& Transform)
{
	Super::OnConstruction(Transform);

	// 값들을 넣어주고 Mesh 생성.
	Mesh->CreateMeshSection(0, Positions, Indices, Normals, Uvs, Colors, TArray<FProcMeshTangent>(), true);
}

void ACStaticMesh_Copied::BeginPlay()
{
	Super::BeginPlay();

}

1. 게임이 시작되기전에 생성되게 하기 위해 Construction을 사용하여 작성한다.

2. 정보들을 넣어준다.

3. 배치될 위치는 Command에서 설정이 되어있기 떄문에 생성해준다.

1. 드래그한 위치에서 생성될 것이므로, 아무곳이나 마우스를 올려두고 메시를 클릭해준다.

2. 저장되어있는 StaticMesh를 클릭해주면 마우스가 위치한 자리에 객체가 생성된다.

3. 출력 로그에도 동일하게 정보가 나오는걸 확인할 수 있다.

 

https://www.youtube.com/watch?v=JKslhv6YWw8 


1. 이제 다시 Player를 만들어 무기를 장착하고, 전투를 하기 위한 작업을 시작해 볼 것이다.

2. 우선 새 프로젝트를 생성해준다.

1. 필드를 하나 제작해준다.

1. 키 설정은 전에 있던 프로젝트에 있는걸 그대로 사용할 것이다.

1. Player를 생성해준다.

1. 기본적으로 사용하던 Helpers.h, Global.h는 가져와서 사용해준다.

더보기
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "CPlayer.generated.h"

UCLASS()
class U2212_06_API ACPlayer : public ACharacter
{
	GENERATED_BODY()

private:
	UPROPERTY(VisibleAnywhere)
		class USpringArmComponent* SpringArm;

	UPROPERTY(VisibleAnywhere)
		class UCameraComponent* Camera;

public:
	ACPlayer();

protected:
	virtual void BeginPlay() override;

public:
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
#include "Characters/CPlayer.h"
#include "Global.h"
#include "CAnimInstance.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/InputComponent.h"

ACPlayer::ACPlayer()
{
	// 생성
	CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
	CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);

	// Mesh 세팅
	GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
	GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));

	USkeletalMesh* mesh;
	CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
	GetMesh()->SetSkeletalMesh(mesh);

	TSubclassOf<UCAnimInstance> animInstance;
	CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_Character.ABP_Character_C'");
	GetMesh()->SetAnimClass(animInstance);

	// SpringArm 세팅, CharacterMovement 까지 가져와주기.
	SpringArm->SetRelativeLocation(FVector(0, 0, 140));
	SpringArm->SetRelativeRotation(FRotator(0, 90, 0));
	SpringArm->TargetArmLength = 200;
	SpringArm->bDoCollisionTest = false;
	SpringArm->bUsePawnControlRotation = true;
	SpringArm->bEnableCameraLag = true;

	GetCharacterMovement()->RotationRate = FRotator(0, 720, 0);
}

void ACPlayer::BeginPlay()
{
	Super::BeginPlay();
	
}

void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

1. Mesh, SpringArm, Camera, CharacterMovement 세팅해준다.

1. 세팅이 끝난 Player를 블루프린트 클래스로 생성해준다.

더보기
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "CGameMode.generated.h"

UCLASS()
class U2212_06_API ACGameMode : public AGameModeBase
{
	GENERATED_BODY()
	
public:
	ACGameMode();
};
#include "CGameMode.h"
#include "Global.h"

ACGameMode::ACGameMode()
{
	CHelpers::GetClass<APawn>(&DefaultPawnClass, "Blueprint'/Game/Player/BP_CPlayer.BP_CPlayer_C'");
}

1. 게임모드에서 Main Player를 넣어줘서 세팅을 해준다.

1. Player가 지정되있는 것을 확인할 수 있다.

1. 캐릭터를 맵안에 올려놓는데는 성공하였다. 이제 움직일 수 있도록 애니메이션을 넣어줄 것이다.

더보기
#pragma once

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "CAnimInstance.generated.h"

UCLASS()
class U2212_06_API UCAnimInstance : public UAnimInstance
{
	GENERATED_BODY()
	
protected:
	// 스피드
	UPROPERTY(BlueprintReadOnly, Category = "Animation")
		float Speed;

	// 회전
	UPROPERTY(BlueprintReadOnly, Category = "Animation")
		float Pitch;

	// 방향
	UPROPERTY(BlueprintReadOnly, Category = "Animation")
		float Direction;

public:
	void NativeBeginPlay() override;
	void NativeUpdateAnimation(float DeltaSeconds) override;

private:
	class ACharacter* OwnerCharacter;

private:
	FRotator PrevRotation;
};
#include "Characters/CAnimInstance.h"
#include "Global.h"
#include "GameFramework/Character.h"

void UCAnimInstance::NativeBeginPlay()
{
	Super::NativeBeginPlay();

	OwnerCharacter = Cast<ACharacter>(TryGetPawnOwner());
	CheckNull(OwnerCharacter);

}

void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);
	CheckNull(OwnerCharacter);

	Speed = OwnerCharacter->GetVelocity().Size2D();

	// 회전 세팅
	FRotator rotator = OwnerCharacter->GetVelocity().ToOrientationRotator();
	FRotator rotator2 = OwnerCharacter->GetControlRotation();
	FRotator delta = UKismetMathLibrary::NormalizedDeltaRotator(rotator, rotator2);
	PrevRotation = UKismetMathLibrary::RInterpTo(PrevRotation, delta, DeltaSeconds, 25);
	Direction = PrevRotation.Yaw;

	Pitch = UKismetMathLibrary::FInterpTo(Pitch, OwnerCharacter->GetBaseAimRotation().Pitch, DeltaSeconds, 25);
}

1. 회전을 세팅해준다.

 

1. 애니메이션 블루프린트를 지정해줘서 생성해준다.

1. 기본인 Speed를 넣어주고 연결해주면 Unarmed 상태가 나온다.

2. 이미 CPlayer.cpp에 애니메이션 블루프린트 경로가 들어가 있기 때문에 동작이 바로 나오게 된다.

1. 동작이 잘 나온다.

'언리얼' 카테고리의 다른 글

UE4 Notify, Attach, Weapon  (0) 2023.04.28
UE4 Component, BackStep  (0) 2023.04.27
UE4 Button Command, Icon  (0) 2023.04.25
UE4 Button Command  (0) 2023.04.24
UE4 Save StaticMesh  (0) 2023.04.13
Comments