Unreal Engine/개념

[UE]@Hot Reload

코딩하는상후니 2022. 11. 29. 20:46

 


 

모든 내용은 참고된 링크 자료를 토대로 작성했고 이를 근거로 추측하는 글입니다.

 

* Hot Reload

 

에디터를 열고 IDE 의 Compile 시 새로운 DLL 파일을 생성하는 과정인 Hot Reload 가 발생한다.
언리얼에서는 Hot Reload 를 추천하지 않는다.
왜냐하면,
에디터를 열고 IDE 를 컴파일하게 되면 아주 빈번하게 Blueprint 와 더불어 많은 문제들을 야기한다.
따라서 언리얼에서는 웬만하면 에디터를 끄고 안전하게 컴파일하기를 권장한다.
 
이 문제를 해결하기 위해서 언리얼에서는 'Live Coding' 이라는 방식을 도입했다.
( 단축키 : Ctrl + Alt + F11 )

 

 

 

 

 

* 리플렉션 데이터 수정의 문제점

 

 

https://unrealcommunity.wiki/live-compiling-in-unreal-projects-tp14jcgs

 

위 그림은 참고 자료에 나와있는 본문이다. 본문을 토대로 내용을 해석하자면,
 
UHT 에 의해 확인되어지는 Header 파일의 경우 코드 수정은 피해야한다고 쓰여있다.
UCLASS/USTRUCT/UENUM 같은 타입들은 이번 시스템에서는 다룰 수 없다고 나와있다.
 
.cpp 에서의 구현은 대부분 문제없지만 UCLASS/USTRUCT 생성자의 경우,
이미 인스턴스로 구현되어있기 때문에 수정을 적용할 수 없다.
CDO ( Create Default Object ) 는 클래스 생성자에 의해 생성된 이후 변경되지 않기 때문이다.
 
여기까지 미루어보았을 때,
언리얼 엔진 특성상 엔진 시작 시 에디터에서 사용할 리플렉션 데이터를 가져오는데
재시작 ( rebulid ) 과정을 거치지 않고서는 해당 데이터를 수정하기에 힘들다는 것을 예측할 수 있겠다.
 
 
왜 이런 불편함이 생기는지 참고 자료에 짧게 설명되어있다.

 

https://unrealcommunity.wiki/live-compiling-in-unreal-projects-tp14jcgs

 

Editor 를 실행할 때, Asset 의 일부분만을 참고해 일시적으로 만들어지게 되는데
해당 데이터가 어떤 이유로 깨질 수 있다고 나와있다.
 
 
종합적으로 살펴보자.
나의 생각으로는 코드의 수정 사항은 원본 데이터에 잘 반영되어진다.
하지만,
Editor 는 원본 데이터가 아닌 일시적으로 원본 데이터의 일부분만을 참조해 생성한 Asset 을 참조하고 있는 것이다.
원본 데이터의 바뀐 사항이 적용되지 않는 문제점으로 보인다.
왜 원본 데이터의 수정 사항을 적용할 수 없을까 ??
 
중요한 것은 일시적으로 일부분만을 참조하는 Asset 도 생성자를 거쳐 생성되어진다.
이로 인해 CDO 가 생성되어진다.
CDO ( Create Default Object ) 는 간략하게 UCLASS, USTRUCT... 등의 식별자라고 생각하면 된다.
이 때문에 GetClass( ) 를 통해 언제 어디서든 접근 가능하다.
 
앞서 말했듯이, CDO 는 클래스 생성자에 의해 생성된 이후 변경되지 않는다.
결국, 바뀐 리플렉션 데이터를 적용하기 위해선 에디터를 다시 재시작해야할 수 밖에 없다.
( 생성자를 다시 호출해 CDO 를 바꾸기 위함이다. )
 
 
 
그럼에도 불구하고 수정되어지면 어떻게 될까 ??
 
UCLASS Header 파일에서 다른 UCLASS 포인터를 가진 변수를 들고 있을 때,
해당 UCLASS 의 Reflection Data 를 수정하면
( ex. UPROPERTY(Replicated) AActor* Weapon  -> UPROPERTY(ReplicatedUsing = OnRep_OverlappingWeapon) AActor* Weapon )
UHT 입장에서는 기존의 데이터 Weapon 은 Replicated 였는데 ReplicatedUsing 은 파악이 불가능하다.
이 때, UHT 는 해당 포인터를 무시한다. ( 변수 이름을 기준으로 판단하는 것처럼 보인다. )
그로 인해, 해당 포인터는 이유 없는 NULL 이 발생한다.
 
이 현상은 무조건 발생하지 않고 간혹 발생한다.
 
 
해결방안으로는
해당 포인터로 선언된 리플렉션 변수 이름은 UHT 가 인지함으로 변수 이름을 아예 다른 이름으로 바꿔야한다.
혹은 변수를 다시 생성해야만 한다.
( ex. Weapon -> WeaponObject )
결과적으로, 알 수 없는 오류가 생기게 되고 엄청나게 시간을 낭비하게 된다.
 
이러한 문제점을 예방하기 위해서 'Live Coding' 기능을 사용해야한다' 라고 참고 자료에 나와있다.
 
 
 
 
 
( 22.12.01 )

* 즉각적인 피드백

 
Live Coding 기능의 주요 특징을 살펴보자.
 
1. IDE 가 Hot Reload 를 사용하지 못하게 한다.
( 에디터를 끈다면 정상적으로 사용 가능하다. )
2. 포인터 등 변수 null 방지
3. Blueprint 함수, 포인터 오염 방지
4. 항상 에디터 재시작이 필요하진 않다.
 
 
중요한 점은 'Live Coding 기능' 은 데이터 손상 방지에 목적이 있다.
 
즉,
앞서 말한 Header 안에 포함된 Reflection data 의 수정을 근본적으로 해결해주지 않는다는 의미이다.
 
Header 에서 Reflection 데이터를 수정하거나 .cpp 에서 조차 수정 후 라이브 코딩을 이용해 컴파일 시,
수정된 코드가 바로 적용되지 않는 현상이 있음을 체험했다.

 

 

private:
	//UPROPERTY(ReplicatedUsing = OnRep_EquippedWeapon)
	//	AWeapon* EquippedWeapon;

    //UFUNCTION()
	//	void OnRep_EquippedWeapon();

	UPROPERTY(Replicated)
		AWeapon* EquippedWeapon;

 

=> OnRep Notify 함수 사용 수정 시, 적용 안됨.
 
 
즉,
라이브 코딩 기능을 사용해서 컴파일하더라도 Reflecation Data 수정 내용이 정상적으로 적용되기 위해선
결국, 에디터를 다시 재시작해야한다. ( 생성자를 통한 CDO 수정 )

 

 

 

 

 

 

 

 


 

참고 자료

 

 

 

 

 

 

 

 

'Unreal Engine > 개념' 카테고리의 다른 글

[UE] @문자열 ( FText, FName, FString )  (0) 2022.08.01