no image
충돌 검사
충돌 검사(Collision Detection)란?게임 내에서 두 오브젝트가 서로 닿았는지(충돌했는지) 확인하는 과정오브젝트 간 충돌을 감지하여 물리 반응을 적용하거나 이벤트를 발생시키는 것이 충돌 검사충돌 검사의 종류 (Unreal Engine)1. 물리 충돌 (Physics Collision)오브젝트가 물리적으로 부딪히는 것 감지충돌 시 물리 법칙에 따른 반응 (튕기거나 멈춤)예시: 플레이어가 벽에 부딪혀 멈춤BoxComp->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);2. 쿼리 충돌 (Query Collision)레이캐스트(Line Trace) 또는 오버랩(Overlap)으로 충돌 감지물리 반응 없이 충돌 여부 확인예시: 아이템 근처에서 'Press ..
2025.01.24
no image
Pawn 클래스 다루기
오늘 작업 내용1. Box Component 생성 및 설정BoxComponent를 생성하고 루트 컴포넌트(Root Component)로 설정.기존 캐릭터의 CapsuleComponent와 유사한 역할을 수행.루트 컴포넌트 설정 이유: Pawn의 기본 충돌 영역을 정의.#include "Components/BoxComponent.h"ASpartaPawn::ASpartaPawn(){ BoxComp = CreateDefaultSubobject(TEXT("Box")); //박스 컴포넌트 생성 RootComponent = BoxComp; //박스 컴포넌트 루트 설정}  2. Skeletal Mesh Component 추가캐릭터 외형을 표시할 Skeletal Mesh Component 생성 및 부모 컴포넌트(Box..
2025.01.23
no image
언리얼 엔진 클래스 계층 구조
클래스 계층 구조와 리스코프 치환 원칙리스코프 치환 원칙 (LSP):하위 클래스는 언제나 상위 클래스를 대체할 수 있어야 한다.상위 클래스의 기능을 확장하거나 특수화할 수 있지만, 호환성은 유지해야 한다.언리얼 엔진의 클래스 구조:Actor → Pawn → Character의 계층은 점차적으로 더 구체적인 기능을 제공.각 클래스는 리스코프 치환 원칙을 충실히 따르며, 상속을 통해 확장 가능.1. UObject 클래스역할: 언리얼 엔진의 모든 클래스의 기본 클래스(Base Class).특징:게임 세계 안에서 직접 배치되거나 사용되지 않음.데이터 관리, 애셋 로딩, 로직 처리와 같은 다양한 시스템의 기초를 형성.메모리 관리와 Garbgage Collection(가비지 컬렉션)을 지원.예시:데이터 테이블, U..
2025.01.22
no image
액터 Transform을 위한 좌표계와 부동 소수점 연산
1. 좌표계월드 좌표계게임이나 3D 환경에서 전체 세계를 기준으로 한 절대적인 좌표계Transform 함수:SetActorLocation()SetActorRotation()AddActorWorldOffset()로컬 좌표계특정 객체의 상대적인 좌표계자식 객체는 부모 객체의 로컬 좌표계를 따른다Transform 함수:AddActorLocalRotation()AddActorLocalOffset() Transform 함수 인자:NewLocation: 새로운 위치 (FVector)DeltaLocation: 이동할 거리 (FVector)bSweep: 충돌 감지 여부(true/false)OutSweepHitResult: bSweep=true인 경우, 그 충돌 결과를 담을 FHitResult 객체Teleport: 순간..
2025.01.21
no image
언리얼 엔진 C++ 빌드 프로세스
목차1. Visual Studio C++ 솔루션 구조 이해하기2. Visual Studio C++ 빌드 설정 이해3. Visual Studio C++ 빌드4. 언리얼 에디터 Live Coding5. 빌드 문제 복구1. Visual Studio C++ 솔루션 구조 이해하기Unreal Project 실제 폴더 구조  Visual Studio C++ 솔루션 구조실제 폴더 구조와 다르게 프로그래머 친화적인 가상 구조를 보여준다. 용어 정리루트: 프로젝트 최상위 디렉토리모듈(Module): 코드와 관련된 기능을 하나의 독립된 단위로 묶은 것 2. Visual Studio C++ 빌드 설정 이해하기코드 수정 -> Compile+Link -> 동적 라이브러리(DLL) -> Unreal Editor에 로드하여 반영 2..
2025.01.20
텍스트 기반 RPG 게임 제작 프로젝트 KPT 회고
KPT란?KPT(Keep/Problem/Try)는 다음을 의미Keep : 잘하고 있는 점. 계속 했으면 좋겠다 싶은 점.Problem : 문제 점. 개선이 필요한 점.Try : 잘하고 있는 것을 더 잘하기 위해서, 문제가 있는 점을 해결하기 위해서 우리가 시도해 볼 것들 Keep1. 참여도가 좋다. 서로 존중하는 자세가 돋보인다.팀원 전부 프로젝트 진행 참여 의사는 분명히 있었습니다. 평소 서로를 대할때 조심하는, 존중하는 모습이 보였습니다. Problem1. 팀원 전부가 프로젝트 전체를 이해했다고 볼 수는 없다.분명 소통은 하고 있었지만 팀원 내에 개발 경험이 많은 사람들이 없기 때문에 서로 무엇을 전달해야하는지, 어떤 방식으로 전달해야 하는지, 그리고 잘 모르고 있었습니다. 그리고 적극성이 부족했습니..
2025.01.17
Unreal Engine에서 Tick 사용법
Tick이란?Unreal Engine에서 Tick은 매 프레임마다 호출되는 함수.Tick 함수는 주로 매 프레임마다 변화하는 로직을 처리하는 데 사용. 예: 캐릭터의 위치 업데이트, 물리 연산, UI 업데이트 등.Tick의 호출 시점과 속도기본적으로 Tick은 매 프레임마다 호출됨.프레임률에 따라 속도가 결정. (예: 60 FPS일 경우 한 번의 Tick은 약 0.0167초(1/60초))프레임률에 따라 Tick의 속도는 변할 수 있으며, 이를 통해 게임의 성능을 조정할 수 있다.Tick을 언제 사용하는가?게임의 상태가 매 프레임마다 업데이트되어야 할 때 사용.예: 캐릭터 이동, 물리 계산, 이벤트 발생 등.게임 루프의 일부로 지속적인 업데이트가 필요한 경우 사용.Tick을 어떻게 사용하나?Tick은 AA..
2025.01.08
챕터 3-2: Unreal Engine 기본 개념
수업 목표Unreal Engine의 개념과 구조를 이해하고 프로젝트 생성 방법 학습.Unreal Engine의 주요 기능(UE_LOG, Random 등) 활용 방법 익히기.언리얼 엔진 특징실시간 렌더링: 뛰어난 기술로 고품질 비주얼 구현 가능.블루프린트: 프로그래밍 지식 없이 게임 로직 제작 가능.다양한 플랫폼 지원: PC, 콘솔, 모바일 등 모두 지원.활성화된 커뮤니티: 튜토리얼과 포럼이 잘 활성화됨.언리얼 엔진 설치하기(생략) 환경셋업Visual Studio에서 " C++을 사용한 게임 개발" 도구 및 기능 설치Unreal Engine editor에서 라이브 코딩 활성화 해지(VS와 충돌 방지) Actor게임 내 배치 가능한 모든 객체를 의미.예: 비행기, RPG 주인공 등. C++클래스로 Actor..
2025.01.07

