일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 224일선
- 1일차
- 주식단테
- 전주비빔 라이스 버거
- 2023 구글 클라우드
- 112일선
- 작계훈련
- 스포일러 주의
- unity
- 리팩터링 4장
- 2023 게이밍 인 구글 클라우드
- 공부
- 언리얼5
- shader
- 스즈메의 문단속
- 448일선
- GenAI
- 상계9동
- 리팩터링
- 언리얼 5
- 이득우의 언리얼 프로그래밍1
- 산토리 하이볼
- 구글 컨퍼런스
- 2023 Gaming
- 주식
- URP
- JavaScript
- 리팩터링 3장
- 2023 게이밍
- 이득우의 언리얼 프로그래밍 1
- Today
- Total
개발 이야기 안하는 개발자
언리얼5_1_1 : 언리얼 오브젝트의 이해 본문
셋팅
언리얼 매크로할때 도움이 되는 툴 : https://vlasovstudio.com/visual-commander/
언리얼 탭 자동줄맞춤 : https://github.com/hackalyze/ue4-vs-extensions
언리얼 작업을 진행하며 알아 둘 점
- 비주얼 스튜디오에서 수동으로 클래스 추가하지 말 것
- 헤더가 변경되면 에디터를 끄고 컴파일할것. (Ctrl + Shift + B)
- 소스파일이 변경되면 라이브 코딩으로 컴파일할 것.(Ctrl + Alt + F11)
- 에디터 없이 컴파일이 안된다면 Ctrl + F5로 빌드해서 에러나는지 확인해 볼 것. (언리얼 쪽에서 꼬인내용일 수 있음)
구글 코딩 스타일 : https://google.github.io/styleguide/cppguide.html
언리얼 C++ 코딩 표준 : https://docs.unrealengine.com/5.1/ko/epic-cplusplus-coding-standard-for-unreal-engine/
언리얼 코딩 표준
언리얼 오브젝트 : https://docs.unrealengine.com/5.1/ko/objects-in-unreal-engine/
- 파스칼 케이싱 사용
- 언리얼 Object를 상속받는 클래스들은 접두사U 가 붙는다. (예 -> UMyGameInstance)
- AActor는 A를, SWidget은 S를, Interface는 I를, 열거형은 E를, 부울 변수는 b를, 그 외 C++ Class F를 붙인다.
- auto 에 너무 많은 의존을 하는것은 권장하지 않는다.
- 포인터를 쓸때는 Type바로옆에 붙이는 것을 추천한다. (Find in Files에서 못읽어 올수도 있음. 예 : T* val)
bool을 사용할땐 크기가 명확하지 않음.
그렇기 때문에 bool 대신에 uint8을 사용하고, Bit Field 오퍼레이터를 사용해서 크기를 다시 재구성한다.
(해당 내용은 데이터 저장에 사용될때 보통 정의되며, 소스코드에서는 편하게 bool을 사용하면 됨)
uint8 bNetTemp:1;
언리얼 인코딩
캐릭터 인코딩 : https://docs.unrealengine.com/5.1/ko/character-encoding-in-unreal-engine/
FString 클래스 : https://docs.unrealengine.com/5.1/ko/fstring-in-unreal-engine/
FName 클래스 : https://docs.unrealengine.com/5.1/ko/fname-in-unreal-engine/
데이터를 저장할때 정렬을 제대로 해야 프로그램의 최대 효율을 사용할 수 있음.
그렇기 때문에 언리얼에선 애매모호한 int가 아닌 uint8, int32 같이 명확하게 표기하도록 함.
서양권에선 1바이트로 언어 표현이 되었지만 아시아권으로 넘어오면서 확장이 되었음.
이때 사용되는 인코딩 방식이 다양해지면서 언리얼은 TCHAR라고 하는 고유 문자 처리 방식을 사용하기로 함.
언리얼은 인코딩을 하는데 UTF-16을 사용한다. (TEXT 매크로 - 2바이트 UTF-16으로 인코딩함)
코드를 작성하고, 한글이 포함된 경우 에러가 발생할 수 있다. 윈도우에서 한글을 사용해서 인코딩이 정상적으로 이루어지지 않았기 때문이다. (CP949형태 멀티 바이트 스트링으로 저장되었기 때문).
이땐 사용한 스크립트 파일을 클릭후 Save As를 눌러 인코딩 옵션을 UTF-8로 수정하면 된다.
언리얼 로그
UE_LOG(<LOG_CATEGORY>, <VERBOSITY_LEVEL>, TEXT("My log string."));
예 : UE_LOG(LogTemp, Warning, TEXT("Hello World"));
TCHAR와 FString
TCHAR LogCharArray[] = TEXT("Hello unreal Umin");
UE_LOG(LogTemp, Log, TEXT("%s") , LogCharArray);
FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString);
FString은 동적 배열 TArray를 가지고 있다. 따라서, 사용할때는 포인터를 붙여서 가르키고 있는 대상(TArray)을 사용해야 한다.
FString이 가지고 있는 TArray의 데이터를 가져오기
const TCHAR* LogCHarPtr = *LogCharString;
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData();
FString이 가지고 있는 TArray를 TCHAR로 가져오기
TCHAR LogCharArrayWithSize[100];
FCString::Strcpy(LogCharArrayWithSize, LogCharString.Len(), *LogCharString);
FString 비교 / 찾기 / 자르기
if (LogCharString.Contains(TEXT("unreal"), ESearchCase::IgnoreCase))
{
int32 Index = LogCharString.Find(TEXT("unreal"), ESearchCase::IgnoreCase);
FString EndString = LogCharString.Mid(Index);
UE_LOG(LogTemp, Log, TEXT("Find Test : %s"), *EndString);
}
FString 자르기2
FString Left, Right;
if (LogCharString.Split(TEXT(" "), &Left, &Right))
{
UE_LOG(LogTemp, Log, TEXT("Split Test : %s 와 %s"), *Left, *Right);
}
FString float To String / Int To String
int32 IntValue = 32;
float FloatValue = 3.141592;
FString floatIntString = FString::Printf(TEXT("Int : %d , Float : %f"), IntValue, FloatValue);
FString floatString = FString::SanitizeFloat(FloatValue);
FString IntString = FString::FromInt(IntValue);
UE_LOG(LogTemp, Log, TEXT("%s"), *floatIntString);
UE_LOG(LogTemp, Log, TEXT("Int:%s Float%s"), *IntString, *floatString);
FString String To float / String To Int
int32 IntValueFromString = FCString::Atoi(*IntString);
float FloatValueFromString = FCString::Atof(*floatString);
FString FloatIntString2 = FString::Printf(TEXT("int : %d , float : %f"), IntValueFromString, FloatValueFromString);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString2);
FName
애셋 관리에 사용됨. (빌드시 해시값으로 변환되기 때문에 문자 표현용이 아님)
- 대소문자 구분 없음.
- 한번 선언시 수정할 수 없음.
- 가볍고 빠름.
값을 넣으면 어딘가에 Value가 저장이 되고, 반환은 Key값이 변환이 된다. (Key는 해시값)
따라서, 찾거나 저장하기에 굉장히 유용하다.
FName key1(TEXT("PLevis"));
FName key2(TEXT("plevis"));
UE_LOG(LogTemp, Log, TEXT("FName 비교 결과 : %s"), key1 == key2 ? TEXT("같음") : TEXT("다름"));
//출력 : FName 비교 결과 : 같음
FText
다국어 지원을 위한 문자열 관리 체계 (보통 UI에서 많이 사용함)
언리얼 리플렉션
리플렉션 - 프로그램이 실행시간에 자기자신을 조사하는 기능
언리얼 오브젝트 리플렉션 시스템 : https://www.unrealengine.com/ko/blog/unreal-property-system-reflection
언리얼 오브젝트의 처리 : https://docs.unrealengine.com/5.1/ko/unreal-object-handling-in-unreal-engine/
C++에는 해당 기능이 없기 때문에 언리얼이 자체적으로 만들었다.
UHT(Unreal Header Tool)이 컴파일을 할때 해당 정보를 수집하며 수행한다.
UFUNCTION이나 UPROPERTY같은 매크로를 보고 컴파일할때 Intermediate라는 폴더에 내용을 저장하게 된다.
해당 매크로가 없다면 언리얼 시스템이 관리를 하지 않기때문에 메모리를 직접 관리해야 한다.(언리얼 GC에 적용 대상에서 제외된다.)
언리얼 오브젝트
언리얼 클래스 정보에는 Class Default Object(CDO)가 함께 포함되어 있다.
CDO는 디폴트 값을 보관하는 탬플릿 객체이다.
CDO의 디폴트값은 클래스 생성자에 정의한 데이터가 기본으로 지정된다.
단, 생성자를 수정한 내용은 다시 빌드를 해야 적용이 된다. (에디터 끄고 다시 컴파일한다.)
언리얼 오브젝트는
헤더파일에서 <#include "class".generate.h > 가 Include중에 제일 밑에 있어야 한다.
Cpp 파일에서 <#include "class".h>가 Include 중에 제일 위에 있어야 한다.
GetClass와 StaticClass로 가져올땐 같은 내용을 가져온다.
UClass* ClassRuntime = GetClass();
UClass* ClassCompile = UMyGameInstance::StaticClass();
check(ClassRuntime == ClassCompile); // 실패하면 에디터가 터짐 (빌드하면 없어지는 코드)
ensure(ClassRuntime == ClassCompile); // 실패하면 에러
ensureMsgf(ClassRuntime == ClassCompile, TEXT("에러가 떴는가?")); // 실패하면 메세지 에러
UE_LOG(LogTemp, Log, TEXT("학교를 담당하는 클래스 이름 : %s"), *ClassRuntime->GetName());
출력 : 학교를 담당하는 클래스 이름 : MyGameInstance
DefaultObject 가져오기
생성자 {SchoolName = TEXT("기본 학교");}
SchoolName = TEXT("한성대");
UE_LOG(LogTemp, Log, TEXT("학교 이름 : %s"), *SchoolName);
UE_LOG(LogTemp, Log, TEXT("기본 학교 이름 : %s"), *GetClass()->GetDefaultObject<UMyGameInstance>()->SchoolName);
출력 :
학교 이름 : 한성대
기본 학교 이름 : 기본 학교
Unreal 오브젝트 생성하기
UStudent* Student = NewObject<UStudent>();
UTeacher* Teacher = NewObject<UTeacher>();
Student->SetName(TEXT("학생1"));
UE_LOG(LogTemp, Log, TEXT("새로운 학생 이름 : %s"), *Student->GetName());
출력 : 새로운 학생 이름 : 학생1
Unreal에 UHT에 적용된 프로퍼티를 이름으로 가져오기
FString CurrentTeacherName;
FString NewTeacherName(TEXT("이득우"));
FProperty* NameProp = UTeacher::StaticClass()->FindPropertyByName(TEXT("Name"));
if (NameProp)
{
NameProp->GetValue_InContainer(Teacher, &CurrentTeacherName);
UE_LOG(LogTemp, Log, TEXT("선생 이름 : %s"), *CurrentTeacherName);
NameProp->SetValue_InContainer(Teacher, &NewTeacherName);
UE_LOG(LogTemp, Log, TEXT("선생2 이름 : %s"), *Teacher->GetName());
}
출력 :
LogTemp: 선생 이름 : 이선생
LogTemp: 선생2 이름 : 이득우
Unreal에 UHT에 적용된 함수를 이름으로 가져오기
Student->DoLesson();
UFunction* DoLessonFunc = Teacher->GetClass()->FindFunctionByName(TEXT("DoLesson"));
if (DoLessonFunc)
{
Teacher->ProcessEvent(DoLessonFunc, nullptr);
}
출력 :
LogTemp: 학생1님이 수업에 참여합니다.
LogTemp: 1학년 1번 학생1님이 수업을 듣습니다
LogTemp: 이득우님이 수업에 참여합니다.
LogTemp: 5년차 선생님 이득우님이 수업을 강의합니다
'Unreal > 이득우의 언리얼 프로그래밍' 카테고리의 다른 글
언리얼 5_4_1 게임플레이 어빌리티 시스템 캐릭터 제작 기초 (0) | 2024.03.24 |
---|---|
언리얼5_2_1 : 게임 컨텐츠의 기본 구조 (3) | 2024.03.06 |
언리얼5_1_4 : 언리얼 프로젝트의 에셋 (1) | 2024.03.05 |
언리얼5_1_3 : 언리얼 엔진의 자료구조와 메모리 관리 (1) | 2024.02.16 |
언리얼5_1_2 : 언리얼 C++ 모던객체지향 설계 (0) | 2024.02.16 |