1. 라이브 코딩으로 컴파일
2. 라이브 코딩을 비활성화 하고 비주얼 스튜디오 내에서 빌드
유니티 | 언리얼 |
---|---|
Start() | BeginPlay() |
Update() | Tick() |
UE_LOG
함수 - 매개변수
- 로그 카테고리: 출력된 로그에서 내가 원하는 카테고리의 로그만 검색할 수 있는 등 구분을 해줌
- 로그 상세 수준: error, warning, log 등의 종류가 있으며 색상이 다르게 나타남
- 로그 내용(형식):
TEXT("~~")
- 인자: 로그 내용이
TEXT("%d")
인 경우,%d
에 들어갈 인자
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
//시작 로그
UE_LOG(LogTemp, Warning, TEXT("BeginPlay"));
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//매 프레임마다 로그
UE_LOG(LogTemp, Error, TEXT("Tick %f"), DeltaTime);
}
핫 리로드
- 언리얼 에디터의 실행 중에 에디터가 사용중인 모듈을 컴파일하면 이를 감지하여 기존 모듈을 내리고 신규 모듈로 바꾸는 작업
- 기존 모듈을 덮어쓰지 않고 새로운 파일로 생성되며 언리얼 에디터를 완전히 종료하고 컴파일하면 임시 모듈들은 제거됨
- 라이브 코딩을 대신할 수 있는 기능이지만 라이브코딩이 더 빠르고 유연
DebugGame
와 Development
모드는 Debug
vsRelease
와 비슷하다DebugGame
모드가 최적화가 덜 되어있지만 디버깅에 유용하다.Shipping
은 최종 배포에 적합한 모드로 최적화를 많이 해주므로 디버깅에 부적합하다.Editor
가 붙은 모드로 빌드 시 dll
파일이 만들어지며 에디터 위에서 dll
파일만 교체하는 것이고exe
실행 파일을 생성하는데 아트 리소스 파일을 따로 지정해주지 않으면 오류가 발생한다.private:
. . .
float RotateSpeed = 30.f;
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//z축 기준으로 회전
AddActorLocalRotation(FRotator(0.f, RotateSpeed * DeltaTime, 0.f));
}
➕ 새로운 맵 생성 [Ctrl + N]
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"
UCLASS()
class PRACTICEUNREAL_API AMyPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
UPROPERTY(VisibleAnyWhere)
UStaticMeshComponent* Mesh;
};
#include "MyPawn.h"
// Sets default values
AMyPawn::AMyPawn()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MESH"));
RootComponent = Mesh;
static ConstructorHelpers::FObjectFinder<UStaticMesh> SM(TEXT("/Script/Engine.StaticMesh'/Game/StarterContent/Props/SM_Couch.SM_Couch'"));
if (SM.Succeeded())
{
Mesh->SetStaticMesh(SM.Object);
}
}
// Called when the game starts or when spawned
void AMyPawn::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyGameModeBase.generated.h"
/**
*
*/
UCLASS()
class PRACTICEUNREAL_API AMyGameModeBase : public AGameModeBase
{
GENERATED_BODY()
//생성자 생성
AMyGameModeBase();
};
#include "MyGameModeBase.h"
#include "MyPawn.h"
AMyGameModeBase::AMyGameModeBase()
{
DefaultPawnClass = AMyPawn::StaticClass();
}
Update()
함수에서 입력 받는 코드를 작성하는 유니티와 다르게SetupPlayerInputComponent(UInputComponent*)
안에서 입력을 받는다.언리얼의 입력
- Axis: 지정된 상수값을 전달하는 입력으로, 해당 키가 눌리는 동안 정해놓은 값이 전달되고 입력이 없으면 0이 전달 - 조이스틱(연속적, 정도)
- Action: 키 입력과 비슷하며 입력한 순간, 입력 도중, 입력 끝 등에 따른 이벤트 - 버튼(T/F)
UpDown
, LeftRight
에 해당하는 키보드를 설정하고 Scale도 1
과 -1
로 설정#include "MyPawn.h"
#include "GameFramework/FloatingPawnMovement.h"
// Sets default values
AMyPawn::AMyPawn()
{
PrimaryActorTick.bCanEverTick = true;
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MESH"));
//움직임 컴포넌트 생성
Movement = CreateDefaultSubobject<UFloatingPawnMovement>(TEXT("MOVEMENT"));
. . .
}
. . .
// Called to bind functionality to input
void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//Axis 입력 받기
//입력에 따라 실행할 함수를 받음
PlayerInputComponent->BindAxis(TEXT("UpDown"), this, &AMyPawn::UpDown);
PlayerInputComponent->BindAxis(TEXT("LeftRight"), this, &AMyPawn::LeftRight);
}
//매핑에서 설정한 Scale값이 Value로 넘어오는 것
void AMyPawn::UpDown(float Value)
{
if (Value == 0.f) return;
//Value에 따라 앞뒤 움직임
AddMovementInput(GetActorForwardVector(), Value);
}
void AMyPawn::LeftRight(float Value)
{
if (Value == 0.f) return;
//Value에 따라 좌우 움직임
AddMovementInput(GetActorRightVector(), Value);
}
. . .
public:
. . .
//입력 받았을 때 실행할 함수 선언
void UpDown(float Value);
void LeftRight(float Value);
private:
UPROPERTY(VisibleAnyWhere)
UStaticMeshComponent* Mesh;
//움직임을 위한 컴포넌트
UPROPERTY(VisibleAnyWhere)
class UFloatingPawnMovement* Movement;
};
#include "MyCharacter.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
//메시 로드
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SM(TEXT("SkeletalMesh'/Game/ParagonSunWukong/Characters/Heroes/Wukong/Meshes/Wukong.Wukong'"));
if (SM.Succeeded())
{
GetMesh()->SetSkeletalMesh(SM.Object);
}
}
. . .
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//키보드 입력
PlayerInputComponent->BindAxis(TEXT("UpDown"), this, &AMyCharacter::UpDown);
PlayerInputComponent->BindAxis(TEXT("LeftRight"), this, &AMyCharacter::LeftRight);
}
void AMyCharacter::UpDown(float Value)
{
if (Value == 0.f) return;
AddMovementInput(GetActorForwardVector(), Value);
}
void AMyCharacter::LeftRight(float Value)
{
if (Value == 0.f) return;
AddMovementInput(GetActorRightVector(), Value);
}
. . .
public:
. . .
void UpDown(float Value);
void LeftRight(float Value);
};
#include "MyGameModeBase.h"
#include "MyCharacter.h"
AMyGameModeBase::AMyGameModeBase()
{
DefaultPawnClass = AMyCharacter::StaticClass();
}
#include "MyCharacter.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SPRINGARM"));
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("CAMERA"));
//루트 컴포넌트에 붙이기
SpringArm->SetupAttachment(GetCapsuleComponent());
//SpringArm에 붙이기
Camera->SetupAttachment(SpringArm);
SpringArm->TargetArmLength = 500.f; //길이
SpringArm->SetRelativeRotation(FRotator(-35.f, 0.f, 0.f)); //각도
//위치와 각도 설정
GetMesh()->SetRelativeLocationAndRotation(
FVector(0.f, 0.f, -88.f), FRotator(0.f, -90.f, 0.f));
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SM(TEXT("SkeletalMesh'/Game/ParagonSunWukong/Characters/Heroes/Wukong/Meshes/Wukong.Wukong'"));
if (SM.Succeeded())
{
GetMesh()->SetSkeletalMesh(SM.Object);
}
}
. . .
. . .
private:
UPROPERTY(VisibleAnyWhere)
class USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnyWhere)
class UCameraComponent* Camera;
Yaw
에 마우스X를 설정Yaw
축 코드를 추가하고, 이에 따른 움직임 함수를 적용한다.void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis(TEXT("UpDown"), this, &AMyCharacter::UpDown);
PlayerInputComponent->BindAxis(TEXT("LeftRight"), this, &AMyCharacter::LeftRight);
//Yaw 축
PlayerInputComponent->BindAxis(TEXT("Yaw"), this, &AMyCharacter::Yaw);
}
. . .
//마우스로 회전
void AMyCharacter::Yaw(float Value)
{
AddControllerYawInput(Value);
}
. . .
public:
. . .
void UpDown(float Value);
void LeftRight(float Value);
void Yaw(float Value); //Yaw 축
BP_MyCharacter
를 생성
- 뷰포트
- Constructor Script
- 이벤트 그래프
아래 코드와 같은 과정이다.
//메시 지정 static ConstructorHelpers::FObjectFinder<UStaticMesh> SM(TEXT("/Script/Engine.StaticMesh'/Game/StarterContent/Props/SM_Couch.SM_Couch'")); if (SM.Succeeded()) Mesh->SetStaticMesh(SM.Object); //위치, 각도 지정 GetMesh()->SetRelativeLocationAndRotation(FVector(0.f, 0.f, -88.f), FRotator(0.f, -90.f, 0.f));
추가
버튼을 눌러 컴포넌트를 쉽게 추가할 수 있다.private: UPROPERTY(VisibleAnyWhere) class USpringArmComponent* SpringArm; UPROPERTY(VisibleAnyWhere) class UCameraComponent* Camera;
SpringArm->SetupAttachment(GetCapsuleComponent()); Camera->SetupAttachment(SpringArm);
SpringArm->TargetArmLength = 500.f; SpringArm->SetRelativeRotation(FRotator(-35.f, 0.f, 0.f));
변수
의 더하기 버튼을 눌러 생성할 수 있으며 자료형과 public/private를 설정ArmLength
변수를 드래그 앤 드롭하여 get하고 타겟 암 길이에 연결SpringArm->TargetArmLength = ArmLength;
void AMyCharacter::LeftRight(float Value) { AddMovementInput(GetActorRightVector(), Value); }
#include "MyGameModeBase.h"
#include "MyCharacter.h"
AMyGameModeBase::AMyGameModeBase()
{
//블루프린트 클래스 찾기
//블루프린트 경로 설정 시 마지막에 '_C' 붙여야함
static ConstructorHelpers::FClassFinder<ACharacter> BP_Char(TEXT("Blueprint'/Game/Blueprints/BP_MyCharacter.BP_MyCharacter_C'"));
//블루프린트 연결
if (BP_Char.Succeeded()) DefaultPawnClass = BP_Char.Class;
}