충돌 검사

언리얼 거토
|2025. 1. 24. 13:00

충돌 검사(Collision Detection)란?

  • 게임 내에서 두 오브젝트가 서로 닿았는지(충돌했는지) 확인하는 과정
  • 오브젝트 간 충돌을 감지하여 물리 반응을 적용하거나 이벤트를 발생시키는 것이 충돌 검사

충돌 검사의 종류 (Unreal Engine)

1. 물리 충돌 (Physics Collision)

  • 오브젝트가 물리적으로 부딪히는 것 감지
  • 충돌 시 물리 법칙에 따른 반응 (튕기거나 멈춤)
  • 예시: 플레이어가 벽에 부딪혀 멈춤
BoxComp->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);

2. 쿼리 충돌 (Query Collision)

  • 레이캐스트(Line Trace) 또는 오버랩(Overlap)으로 충돌 감지
  • 물리 반응 없이 충돌 여부 확인
  • 예시: 아이템 근처에서 'Press E' 메시지 표시
BoxComp->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
 
 

3. 관련 코드

1. 충돌 설정 활성화 함수

BoxComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
옵션 설명
NoCollision 충돌 비활성화 (충돌 검사 X, 물리 적용 X)
QueryOnly 충돌 검사만 활성화 (충돌 반응 없음, 물리 적용 X)
PhysicsOnly 물리 적용만 활성화 (충돌 검사 X, 물리 적용 O)
QueryAndPhysics 충돌 검사 + 물리 적용 모두 활성화 (충돌 O, 물리 O)

 

2. 오브젝트의 충돌 유형(Collision Object Type) 설정 함수

BoxComp->SetCollisionObjectType(ECollisionChannel::ECC_Pawn);
충돌 채널 설명
ECC_WorldStatic 고정된 지형, 벽 등 (움직이지 않는 오브젝트)
ECC_WorldDynamic 움직이는 오브젝트 (예: 물리 오브젝트)
ECC_Pawn 플레이어나 AI 캐릭터
ECC_PhysicsBody 물리 시뮬레이션이 적용되는 오브젝트
ECC_Vehicle 차량과 관련된 오브젝트
ECC_Visibility 라인트레이스(레이캐스트) 감지용

 

3. 다른 충돌 채널에 대한 반응 함수

// 모든 채널의 오브젝트와의 충돌을 막도록 설정
BoxComp->SetCollisionResponseToAllChannels(ECR_Block);

// 캐릭터(Pawn)와의 충돌을 무시하도록 설정
BoxComp->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore);

// 정적 오브젝트와는 충돌을 막도록 설정
BoxComp->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);

// 동적 오브젝트와는 겹치도록 설정
BoxComp->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Overlap);
옵션 설명
ECR_Ignore 충돌 무시 (아예 반응 X)
ECR_Overlap 겹쳐지지만 충돌하지 않음 (예: 트리거)
ECR_Block 충돌 발생 (움직임 차단)

Pawn의 점프 후 착지 여부 판별 방법

1. 오버랩(Overlap) :

기본 충돌 영역을 정의 해주는 루트 컴포넌트(예: UBoxComponent or UCapsuleComponent)를 만들고,
Pawn이 그 영역과 겹치는지(Overlap) 확인하는 방식

  • 장점: 성능 좋음 (이벤트 기반)
  • 단점: 콜리전 설정 필요
  • C++ 예제:
