Hot reload in UE4: Pitfalls and Guidelines?

Dear community,

I very much appreciate the hot reload feature in UE4 - big time saver (as long as it works). As I study the feature, putting logs in constructors and destructors of my classes, I observe some patterns I don’t immediately understand. An all common approach for hot reload of C++ code is, in my humble understanding, not easy to achieve, if possible at all. Which leads me to the question: are there guidelines and list of pitfalls to consider when writing hot reloadable code in UE4?

By what means does UE4 transfer living objects from current version of a dll/dylib/so to a new one? Exploiting copy-constructors, plain mem-copies, or other means of replication, such as, expecting new objects to be properly reconfigured based on UPROPERTY? I have been working on a class based on FRunnable and one based on APlayerController. I just noted that GENERATED_BODY() includes a private copy-constructor, so I guess that’s not how it’s done.

I would like to know some guidelines, such as, if your class uses raw pointers, make sure to have proper copy constructor (if that is applicable, for my current need my class should never be copied). Specifically, what are the constructs that should be avoided or when the hot-reload cannot/should not be used.

Below are some commented logs during six hot reloads, there seems to be a pattern, but it seems to be a lot more objects created than I expect it to be. I have named the objects I spot with letters and the number of in which pass they were created and what version of the library. I started to include a version number after two hot reloads. My annotations are within parenthesis at the end of the MyInfo lines. I assume the destructor for unknown objects, that was not created through my constructor was created with another form of constructor that I don’t know of.

