🎮Unreal4/C++

[UE4] CDO 에러, 무기 장착/해제 구조, Abstract 지정자, FORCEINLINE (inline 매크로), FActorSpawnParameters, GetComponent

공대 컴린이 2023. 3. 8. 18:05
728x90

📕 CDO (Class Default Object) 에러

호출해야 하는 자료(Object)들이 존재하지 않아서 생기는 오류로, 컴파일이 완료된 후 hot reload 상황에서 발생하기 때문에 컴파일은 이미 완료 된 상태에서 에러가 난다.

주로 찾으려는 오브젝트의 경로를 잘못 작성했을 때 발생한다.

📗 무기 장착/해제 기능 구조

class Weapon
{
	virtual void Equip()
	{
		if(장착 조건)
        	return;
	}
}

class Rifle : Weapon
{
	void Eqiup()
	{
		
        if(장착 조건) // 비효율적인 코드 작성!
        {
        	Super::Equip();
        }
	}
}

 

무기의 최상의 클래스인 Weapon 클래스를 만들고, Weapon을  상속받는 각각의 종류별 무기(ex. Rifle)을 만든다고할 때, 무기를 장착하는 기능인 Equip() 함수를 생성할 것이다.

만약 부모클래스인 Weapon::Equip() 함수에서 무기 장착이 가능한지에 대한 조건문을 걸었다면, Weapon을 상속받은 자식클래스 Rifle에서도 똑같은 조건문을 걸고, 무기 장착이 가능한 경우에만 부모클래스의 Super::Equip() 함수를 사용할 수 있다.

이는 결국 똑같은 조건문을 작성하며 비효율적인 구조로 이루어지게 된다.

 

class Weapon
{
	virtual void Equip()
	{
		if(장착 조건) return;
	}
    
    virtual bool CanEquip() 
    { 
    	return 장착조건; 
    }
}

class Rifle : Weapon
{
	void Eqiup()
	{
		
        if(Super::CanEquip()) // 혹은 Override 후 CanEquip();
        	Super::Equip();
	}
}

 

이를 해결하기 위해 무기 장착이 가능한지를 체크해주는 CanEquip() 함수를 만들고 추가로 자식클래스에서 더 검사하고싶은 조건이 있다면 재정의하여 사용할 수 있도록 추상화 함수로 작성하는 방법이 있다.

📘 실제 적용 코드

설명한 구조대로 C++ 클래스인 Weapon을 작성한 내용이다.

나는 클래스 자체를 abstract로 추상화하여  Weapon을 상속받는 종류별 무기들이 함수를 호출하여 사용할 수 있도록 구현하였다.

📙 Abstract 지정자

 

클래스를 추상클래스로 지정했을 때의 효과는 언리얼 문서에 더 자세히 나와있다.

이는 C++의 추상화가 아닌, 언리얼만의 추상화이기 때문에 순수 가상함수가 꼭 존재하지 않아도 된다. 또한 추상은 상속되지 않는다.

 

 또한 문서에 적힌 내용대로 만들어진 추상 클래스는 뷰포트에 드래그하여 배치할 수 없고, Weapon을 상속받아 구현한 Weapon_AR4만이 뷰포트에 드래그하여 배치할 수 있다.

 

Weapon의 기능을 제어할 WeaponComponent를 제작하고, 무기 종류에 따른 Enum값을 생성하였다.

일반적인 방법으로 Class 안에 enum Type { A, B}; 처럼 선언하는 것은 직렬화가 안되기 때문에 UENUM을 사용하여 직렬화해야 한다.

이때 주의할 점은 ENUM이나 STRUCT 전부 다 직렬화를 시키기 위해선 직렬화 코드를 UCLASS 위gernerated 헤더파일 아래그 사이에 위치해야 한다는 점이다.

📓 inline, FORCEINLINE 

bool IsUnarmedMode() { return Type == EWeaponType::Max; }

 

위와 같이 작성된 코드를 inline 함수라고 한다.

inline 키워드는 inline, _inline, __inline 의 총 세 종류가 존재하는데, 컴파일러 설정에 따라 모두 다르게 적용된다.

프로그래머가 강제할건지, C 컴파일러가 강제할건지, 상황에따라 강제할건지가 모두 다르다. 또한 언리얼에서는 CPU 스펙마다 강제가 다르기때문에, FORCEINLINE 매크로를 붙여 무조건 인라인 함수가 되도록 강제시킬 수 있다.

 

FORCEINLINE bool IsUnarmedMode() { return Type == EWeaponType::Max; }

 

FORCEINLINE 는 간단한 Return 함수나 간단한 Set 함수 같은 경우는 Main으로 점프한 뒤 돌아올 필요없이 바로 실행시키면 되기때문에 무조건 inline을 사용하도록 만드는 매크로이다.

💡 FActorSpawnParameters

FActorSpawnParameters는 SpawnActor함수를 실행시킬 때 Spawn 관련 설정들을 전부 설정할 수 있는 자료형이다.

위 코드는 Weapon Component에서 Weapon을 Spawn 시킬 때 Owner를 플레이어(Owner)로 설정하고, 언제나 스폰되도록 AlwaysSpawn 설정을 저장한 내용이다.

💡 GetComponent

Get Component 기능을 템플릿화하여 편리하게 함수로 만들었다.

하나의 Component를 찾아올 때는 GetComponentByClass 함수를 사용하여 매개변수로 StaticClass 정보를 전달한다.

추가로 컴포넌트 이름을 전달했을 때 해당 이름인 컴포넌트를 반환해주는 함수도 작성하였는데, 이는 GetComponents 함수를 이용하여 InActor에 존재하는 모든 컴포넌트 정보를 불러오고, 그 컴포넌트들을 for문 돌면서 이름을 검사한다.


참조

https://docs.unrealengine.com/4.27/ko/ProgrammingAndScripting/GameplayArchitecture/Classes/Specifiers/

 

클래스 지정자

클래스가 엔진과 에디터의 다양한 부분과 어떻게 작동하는지를 지정하기 위해 UClass 선언시 사용되는 키워드입니다.

docs.unrealengine.com

728x90