//생성자
/*BoxComp->OnComponentBeginOverlap.AddDynamic(this, &ASpartaPawn::OnOverlapBegin);*/

void ASpartaPawn::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
                                 UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
                                 bool bFromSweep, const FHitResult& SweepResult)
{
    if (OtherActor && OtherActor != this && OtherComp)
    {
        // 땅에 닿았는지 확인 (충돌 대상의 태그 등을 활용 가능)
        if (OtherActor->ActorHasTag(TEXT("Ground")))
        {
            bIsJumping = false;
            GetWorldTimerManager().ClearTimer(JumpTimerHandle); // 타이머 중지
        }
    }
}
 

2. 라인트레이스(Line Trace, Raycast):

플레이어의 발 아래로 짧은 Ray를 쏴서 땅과의 거리를 체크하는 방식

  • 장점: 정확한 거리 측정 가능
  • 단점: 잦은 호출 (CPU 부담)
  • C++ 구현 코드 :
void ASpartaPawn::StartJump(const FInputActionValue& value)
{
    if (value.Get<bool>()&&!bIsJumping) // 점프 중이 아닐 때만 실행
    {
        bIsJumping = true;
        JumpVelocity = InitialJumpVelocity;
        GetWorldTimerManager().SetTimer(JumpTimer, this, &ASpartaPawn::HandleJump, 0.016f, true);
    }
}

void ASpartaPawn::StopJump(const FInputActionValue& value)
{
    if (!value.Get<bool>())
    {
        // 점프 속도 즉시 감소 (짧게 누르면 낮은 점프)
        JumpVelocity *= 0.5f;
    }
}
void ASpartaPawn::HandleJump() 
{
    if (!bIsJumping) return;

    float DeltaTime = GetWorld()->GetDeltaSeconds();

    // 중력 적용
    CurrentJumpVelocity += Gravity * DeltaTime;

    FVector NewLocation = GetActorLocation();
    NewLocation.Z += CurrentJumpVelocity * DeltaTime;

    // 땅에 닿았는지 확인
    if (IsOnFoot()) 
    {
        bIsJumping = false;
        GetWorldTimerManager().ClearTimer(JumpTimerHandle); // 타이머 중지
    }

    SetActorLocation(NewLocation, true);
}
bool ASpartaPawn::IsOnFoot()
{
    FVector Start = GetActorLocation();
    FVector End = Start - FVector(0.0f, 0.0f, TraceLength); // TraceLength: 검사할 거리

    FHitResult HitResult; // 라인 트레이스의 결과를 담을 구조체 변수
    FCollisionQueryParams Params; // 트레이스의 옵션을 설정하는 객체
    Params.AddIgnoredActor(this); // 자신은 무시

    // 디버그 라인 그리기
    DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1.0f, 0, 2.0f);
	
    //라인 트레이스 실행, 충돌 여부 검사
    bool bHit = GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Visibility, Params);

    if (bHit && HitResult.GetActor())
    {
        return true; // 땅에 닿았음
    }

    return false; // 땅에 닿지 않음
}
 
  • FHitResult HitResult
    • 목적: 라인 트레이스의 결과(충돌 정보)를 담는 구조체.
    • 내용: 충돌한 액터, 충돌 지점, 표면 법선 벡터 등의 정보를 포함.
  • FCollisionQueryParams Params
    • 목적: 라인 트레이스 실행 시 사용할 설정을 정의.
    • 내용: 충돌 무시 대상(예: 자신)을 설정하거나 특정 조건을 지정.
  • Params.AddIgnoredActor(this)
    • 목적: 자기 자신을 라인 트레이스에서 제외.
    • 내용: 트레이스가 현재 액터와 충돌하지 않도록 설정.
  • bool bHit = GetWorld()->LineTraceSingleByChannel(...)
    • 목적: 라인 트레이스를 실행하고 충돌 여부를 반환.
    • 내용:
      • Start에서 End까지 라인 트레이스를 수행.
      • 충돌 정보는 HitResult에 저장.
      • 반환값 bHit: 충돌 시 true, 아니면 false.
  • if (bHit && HitResult.GetActor())
    • 목적: 충돌 발생 여부와 충돌한 액터의 유효성 확인.
    • 내용:
      • bHit가 true이고, HitResult.GetActor()가 nullptr이 아니면 유효한 충돌로 간주.

최적의 조합

  • 기본: Overlap
  • 정확한 거리 측정 필요시: Raycast 보조적으로 사용

 

라인트레이스(RayCast)를 활용하여 구현한 예시:

 

 

 

 

 

 

Pawn 클래스 다루기

언리얼 거토
|2025. 1. 23. 21:40

오늘 작업 내용

1. Box Component 생성 및 설정

  • BoxComponent를 생성하고 루트 컴포넌트(Root Component)로 설정.
  • 기존 캐릭터의 CapsuleComponent와 유사한 역할을 수행.
  • 루트 컴포넌트 설정 이유: Pawn의 기본 충돌 영역을 정의.

#include "Components/BoxComponent.h"

ASpartaPawn::ASpartaPawn()
{
	BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("Box")); //박스 컴포넌트 생성
	RootComponent = BoxComp; //박스 컴포넌트 루트 설정
}

 

 

2. Skeletal Mesh Component 추가

  • 캐릭터 외형을 표시할 Skeletal Mesh Component 생성 및 부모 컴포넌트(Box)와 연결.

