게임 제작 Base 82

클래스 생성 시, 부모 클래스 선택

언리얼 엔진을 다루다 보니, 문득 언리얼 엔진의 "C++ 클래스 생성 툴"은 왜 있는건지가 궁금해졌다. 이는 전적으로 편의성을 위해 만들어진 것이라고 한다. 초기 언리얼 개발자들은 새 클래스를 만들 때, 1. 헤더파일을 직접 만들고2. 소스파일을 직접 만들고3. #include, UCLASS(), GENERATED_BODY(), public 상속까지 모두 다 직접 코드로 타이핑해야 했다고 함. 그래서 Epic은 편의성을 위해, "New C++ Class Wizard"를 만들어서 수작업으로 할 법한 일들을 자동화하였고, 이것이 지금 우리가 쓰고 있는 C++ 클래스 생성 툴이라고 한다. 이 툴은 이러한 기능들을 한다고 보면 됨.1. 부모 클래스를 선택 : 적절한 헤더를 포함하여 상속 구조까지 자동으로 완성해..

Task, Service, Decorator와 BlackboardBase 상속

BlackboardBase 클래스를 상속받는 기준구분 기준- 블랙보드에 있는 Key 값을 직접적으로 사용하는지 여부- 즉, GetSelectedBlackboardKey() 를 쓸 필요가 있는지로 판단하면 된다.일반 클래스(Task, Service, Decorator)- 블랙보드에 직접 접근할 필요가 없거나, 외부 컴포넌트로만 처리 가능할 때ex)- UBTTask_TryAttack : 애니메이션 재생, 타이머 대기 등은 블랙보드 키가 없어도 실행 가능. 상태나 컴포넌트에서 정보만 가져오면 충분하다. 블랙보드에 접근할 필요 없이, 그냥 공격만 수행하면 됨.BlackboardBase기반 클래스- 블랙보드 키를 사용하는 Task / Service / Decorator인 경우- 블랙보드에서 TargetActor,..

언리얼 엔진의 AI