LogInit:Display: Running engine for game: DummyProjectX
LogPlatformFile: Not using cached read wrapper
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  INITIAL START 0)
MyInfo: AMyPlayerController::Constructor(0x0x165dbb580)     (A0 - Player)
MyInfo: NetworkCommandServer::Constructor(0x0x164bc8900)    (A0 - Server)
LogHotReload: New module detected: UE4Editor-DummyProjectX-6329.dylib
LogHotReload: Starting Hot-Reload from IDE
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  RELOAD PASS 1)
MyInfo: AMyPlayerController::Constructor(0x0x17b786080)     (B1 - Player)
MyInfo: NetworkCommandServer::Constructor(0x0x1742e6840)    (B1 - Server)
MyInfo: AMyPlayerController::Constructor(0x14d11cb80)       (C1 - Player)
MyInfo: NetworkCommandServer::Constructor(0x1742e7060)      (C1 - Server)
LogHotReload: Re-instancing MyWorldSettings after hot-reload.
LogContentBrowser: Native class hierarchy updated for 'DummyProjectX' in 0.0081 seconds. Added 3 classes and 2 folders.
Display: HotReload successful (0 functions remapped  0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0308 seconds. Added 2187 classes and 421 folders.
Display: HotReload took  0.5s.
LogHotReload: New module detected: UE4Editor-DummyProjectX-2822.dylib
LogHotReload: Starting Hot-Reload from IDE
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  RELOAD PASS 2)
MyInfo: AMyPlayerController::Destructor(0x165dbb580)        (A0 - Player)
MyInfo: NetworkCommandServer::Shutdown(0x164bc8900) called  (A0 - Server)
MyInfo: NetworkCommandServer::Destructor(0x0x164bc8900)     (A0 - Server)
MyInfo: AMyPlayerController::Destructor(0x14d11c100)        (Unknown)
MyInfo: AMyPlayerController::Destructor(0x17b786080)        (B1 - Player)
MyInfo: NetworkCommandServer::Shutdown(0x1742e6840) called  (B1 - Server)
MyInfo: NetworkCommandServer::Destructor(0x0x1742e6840)     (B1 - Server)
MyInfo: AMyPlayerController::Constructor(0x17b786080)       (D2 - Player, reused addr)
MyInfo: NetworkCommandServer::Constructor(0x173beb880)      (D2 - Server)
MyInfo: AMyPlayerController::Constructor(0x173a08b80)       (E2 - Player)
MyInfo: NetworkCommandServer::Constructor(0x173beb920)      (E2 - Server)
LogContentBrowser: Native class hierarchy updated for 'DummyProjectX' in 0.0026 seconds. Added 3 classes and 2 folders.
Display: HotReload successful (0 functions remapped  0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0228 seconds. Added 2187 classes and 421 folders.
Display: HotReload took  0.4s.
LogHotReload: New module detected: UE4Editor-DummyProjectX-8727.dylib
LogHotReload: Starting Hot-Reload from IDE
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  RELOAD PASS 3)
MyInfo: AMyPlayerController::Destructor(0x14d11cb80)        (C1 - Player)
MyInfo: NetworkCommandServer::Shutdown(0x1742e7060) called  (C1 - Server)
MyInfo: NetworkCommandServer::Destructor(0x1742e7060)       (C1 - Server)
MyInfo: AMyPlayerController::Destructor(0x173a08100)        (Not seen)
MyInfo: AMyPlayerController::Destructor(0x17b786080)        (D2 - Player)
MyInfo: NetworkCommandServer::Shutdown(0x173beb880) called  (D2 - Server)
MyInfo: NetworkCommandServer::Destructor(0x173beb880)       (D2 - Server)
MyInfo: AMyPlayerController::Constructor(0x16fc71600)       (F3 - Player)
MyInfo: NetworkCommandServer::Constructor(0x18047e520)      (F3 - Server)
MyInfo: AMyPlayerController::Constructor(0x17b890b80)       (G3 - Player1)
MyInfo: NetworkCommandServer::Constructor(0x18047e480)      (G3 - Server1)
LogContentBrowser: Native class hierarchy updated for 'DummyProjectX' in 0.0030 seconds. Added 3 classes and 2 folders.
Display: HotReload successful (0 functions remapped  0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0221 seconds. Added 2187 classes and 421 folders.
Display: HotReload took  0.3s.
LogHotReload: New module detected: UE4Editor-DummyProjectX-4716.dylib
LogHotReload: Starting Hot-Reload from IDE
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  RELOAD PASS 4)
MyInfo: AMyPlayerController::Destructor(0x173a08b80)        (E2 - Player)
MyInfo: NetworkCommandServer::Shutdown(0x173beb920) called  (E2 - Server)
MyInfo: NetworkCommandServer::Destructor(0x173beb920)       (E2 - Server)
MyInfo: AMyPlayerController::Destructor(0x16fc73580)        (Unknown)
MyInfo: AMyPlayerController::Destructor(0x16fc71600)        (F3 - Player1)
MyInfo: NetworkCommandServer::Shutdown(0x18047e520) called  (F3 - Server1)
MyInfo: NetworkCommandServer::Destructor(0x18047e520)       (F3 - Server1)
MyInfo: AMyPlayerController::Constructor(0x173a08100)       (H4 - Player1, reused addr)
MyInfo: NetworkCommandServer::Constructor(0x149da1ee0)      (H4 - Server1)
MyInfo: AMyPlayerController::Constructor(0x1744f9600) ver 2 (I4 - Player2)
MyInfo: NetworkCommandServer::Constructor(0x149da1d00)      (I4 - Server2)
LogContentBrowser: Native class hierarchy updated for 'DummyProjectX' in 0.0353 seconds. Added 3 classes and 2 folders.
Display: HotReload successful (0 functions remapped  0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0458 seconds. Added 2187 classes and 421 folders.
Display: HotReload took  2.8s.
LogHotReload: New module detected: UE4Editor-DummyProjectX-8289.dylib
LogHotReload: Starting Hot-Reload from IDE
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  RELOAD PASS 5)
MyInfo: AMyPlayerController::Destructor(0x17b890b80) ver 2  (G3 - Player1)
MyInfo: NetworkCommandServer::Shutdown(0x18047e480) called  (G3 - Server1)
MyInfo: NetworkCommandServer::Destructor(0x18047e480)       (G3 - Server1)
MyInfo: AMyPlayerController::Destructor(0x1744fb580) ver 2  (Unkown)
MyInfo: AMyPlayerController::Destructor(0x173a08100) ver 2  (H4 - Player1)
MyInfo: NetworkCommandServer::Shutdown(0x149da1ee0) called  (H4 - Server1)
MyInfo: NetworkCommandServer::Destructor(0x149da1ee0)       (H4 - Server1)
MyInfo: AMyPlayerController::Constructor(0x172d7eb00) ver 2 (J5 - Player2)
MyInfo: NetworkCommandServer::Constructor(0x15cbe89a0)      (J5 - Server2)
MyInfo: AMyPlayerController::Constructor(0x172d7d600) ver 3 (K5 - Player3)
MyInfo: NetworkCommandServer::Constructor(0x15cbe87c0)      (K5 - Server3)
LogContentBrowser: Native class hierarchy updated for 'DummyProjectX' in 0.0033 seconds. Added 3 classes and 2 folders.
Display: HotReload successful (0 functions remapped  0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0320 seconds. Added 2187 classes and 421 folders.
Display: HotReload took  0.6s.
LogHotReload: New module detected: UE4Editor-DummyProjectX-6465.dylib
LogHotReload: Starting Hot-Reload from IDE
(- - - - - - - - - - - - - - - - - - - - - - - - - - - - -  RELOAD PASS 6)
MyInfo: AMyPlayerController::Destructor(0x1744f9600) ver 3  (I4 - Player2)
MyInfo: NetworkCommandServer::Shutdown(0x149da1d00) called  (I4 - Server2)
MyInfo: NetworkCommandServer::Destructor(0x149da1d00)       (I4 - Server2)
MyInfo: AMyPlayerController::Destructor(0x172d7cb80) ver 3  (Unknown)
MyInfo: AMyPlayerController::Destructor(0x172d7eb00) ver 3  (J5 - Player2)
MyInfo: NetworkCommandServer::Shutdown(0x15cbe89a0) called  (J5 - Server2)
MyInfo: NetworkCommandServer::Destructor(0x15cbe89a0)       (J5 - Server2)
MyInfo: AMyPlayerController::Constructor(0x172d7eb00) ver 3 (L6 - Player3)
MyInfo: NetworkCommandServer::Constructor(0x15cbeaf20)      (L6 - Server3)
MyInfo: AMyPlayerController::Constructor(0x17b894100) ver 4 (M6 - Player4)
MyInfo: NetworkCommandServer::Constructor(0x15cbeaac0)      (M6 - Server4)
LogContentBrowser: Native class hierarchy updated for 'DummyProjectX' in 0.0203 seconds. Added 3 classes and 2 folders.
Display: HotReload successful (0 functions remapped  0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0265 seconds. Added 2187 classes and 421 folders.
Display: HotReload took  0.6s.