저는 거미를 좋아하지 않습니다. 그냥 Box랑 잘 어울리는 무료 Skeletal Mesh를 찾았을 뿐

ASpartaPawn::ASpartaPawn()
{
	SkeletalMeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalMesh")); //스켈레탈 메쉬 생성
	SkeletalMeshComp->SetupAttachment(BoxComp);
}

 

 

3. Spring Arm & Camera Component 추가

  • 루트 컴포넌트(Box) 하위에 Spring Arm, 그리고 Spring Arm 하위로 Camera Component를 추가하였다.

거미 엉덩이만 보게 될 것이다.

#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"

ASpartaPawn::ASpartaPawn()
{
	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	SpringArmComp->SetupAttachment(RootComponent);
	SpringArmComp->TargetArmLength = 300.0f;
	SpringArmComp->bUsePawnControlRotation = true;

	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
	CameraComp->bUsePawnControlRotation = true;
}

 

4. Enhanced Input System 구성

  • Input Action 및 Input Mapping Context 생성.
  • Player Controller에서 입력 데이터를 처리하도록 설정.
  • 현재 구현된 Action:
    1. Move: 캐릭터 이동.(SetActorLocation() 사용)
    2. Sprint: 달리기.

조만간 자유롭게 움직이게 해줄게


 

Character 클래스에 이미 구현된 기능들을 커스텀하거나 하나씩 구현해보려니 쉽지 않았습니다..  😭

내일은 시선 처리 기능인 Look, Jump 등을 구현해볼 예정



클래스 계층 구조와 리스코프 치환 원칙

  • 리스코프 치환 원칙 (LSP):
    • 하위 클래스는 언제나 상위 클래스를 대체할 수 있어야 한다.
    • 상위 클래스의 기능을 확장하거나 특수화할 수 있지만, 호환성은 유지해야 한다.
  • 언리얼 엔진의 클래스 구조:
    • Actor → Pawn → Character의 계층은 점차적으로 더 구체적인 기능을 제공.
    • 각 클래스는 리스코프 치환 원칙을 충실히 따르며, 상속을 통해 확장 가능.

1. UObject 클래스

  • 역할: 언리얼 엔진의 모든 클래스의 기본 클래스(Base Class).
  • 특징:
    • 게임 세계 안에서 직접 배치되거나 사용되지 않음.
    • 데이터 관리, 애셋 로딩, 로직 처리와 같은 다양한 시스템의 기초를 형성.
    • 메모리 관리와 Garbgage Collection(가비지 컬렉션)을 지원.
  • 예시:
    • 데이터 테이블, UI 위젯, 오디오 큐.

2. Actor 클래스

  • 역할: 게임 세계(월드) 내에서 존재할 수 있는 모든 오브젝트의 기본 클래스.
  • 특징:
    • 게임 월드에 스폰(배치)될 수 있음.
    • Transform(위치, 회전, 스케일) 정보를 가짐.
    • 컴포넌트를 통해 다양한 기능 추가 가능 (예: Static Mesh Component, Light Component).
    • 이벤트와 로직을 포함해 게임플레이 요소를 구현할 수 있음.
  • 주요 기능:
    • Tick: 매 프레임 실행되는 로직을 작성할 수 있음.
    • BeginPlay: 게임 시작 시 호출되는 초기화 함수.
  • 예시:
    • 문, 아이템, 장애물, 이동하는 플랫폼 등.

3. Pawn 클래스 (Actor를 상속)

  • 역할: 플레이어 또는 AI가 제어할 수 있는 오브젝트.
  • 특징:
    • Actor 클래스의 하위 클래스.
    • Controller를 통해 플레이어나 AI가 조작할 수 있음.
    • 자체적으로 이동 기능이 구현되지 않음(직접 구현 필요).
    • 단순히 AI 또는 플레이어의 컨트롤 가능한 몸체 역할.
  • 사용 예시:
    • 탱크, 비행기, NPC, 기본적인 캐릭터(자유로운 커스터마이징+성능 최적화에 유리)
  • 주요 함수:
    • PossessedBy: 이 Pawn을 제어하는 컨트롤러가 설정될 때 호출.
    • UnPossessed: 컨트롤러가 이 Pawn을 더 이상 제어하지 않을 때 호출.

4. Character 클래스 (Pawn을 상속)

  • 역할: 걷기, 점프, 중력과 같은 움직임이 기본적으로 구현된 Pawn.
  • 특징:
    • Capsule Component: 캐릭터의 충돌을 정의.
    • Character Movement Component: 이동 및 점프, 낙하 등의 복잡한 이동 메커니즘을 기본 제공.
    • Skeletal Mesh와 Animation 시스템을 사용하여 캐릭터의 외형과 애니메이션 적용 가능.
    • 플레이어 캐릭터나 NPC 같은 복잡한 캐릭터를 쉽게 구현할 수 있음.
  • 사용 예시:
    • 플레이어 캐릭터
  • 주요 기능:
    • Jump: 캐릭터가 점프하도록 명령.
    • MoveForward, MoveRight: 기본 입력과 연동하여 캐릭터 이동 구현.
    • 중력, 충돌 처리.
    • 애니메이션 처리.

클래스 비교