언리얼 엔진 AI의 핵심 구조 : Behavior Tree 시스템- 언리얼에서는 AI의 행동을 시각적으로 구성하고 관리하기 위해 다음과 같은 시스템을 사용함AIController- AI 캐릭터를 제어하는 실제 C++ 클래스- BT를 실행하는 껍데기Behavior Tree(BT)- AI의 생각 구조를 트리 형태로 시각화한 것- 인공지능의 핵심- 위에서 아래, 왼쪽에서 오른쪽으로 판단하고 실행(DFS)Blackboard- AI가 행동을 판단할 때 참고하는 데이터 저장소 / 메모장 / 기억 창고- AI가 기억하고 있는 정보(타겟 위치, 체력, 사망 여부 등)를 저장해둠- BTTask, BTService, BTDecorator 모두 이 데이터를 읽고 판단함BTTask- 실제 행동을 수행하는 노드 (공격, 이동 ..

Interface 1편

특정 기능을 구현할 것을 약속한 추상 형식을 의미.객체(클래스)가 반드시 구현해야 할 기능을 지정하는데 사용.다형성의 구현, 의존성이 분리된 설계에 유용하게 활용잠재적으로 무관한 클래스 세트가 공통의 함수 세트를 구현할 수 있도록 하는데 쓰임. 그대로라면 유사성이 없었을 크고 복잡한 클래스들에 어떤 게임 함수 기능을 공유시키고자 하는 경우에 사용. 언리얼 C++ 인터페이스는 추상 타입으로 강제되지 않고, 내부에 기본 함수를 구현할 수 있음UINTERFACE클래스는 실제 인터페이스가 아니다. 언리얼 엔진의 리플렉션 시스템에 보이도록 하기 위해서만 존재하는 비어 있는 클래스임.함수를 헤더 파일에 직접 작성가능기본적으로 아무것도 하지 않는 함수이거나 사소한 동작을 하는 함수의 경우에 작성. 복잡한 함수는 소스..

Texture Streaming Pool

텍스쳐 스트리밍 메모리 예산을 초과했을 때 발생하는 현상.고해상도 텍스쳐를 GPU에 로딩할 수 없어서 낮은 LOD 텍스쳐(혹은 가짜 텍스쳐)만 보이게 됨(캐릭터들이 진흙처럼 나옴)이 현상의 원인텍스쳐 스트리밍 시스템- GPU의 VRAM을 절약하기 위해, 자주 보이는 텍스쳐는 고해상도로 로딩하고 멀리 있거나 안 보이는 텍스쳐는 낮은 해상도만 로딩하도록 자동으로 처리해주는 시스템.문제 발생 원인- 그런데 사용 중인 텍스쳐 전체의 예상 메모리 사용량이 스트리밍 예산(PoolSize)을 초과하면 문제가 발생함.- 고해상도 텍스쳐를 로딩할 여유가 없어져서- 낮은 LOD 텍스쳐 또는 대체 텍스쳐만 로딩되고- 결과적으로 캐릭터가 진흙처럼 보이게 된다해결 방법 1- 콘솔 명령어로 예산을 임시로 늘리기- 게임 실행 중..

언리얼 엔진에서의 이름 짓기

언리얼 개발자들은 일부러 변수명을 길게 쓰고, 그게 훨씬 편하다고 생각함게임 유저 입장에서는 AP, AD, Atk, Dmg, Spd 등등으로 사용하는게 빠르고 편하지만, 이건 어디까지나 유저의 입장일 뿐이고 개발자의 입장에서는 완전히 다르다 변수 이름을 축약해서 사용하면 안좋은 이유코드의 명확성을 최우선으로 해야함언리얼 엔진은 초거대 프로젝트에 최적화된 엔진임. 즉, 개발자 혼자 코딩하는 것이 아니라 수십~수백명이 같이 작업하게 됨그러므로 단어 하나하나가 직관적으로 명확히 읽혀서, 1초라도 더 빠르게 의미를 이해하는 것이 매우 중요함변수명이 짧으면 편할 것 같지만, 축약어로 인해 0.5초라도 "이게 무슨 변수였더라?" 하고 고민하는 시간이 생긴다면 그것 자체가 팀 전체에게 손해임언리얼은 블루프린트와 같이..

함수 파라미터와 멤버 변수의 이름 충돌로 인한 오류

EnemyCharacter에 ApplyDamage_Implementation을 구현하고 나서 빌드하는데 자꾸 빌드 오류가 발생함. 그런데 EnemyCharacter의 함수를 주석처리하여 확인해보니, PlayerCharacter에 선언한 ApplyDamage_Implementation과 완전히 동일하게 선언했는데도 불구하고, PlayerCharacter의 함수는 정상적으로 빌드가 되는데 EnemyCharacter에 선언한 함수에서만 자꾸 오류가 발생하여 빌드가 안됨. 자꾸 "DamageAmount 선언은 클래스 멤버를 숨깁니다" 라는 오류 문구가 떠서 이게 도대체 무슨 말인가 싶었었다.그래서 한참을 이것저것 바꿔보고 고민하고 하다가 발견한 충격적인 사실... 위에 "플레이어 피격 테스트용 변수들" 에 ..

Capsule Component

캡슐 컴포넌트의 역할1. 이동 충돌 처리(CharacterMovement 기준)- 언리얼 ACharacter는 움직임의 중심 충돌체로 캡슐 컴포넌트를 사용함- 벽과의 충돌, 지면과의 접촉, 중력, 점프 모두 이 캡슐을 기준으로 처리됨- 예를 들어, 벽에 부딪힐 때는 Mesh가 아니라 벽에 캡슐이 닿는지를 검사함2. 루트 콜리젼(모든 컴포넌트들의 기준 위치)- 캡슐 컴포넌트가 루트 컴포넌트이기 때문에, 모든 위치 계산(스폰, 회전, 이동 등)은 이걸 기준으로 함3. 기본 충돌 판정(Overlap, Trace충돌, Pawn Detection 등)- 적 AI의 감지도, 플레이어의 충돌 판정도 캡슐이 대표하는 Actor Collision으로 작동하는 경우가 많음 메시 콜리젼의 역할스켈레탈 메시에도 콜리전이 붙어..

#include 인텔리센스 에러

Visual Studio 업데이트가 있길래 업데이트를 받았는데, 그 기점으로 에러가 발생#include "헤더파일" 에서, 현재 파일이 속해있는 폴더 외의 다른 폴더를 인식을 못함ex)Source / SOJ / Animation : Anim_Common, Anim_Player, Anim_EnemySource / SOJ / Character : BaseCharacter, PlayerCharacter, EnemyCharacter이런 폴더 구조라면, Anim_Common에서 #include 를 하면, 자동완성에 Animation 폴더만 잡힘Anim_Common이 존재하는 폴더가 아닌 다른 폴더인 Character 폴더는 아예 자동완성에 잡히질 않음 별에 별 짓을 다 해보았지만 결국 해결 못함.vs / Save..

Delegate 2편

C++ 객체에서만 사용가능한 델리게이트- .Bind- .BindUObject- .Unbind- .Add- .AddUObject- .Remove / .RemoveAllC++과 블루프린트 객체가 모두 사용가능한 델리게이트Dynamic Delegate- 여기에 바인딩 할 함수는 UFUNCTION() 으로 선언 필수 - .BindDynamic- .AddDynamic- .RemoveDynamicSingleCast & MultiCast- 함수 1개를 바인드하여 사용- DECLARE_DELEGATE- DECLARE_DYNAMIC_DELEGATE- 함수 여러개를 바인드하여 사용- 바인딩 된 모든 함수들을 동시에 호출- DECLARE_MULTICAST_DELEGATE- DECLARE_DYNAMIC_MULTICAST_DE..