728x90
케릭터가 분리되어있을 때, 구분적으로 케릭터를 생성하고 관리하는 방법을 안다.
일정 동작사항에 케릭터의 메쉬를 바꿀 수 있다.
EnumType
#pragma once
#include "CoreMinimal.h"
#pragma region Enum
UENUM(BlueprintType)
enum class ECharacterMoudlePart
{
Body UMETA(DisplayName = "Body"),
Head UMETA(DisplayName = "Head"),
LeftGranade UMETA(DisplayName = "LeftGranade"),
RightGranade UMETA(DisplayName = "RightGranade"),
Tablet UMETA(DisplayName = "Tablet"),
LeftBag UMETA(DisplayName = "LeftBag"),
RightBag UMETA(DisplayName = "RightBag"),
VestBag UMETA(DisplayName = "VestBag"),
BackBag UMETA(DisplayName = "BackBag"),
ExoLegs UMETA(DisplayName = "ExoLegs"),
};
#pragma endregion
사용할 캐릭터의 Enum을 생성하고 정의해준다.
이 Enum을 사용해서 Base_Character의 메시데이터를 정의해줄것이다.
Base_Character
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "BaseCharacter.generated.h"
#define SKELETAL_MESH_COMP(NAME) \
UPROPERTY(VisibleDefaultsOnly) \
TObjectPtr<USkeletalMeshComponent> NAME;
UCLASS()
class FTPSGAME_API ABaseCharacter : public ACharacter
{
GENERATED_BODY()
protected:
SKELETAL_MESH_COMP(Body)
SKELETAL_MESH_COMP(Head)
SKELETAL_MESH_COMP(LeftGranade)
SKELETAL_MESH_COMP(RightGranade)
SKELETAL_MESH_COMP(Tablet)
SKELETAL_MESH_COMP(LeftBag)
SKELETAL_MESH_COMP(RightBag)
SKELETAL_MESH_COMP(VestBag)
SKELETAL_MESH_COMP(BackBag)
SKELETAL_MESH_COMP(ExoLegs)
public:
// Sets default values for this character's properties
ABaseCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
스켈레톤 메시를 여러개 가지는 케릭터 H와 CPP를 생성해준다.
// Fill out your copyright notice in the Description page of Project Settings.
#include "Actors/BaseCharacter.h"
#include "Utility/Helper.h"
#define CREATE_EMSH_COMP(Name) \
Name = Helper::CreateSceneComponent \
<USkeletalMeshComponent>(this, #Name, GetMesh());
// Sets default values
ABaseCharacter::ABaseCharacter()
{
// Create Skeletal Mesh Comp
{
CREATE_EMSH_COMP(Body)
CREATE_EMSH_COMP(Head)
CREATE_EMSH_COMP(LeftGranade)
CREATE_EMSH_COMP(RightGranade)
CREATE_EMSH_COMP(Tablet)
CREATE_EMSH_COMP(LeftBag)
CREATE_EMSH_COMP(RightBag)
CREATE_EMSH_COMP(VestBag)
CREATE_EMSH_COMP(BackBag)
CREATE_EMSH_COMP(ExoLegs)
}
// Mesh Load
{
USkeletalMesh* BodyMesh =
Helper::GetAsset<USkeletalMesh>("/Script/Engine.SkeletalMesh'/Game/Characters/Elite_Solders/Body/SKM_UE5__Elite_Soldier_Body.SKM_UE5__Elite_Soldier_Body'");
GetMesh()->SetSkeletalMesh(BodyMesh);
USkeletalMesh* HeadMesh = Helper::GetAsset<USkeletalMesh>("/Script/Engine.SkeletalMesh'/Game/Characters/Elite_Solders/Heads/SKM_UE5__Elite_Soldier_Head_01.SKM_UE5__Elite_Soldier_Head_01'");
Head->SetSkeletalMesh(HeadMesh);
}
// Set Leader
{
Head->SetLeaderPoseComponent(GetMesh());
LeftGranade->SetLeaderPoseComponent(GetMesh());
RightGranade->SetLeaderPoseComponent(GetMesh());
Tablet->SetLeaderPoseComponent(GetMesh());
LeftBag->SetLeaderPoseComponent(GetMesh());
RightBag->SetLeaderPoseComponent(GetMesh());
VestBag->SetLeaderPoseComponent(GetMesh());
BackBag->SetLeaderPoseComponent(GetMesh());
ExoLegs->SetLeaderPoseComponent(GetMesh());
}
// Set Mesh Location & Rocation
{
GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
}
}
// Called when the game starts or when spawned
void ABaseCharacter::BeginPlay()
{
Super::BeginPlay();
}
// Called to bind functionality to input
void ABaseCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
각 메시는, PosComponent의 mesh에서 값을 읽어오기 때문에, 지정된 본에 대한 이동움직임. 즉, ABP의 동작사항을 이어받아 각각 움직이게 된다.
LeaderPosComponent의 mesh에 상속받기 때문에, Mesh의 이동에 상속받는다는 의미.
머리와 몸체는 따로 설정이 들어갈 수 있지만, 기본값을 지정해주어, 값이 없어도 기본몸과 머리가 존재하도록 해준다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Actors/BaseCharacter.h"
#include "Hero.generated.h"
class USpringArmComponent;
class UCameraComponent;
struct FInputActionValue;
class UInputMappingContext;
class UInputAction;
UCLASS()
class FTPSGAME_API AHero : public ABaseCharacter
{
GENERATED_BODY()
// Components
UPROPERTY(VisibleDefaultsOnly, Category = "Camera")
TObjectPtr<UCameraComponent> Camera;
UPROPERTY(VisibleDefaultsOnly, Category = "Camera")
TObjectPtr<USpringArmComponent> SpringArm;
UPROPERTY(EditDefaultsOnly, CateGory = Input, meta=(AllowPrivateAccess="true"))
TObjectPtr<UInputAction> MoveAction;
UPROPERTY(EditDefaultsOnly, CateGory = Input, meta = (AllowPrivateAccess = "true"))
TObjectPtr<UInputAction> ViewAction;
UPROPERTY(EditDefaultsOnly, CateGory = Input, meta = (AllowPrivateAccess = "true"))
TObjectPtr<UInputAction> JumpAction;
UPROPERTY(EditDefaultsOnly, CateGory = Input, meta = (AllowPrivateAccess = "true"))
TObjectPtr<UInputMappingContext> InputMappingContext;
public:
AHero();
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void Move(const FInputActionValue& Value);
void Look(const FInputActionValue& Value);
};
기본 이동에 대한 Character를 Base_Character를 부모로 두고 생성한다.
// Fill out your copyright notice in the Description page of Project Settings.
#include "Actors/Heros/Hero.h"
#include "Utility/Helper.h"
#include "Engine/LocalPlayer.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/Controller.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
AHero::AHero()
{
{
SpringArm = Helper::CreateSceneComponent<USpringArmComponent>(this, "Spring Arm", GetCapsuleComponent());
Camera = Helper::CreateSceneComponent<UCameraComponent>(this, "Camera", SpringArm);
}
}
void AHero::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
// Jumping
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
// Moving
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AHero::Move);
// Looking
EnhancedInputComponent->BindAction(ViewAction, ETriggerEvent::Triggered, this, &AHero::Look);
}
}
void AHero::Look(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D LookAxisVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
// add yaw and pitch input to controller
AddControllerYawInput(LookAxisVector.X);
AddControllerPitchInput(LookAxisVector.Y);
}
}
void AHero::Move(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D MovementVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
// find out which way is forward
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// get forward vector
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
// get right vector
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
// add movement
AddMovementInput(ForwardDirection, MovementVector.Y);
AddMovementInput(RightDirection, MovementVector.X);
}
}
기본 움직임을 구현하였다.
메시가 잘 나타나는지 확인한다. 메시데이터가 잘 붙어서 생성되어있으면 성공.
728x90
'서울게임아카데미 교육과정 6개월 국비과정' 카테고리의 다른 글
20240424 132일차 언리얼 C++ 데이터 레이블 활용 캐릭터 생성3 (0) | 2024.04.24 |
---|---|
20240423 131일차 언리얼 C++ 데이터 레이블 활용 케릭터 생성2 (0) | 2024.04.23 |
20240419 129일차 언리얼 C++ 데이터 테이블 (1) | 2024.04.19 |
20240416 127일차 언리얼 C++ 캐릭터 조작 (0) | 2024.04.16 |
20240409 123일차 언리얼 블루프린트 AI EQS (0) | 2024.04.09 |