UObject 모든 클래스의 기본 클래스.
직접 배치되지 않음.
데이터 관리, 가비지 컬렉션 UI 위젯, 데이터 테이블, 오디오 큐
Actor 게임 월드 내 배치 가능한 모든 오브젝트의 기본 클래스. Transform, Tick, BeginPlay 문, 아이템, 장애물
Pawn 플레이어 또는 AI가 제어 가능한 Actor. Controller 연동, Possess 기능 탱크, 비행기, AI 제어
가능한 몸체
Character 이동, 중력, 점프가 구현된 Pawn. Character Movement Component, Animation 플레이어 캐릭터, NPC

 


✏️ 내일은 Pawn 클래스로 Character 클래스의 기능들을 구현해볼 예정입니다. 그 전에 간략하게 관련 클래스 계층 구조를 알아봤습니다. 고양이 같은 동물을 구현해보고 싶은데 리깅된 무료 3D 모델을 아직 못 구했네요ㅜ 유능한 3D 모델러를 구하고 싶다는 생각이 들었습니다. 


1. 좌표계

월드 좌표계

  • 게임이나 3D 환경에서 전체 세계를 기준으로 한 절대적인 좌표계
  • Transform 함수:
    • SetActorLocation()
    • SetActorRotation()
    • AddActorWorldOffset()

로컬 좌표계

  • 특정 객체의 상대적인 좌표계
  • 자식 객체는 부모 객체의 로컬 좌표계를 따른다
  • Transform 함수:
    • AddActorLocalRotation()
    • AddActorLocalOffset()

 

Transform 함수 인자:

  • NewLocation: 새로운 위치 (FVector)
  • DeltaLocation: 이동할 거리 (FVector)
  • bSweep: 충돌 감지 여부(true/false)
  • OutSweepHitResult: bSweep=true인 경우, 그 충돌 결과를 담을 FHitResult 객체
  • Teleport: 순간 이동 여부(none이면 부드럽게 이동)

 

예시:

void SetActorLocation(FVector NewLocation, bool bSweep = false, FHitResult* OutSweepHitResult = nullptr, ETeleportType Teleport = ETeleportType::None);
void AddActorLocalRotation(FRotator DeltaRotation, ETeleportType Teleport = ETeleportType::None);

 

좌표계 확실히하고 가자! 액터를 자전시키고 싶은데 공전하는 현상이 없도록


2. 부동 소수점의 문제

부동 - 소수점 위치가 고정되지 않고 이동(floating)할 수 있다~

2-1. C++에서 float와 double의 차이

  1. float
    • 32비트(4바이트) 크기의 부동 소수점 숫자.
    • 소수점 이하 약 7자리의 정밀도를 가짐.
    • 메모리 사용량이 적고, 연산 속도가 더 빠름.
  2. double
    • 64비트(8바이트) 크기의 부동 소수점 숫자.
    • 소수점 이하 약 15~16자리의 정밀도를 가짐.
    • 메모리를 더 많이 사용하고, 더 높은 정밀도가 필요할 때 사용.

접미사를 붙이지 않은 숫자는 기본적으로 double로 처리

게임 개발에서는 많은 계산이 이루어지기 때문에 float를 선호

 

2-2. 부동 소수점 연산의 한계

기본 개념

  • 부동 소수점(Floating-point): 컴퓨터가 실수를 표현하기 위해 사용하는 방법으로, 정확한 숫자가 아닌 근사치를 저장.
  • 정밀도 제한: 부동 소수점은 제한된 비트 수로 숫자를 표현하므로, 연산 중에 작은 오차가 발생.
  • 연산 결과 오차: 반복 연산에서 오차가 누적될 가능성이 있음.

참고 자료

 

2-3. 플랫폼 이동 구현에서의 핵심 문제

문제의 본질

  • 플랫폼이 목표 위치에 정확히 도달하지 못하는 이유는 부동 소수점 연산의 정밀도 문제로 조건이 만족되지 않기 때문.
  • 특히, FVector::Dist로 계산한 거리와 작은 임계값(Threshold)을 비교할 때 조건이 false로 평가되면 방향 반전이 발생하지 않음.

Unreal Engine 관련 주요 함수

  • FVector::Dist
    두 점 간의 유클리드 거리를 계산:
float FVector::Dist(const FVector& V1, const FVector& V2);
  • FMath::IsNearlyEqual
    두 부동 소수점 값을 일정 임계값 내에서 비교:
bool FMath::IsNearlyEqual(float A, float B, float ErrorTolerance);

 

2-4. 임계값 설정의 중요성

일반적인 해결 방법

  • 비교할 때 일정한 버퍼(zone)를 만들어 작은 오차를 허용.
  • 정수 연산하기.

임계값 선택 시 고려 사항

  • 임계값이 너무 작으면 부동 소수점 오차로 조건이 만족되지 않을 가능성이 있음.
  • 임계값이 너무 크면 목표에 도달하기 전에 조건이 만족될 수 있음.

 

✏️ 단순 비주얼 스튜디오 스크립팅과 미묘하게 다른 점이 많아 신경쓸 부분들이 있었습니다.

임계값 설정 때문에 테스트를 정말 많이 해봤네요..ㅎㅎ

섬세함이 요구되는 개발..  나랑 너무 어울림


 

'TIL > C++와 UE' 카테고리의 다른 글

회전 관련 함수 및 Pawn 클래스 Look 함수  (1) 2025.01.27
충돌 검사  (0) 2025.01.24
Pawn 클래스 다루기  (0) 2025.01.23
언리얼 엔진 클래스 계층 구조  (0) 2025.01.22
언리얼 엔진 C++ 빌드 프로세스  (0) 2025.01.20

목차

1. Visual Studio C++ 솔루션 구조 이해하기

2. Visual Studio C++ 빌드 설정 이해

3. Visual Studio C++ 빌드

4. 언리얼 에디터 Live Coding

5. 빌드 문제 복구


1. Visual Studio C++ 솔루션 구조 이해하기

Unreal Project 실제 폴더 구조

 

Visual Studio C++ 솔루션 구조

  • 실제 폴더 구조와 다르게 프로그래머 친화적인 가상 구조를 보여준다.

 

용어 정리

루트: 프로젝트 최상위 디렉토리

모듈(Module): 코드와 관련된 기능을 하나의 독립된 단위로 묶은 것

 

2. Visual Studio C++ 빌드 설정 이해하기

코드 수정 -> Compile+Link -> 동적 라이브러리(DLL) -> Unreal Editor에 로드하여 반영

 

2-1. 빌드 구성 및 플랫폼

빌드 구성(Configuration)

  • DebugGame
    • 게임 로직만 디버그 가능, 엔진은 최적화 상태.
    • 독립 실행 파일 환경에서 디버깅.
  • DebugGame Editor
    • 에디터에서 게임 로직 디버깅 가능.
    • 에디터 플레이 중 브레이크포인트 설정 지원.
  • Development
    • 디버그 정보를 최소화하여 실행 속도 향상.
    • 독립 실행 파일 환경에서 테스트 및 개발용.
  • Development Editor
    • 에디터에서 개발과 테스트를 위한 빌드.
    • Live Coding에 적합, 초·중급자용 기본 모드.
  • Shipping
    • 최송 배포용.
    • 디버그 정보 제거, 성능 최적화 극대화.

 

플랫폼(Platform) 설정

  • 모바일 (Android, iOS), 콘솔 (PS, Xbox 등)로 빌드하려면 해당 플랫폼용 SDK 추가 설치 필요.

 

3. Visual Studio에서 C++ 빌드

전체 솔루션 빌드(Ctrl + Shift + B)

  • 모든 모듈을 통째로 빌드.
  • 첫 빌드 or 엔진 소스 수정 or 엔진 전체 파일 필요한 경우.

부분 빌드

  • 프로젝트 우클릭 -> Build
  • C++ 로직만 수정했을 경우 다른 모듈을 제외한 게임 프로젝트 코드만 빠르게 빌드.

빌드 시 주의 사항

  • 빌드 전 Unreal Editor 닫기(DLL 교체 못해 에러 발생),
  • 빌드 후 Set as Startup Project로 프로젝트 실행 대상 설정.
    • 디버깅 시 실행될 기본 프로젝트로 설정

 

4.  Live Coding...

(에디터 연결 종료 안한채) C++ 코드 수정 → Live Coding으로 변경 사항만 컴파일 → 에디터에 즉시 로직 반영”

 

근데 뭔가 아직 에러 나는 것 같은데 그냥 쓰지 말까 싶다. 비활성화 

 

5. 빌드 문제 복구

 

  1. 에디터와 Visual Studio 종료
    • 빌드 파일 잠금을 방지하려면 모두 종료 후 재시작.
  2. Intermediate, DerivedDataCache, Saved 폴더 삭제
    • 임시 데이터 삭제 후 빌드로 캐시 문제 해결.
  3. .uproject 파일 → “Generate Visual Studio project files”
    • 솔루션 및 설정을 재생성하여 구성 복구.
  4. Visual Studio에서 클린 빌드
    • Clean Solution으로 기존 빌드 정리 후 Build Solution으로 재빌드.
    • 에러 발생 시 Output 창과 Error List 확인.
  5. 언리얼 에디터 재실행
    • 코드 변경 사항 확인.
    • 문제 지속 시 로그 파일 확인 및 엔진/프로젝트 설정 점검.

✏️ 오늘 조가 바뀌었는데 게임 개발 경험이 있는 분들이 3분이나 계십니다.

개별 프로젝트 진행 해보자는 이야기가 나와서 기대도 되지만 오늘은 따라가느라 바빴네요😂

함 해보죠 뭐..

 

 

KPT란?

KPT(Keep/Problem/Try)는 다음을 의미

  • Keep : 잘하고 있는 점. 계속 했으면 좋겠다 싶은 점.
  • Problem : 문제 점. 개선이 필요한 점.
  • Try : 잘하고 있는 것을 더 잘하기 위해서, 문제가 있는 점을 해결하기 위해서 우리가 시도해 볼 것들

 

Keep

1. 참여도가 좋다. 서로 존중하는 자세가 돋보인다.

팀원 전부 프로젝트 진행 참여 의사는 분명히 있었습니다. 평소 서로를 대할때 조심하는, 존중하는 모습이 보였습니다.

 

Problem

1. 팀원 전부가 프로젝트 전체를 이해했다고 볼 수는 없다.

분명 소통은 하고 있었지만 팀원 내에 개발 경험이 많은 사람들이 없기 때문에 서로 무엇을 전달해야하는지, 어떤 방식으로 전달해야 하는지, 그리고 잘 모르고 있었습니다. 그리고 적극성이 부족했습니다.

 

2. 시간을 준수하지 않았다.

프로젝트 마감 하루 전날에 전체 코드들의 결합을 완성하고 여유가 있을 시 추가 기능을 살펴보자는 계획이 있었습니다. 사실 제출 마지막까지 코드를 붙잡고 있던 사람은 아니기에 정확한 이유는 모르나, 정한 시간내에 특정 기능이 제대로 작동되지 않으면 해당 부분을 과감히 버려야된다고 생각합니다(그 기능이 필수나 도전일지라도). 시간을 준수하지 않으면 팀의 활동이 예측불가능해지기 때문에 전체가 삐걱댑니다.

 

 

 

Try:

1. 팀이 프로젝트를 Follow-up 할 수 있는 기회 또는 방법을 제공해 보자.

  • 회의때 특정 시간동안 이루어낸 작업에 대한 설명을 간단히 하는 시간을 갖는 방법
  • 개인 공부 시간을 갖는 방법
  • Github Read.me와 comment를 꼼꼼히 작성하는 방법 

2. 시간을 준수해보자

  • Notion 같은 계획표 철저히 활용
  • 달성 가능한 목표 설정

Unreal Engine에서 Tick 사용법

언리얼 거토
|2025. 1. 8. 23:00

 

Tick이란?

  • Unreal Engine에서 Tick은 매 프레임마다 호출되는 함수.
  • Tick 함수는 주로 매 프레임마다 변화하는 로직을 처리하는 데 사용.
    • 예: 캐릭터의 위치 업데이트, 물리 연산, UI 업데이트 등.
  • Tick의 호출 시점과 속도
    • 기본적으로 Tick은 매 프레임마다 호출됨.
    • 프레임률에 따라 속도가 결정. (예: 60 FPS일 경우 한 번의 Tick은 약 0.0167초(1/60초))
    • 프레임률에 따라 Tick의 속도는 변할 수 있으며, 이를 통해 게임의 성능을 조정할 수 있다.
  • Tick을 언제 사용하는가?
    • 게임의 상태가 매 프레임마다 업데이트되어야 할 때 사용.
    • 예: 캐릭터 이동, 물리 계산, 이벤트 발생 등.
    • 게임 루프의 일부로 지속적인 업데이트가 필요한 경우 사용.
  • Tick을 어떻게 사용하나?
    • Tick은 AActor 클래스의 함수로 구현.
      • 예를 들어, AMyActor2::Tick(float DeltaTime)와 같이 정의.
    • 매 프레임마다 호출되며, DeltaTime을 인자로 받아 프레임 간 시간 차이를 사용 가능.
  • Tick의 속도 조절 방법
    • PrimaryActorTick.TickInterval을 설정하여 Tick 간의 간격을 조정.
    • 예를 들어, PrimaryActorTick.TickInterval = 1.0f;로 설정하면, 1초에 한 번만 Tick을 호출.
  • Tick을 멈추는 방법
    • PrimaryActorTick.bCanEverTick = false;로 설정하여 Tick을 비활성화.
    • SetActorTickEnabled(true/false) <- 동적으로 Tick을 활성/비활성
    • 예를 들어, 일정 조건을 만족했을 때 Tick을 멈추고 싶을 때 사용.
  • Tick 사용 예시
    • AMyActor2 클래스에서 Tick을 사용하여 이동 로직과 이벤트를 발생시키는 예시
void AMyActor2::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    
    // 이동 및 이벤트 발생
    int32 XStep = Step();
    int32 YStep = Step();
    NewPosition.X = CurrentPosition.X + XStep;
    NewPosition.Y = CurrentPosition.Y + YStep;
    
    // 이동 거리와 이벤트를 로그에 출력
    UE_LOG(LogTemp, Display, TEXT("Position: (%f, %f)"), NewPosition.X, NewPosition.Y);
    createEvent(50);

    CurrentPosition = NewPosition;
    CurrentStep++;

    // 모든 이동이 끝나면 Tick 비활성화
    if (CurrentStep >= 10)
    {
        PrimaryActorTick.bCanEverTick = false;
    }
}

 

 

Tick 속도 문제 해결하기

  • TickInterval을 Tick의 속도를 조절할 수 있다. 또는 DeltaTime을 이용해 프레임 독립적인 이동을 구현할 수도 있다.
  • 예를 들어, 이동을 DeltaTime에 비례하도록 하면 다양한 FPS에서도 일정한 속도로 이동할 수 있다.

'TIL > C++' 카테고리의 다른 글

학생 성적 관리 시스템 (STL 활용)  (0) 2025.02.10
챕터 3-2: Unreal Engine 기본 개념  (2) 2025.01.07
챕터 3-1: 디자인 패턴  (0) 2025.01.06
챕터 2-4: 객체지향적 설계  (1) 2025.01.03
챕터 2-3 : STL 기초  (1) 2025.01.02

챕터 3-2: Unreal Engine 기본 개념

언리얼 거토
|2025. 1. 7. 20:09

수업 목표

  • Unreal Engine의 개념과 구조를 이해하고 프로젝트 생성 방법 학습.
  • Unreal Engine의 주요 기능(UE_LOG, Random 등) 활용 방법 익히기.

언리얼 엔진 특징

  • 실시간 렌더링: 뛰어난 기술로 고품질 비주얼 구현 가능.
  • 블루프린트: 프로그래밍 지식 없이 게임 로직 제작 가능.
  • 다양한 플랫폼 지원: PC, 콘솔, 모바일 등 모두 지원.
  • 활성화된 커뮤니티: 튜토리얼과 포럼이 잘 활성화됨.

언리얼 엔진 설치하기

(생략)

 

환경셋업

  • Visual Studio에서 " C++을 사용한 게임 개발" 도구 및 기능 설치
  • Unreal Engine editor에서 라이브 코딩 활성화 해지(VS와 충돌 방지)

Actor

  • 게임 내 배치 가능한 모든 객체를 의미.
  • 예: 비행기, RPG 주인공 등.

C++클래스로 Actor 생성(한글 이름X) -> Visual Studio 자동 생성 -> UE_LOG 추가 -> 액터 배치(드래그) -> 출력로그 확인 

 

코드 예제: 369 게임

int Start = 1; 
int End = 30;

for (int i = Start; i <= End; ++i)
{
    FString Number = FString::FromInt(i);
    bool bIsClap = false;

    for (TCHAR Char : Number)
    {
        if (Char == '3' || Char == '6' || Char == '9')
        {
            bIsClap = true;
            break;
        }
    }

    if (bIsClap)
    {
        UE_LOG(LogTemp, Warning, TEXT("짝"));
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("%d"), i);
    }
}

 

코드 예제: 랜덤 숫자 합계 출력

int MinValue = 1;
int MaxValue = 100;

int RandomNumber1 = FMath::RandRange(MinValue, MaxValue);
int RandomNumber2 = FMath::RandRange(MinValue, MaxValue);
int RandomNumber3 = FMath::RandRange(MinValue, MaxValue);

int Sum = RandomNumber1 + RandomNumber2 + RandomNumber3;

UE_LOG(LogTemp, Warning, TEXT("Generated Numbers: %d, %d, %d"), RandomNumber1, RandomNumber2, RandomNumber3);
UE_LOG(LogTemp, Warning, TEXT("Sum of Numbers: %d"), Sum);

UE_LOG 사용법

  • 구조
    1. 카테고리: 로그를 분류하는 태그.
    2. 심각성: 로그의 중요도(색상으로 구분).
    3. 내용: 출력할 메시지.
      • 디버깅과 정보 확인에 매우 유용
  • 예시
UE_LOG(LogTemp, Log, TEXT("Game has started."));
UE_LOG(LogTemp, Display, TEXT("Welcome, %s!"), *PlayerName);
UE_LOG(LogTemp, Warning, TEXT("Player health is below maximum: %d"), PlayerHealth);
UE_LOG(LogTemp, Error, TEXT("No ammo left!"));

Unreal Engine + Visual Studio 사용 시 유의사항

프로젝트 관리

  • Unreal은 .uproject 파일 사용, Visual Studio의 .sln 파일은 사용하지 않음.
  • Unreal Editor나 Ctrl + Shift + B로 빌드.
  • Generated.h와 같은 자동 생성된 파일은 수정하지 않음.

Unreal에서의 코드 작성

  • 문자열은 TEXT() 매크로로 감싸기 (예: TEXT("Hello")).
  • 출력은 std::cout 대신 UE_LOG 사용.
  • Unreal 스타일 가이드에 맞게 UCLASS, UPROPERTY, UFUNCTION 매크로 사용.

헤더 파일과 소스 파일

클래스 선언은 헤더 파일에, 정의는 CPP 파일에 작성.

  • Unreal에서는 클래스를 헤더 파일에 선언하고, 메서드 구현은 CPP 파일에서 하는 것이 일반적.
  • 클래스 선언은 헤더 파일에, 정의는 CPP 파일에 작성.
    • Unreal에서는 클래스를 헤더 파일에 선언하고, 메서드 구현은 CPP 파일에서 하는 것이 일반적.
// Header file (.h)
UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

public:
    void MyMethod();
};

// Source file (.cpp)
void AMyActor::MyMethod() 
{
    // method implementation
}
  • 헤더 파일에서의 선언은 클래스 인터페이스 제공.
  • CPP 파일에서 메서드 정의로 구현. 이렇게 하면 코드가 더 깔끔하고 컴파일 성능도 향상됨.

디버깅 및 로그

  • Breakpoints를 설정하여 Unreal Editor와 Visual Studio에서 디버깅 가능.
  • Saved/Logs 폴더에서 Crash 로그 확인.

기타 팁

  • Unreal의 API 문서를 활용하여 함수와 클래스 사용법 확인.
  • 작은 기능 추가 후 바로 Unreal Editor에서 핫 리로드로 테스트.

기타의 기타

  • 두 점 사이의 거리는 **FVector::Dist()**로 계산.
float Distance = FVector::Dist(PointA, PointB);
  • 다국어 지원 시 FText 사용.
FText WelcomeMessage = NSLOCTEXT("MyGame", "Welcome", "Welcome to the Game!");
  • 위치나 방향은 FVector, 문자열은 FString 사용.
FVector Location = FVector(0.0f, 0.0f, 0.0f);
FString PlayerStatus = FString::Printf(TEXT("Player: %s, Health: %d"), *PlayerName, Health);

'TIL > C++' 카테고리의 다른 글

학생 성적 관리 시스템 (STL 활용)  (0) 2025.02.10
Unreal Engine에서 Tick 사용법  (0) 2025.01.08
챕터 3-1: 디자인 패턴  (0) 2025.01.06
챕터 2-4: 객체지향적 설계  (1) 2025.01.03
챕터 2-3 : STL 기초  (1) 2025.01.02