EsotericSoftware / spine-runtimes

2D skeletal animation runtimes for Spine.
http://esotericsoftware.com/
Other
4.35k stars 2.89k forks source link

[ue4] UE4 4.20 Spine 3.7-beta-cpp Hot Reload not working #1180

Closed GryphonWorx closed 5 years ago

GryphonWorx commented 5 years ago

After a lot of fiddling to get the 3.7-beta-cpp to build properly with the include directories etc I have at last gotten it working. The only problem now seems to be that the SpineEditor plugin doesn't get hot reloaded and thus on compile in VS all spine functionality disappears. Upon restarting the editor it says the SpineEditor plugin doesn't exist and you have to rebuild in VS to clean out the hot reload files and then you can start the editor again.

It is getting quite tedious to have to restart the editor every time I have to compile while testing things out. Is there something I am missing or is this a bug?

badlogic commented 5 years ago

What UE version are you using? Hot reload is nothing that we can control on our end as plugin providers. Do you experience similar issues with other plugins that have an editor component?

badlogic commented 5 years ago

Sorry, just saw you posted the version in the issue title. I'll try to reproduce locally.

badlogic commented 5 years ago

Could you also elaborate what issues you had compiling the plugin? For UE 4.20, the build.cs file has to be modified, after which compilation should work out of the box.

GryphonWorx commented 5 years ago

The plugin looks for includes in several places where there are none, like the engine source directories in program files:

SpinePlugin.Build.cs : Referenced directory 'C:\Program Files\Epic Games\UE_4.20\Engine\Source\SpinePlugin\Public' does not exist. SpinePlugin.Build.cs : Referenced directory 'C:\Program Files\Epic Games\UE_4.20\Engine\Source\SpinePlugin\Public\spine-cpp\include' does not exist. SpinePlugin.Build.cs : Referenced directory 'D:\\Plugins\SpinePlugin\Source\SpinePlugin\Public\spine-cpp\include' does not exist. SpineEditorPlugin.Build.cs : Referenced directory 'C:\Program Files\Epic Games\UE_4.20\Engine\Source\SpineEditorPlugin\Public' does not exist. SpineEditorPlugin.Build.cs : Referenced directory 'C:\Program Files\Epic Games\UE_4.20\Engine\Source\SpinePlugin\Public\spine-cpp\include' does not exist. SpineEditorPlugin.Build.cs : Referenced directory 'D:\\Plugins\SpinePlugin\Source\SpinePlugin\Public\spine-cpp\include' does not exist. The Project dir includes are wrong after following the readme.md instructions in the UE4 folder from the Spine GIT tree (to copy the spine-cpp folder over) because the path ends up being: D:\\Plugins\SpinePlugin\Source\SpinePlugin\Public\spine-cpp\spine-cpp\include Which is easy to fix for the end user of course x).

There's nothing exactly wrong with the spamming of broken include paths as such, things still build, but people in the team ask questions about it etc.

It also looks like the only other editor-mode plugin we use is the UE4 Git Plugin (https://github.com/SRombauts/UE4GitPlugin for LFS2 support). That doesn't insist on building itself on every compile while VS says: 1>Compiling game modules for hot reload 1>Building 5 actions with 12 processes... 1> [1/5] UE4Editor-SpinePlugin-8165.lib 1> [2/5] UE4Editor-SpinePlugin-8165.dll 1> [4/5] UE4Editor-RGame-7846.lib 1> [5/5] UE4Editor-RGame-7846.dll Regardless of where the changes are. To be honest I am semi-new to plugins since the core engine tends to do what we want, and I can't find any information (for or against) of Editor mode plugins not hot reloading.

badlogic commented 5 years ago

Ah, sorry about the wrong instructions and ending up with an invalid spine-cpp path. I'll fix that!

Regarding the source directories, I've been trying to hunt down the cause of this myself for a while. It started with UE 4.20, worked as intended before. As you pointed out, the docs on plugins are rather ... let's say minimal. And nothing in the UE 4.20 changelog indicates what we're doing wrong there. I'll continue to investigate.

I'm currently trying to figure out what's going on with editor plugin hot reloads and will report back here.

Thanks for reporting!

badlogic commented 5 years ago

Found the fix for the include paths https://issues.unrealengine.com/issue/UE-60969

The problem is that this will make the plugin's build.cs incompatible with old UE4 versions, so I'm hesitant to apply the fix until we make 4.20 the minimum version (currently 4.18).

GryphonWorx commented 5 years ago

Very good, I found the same thing too, thought I'd be helpful but like minds XD. Good call though, we can live with the include paths being spammy on compile, it's not a big deal ayway. The biggest thing is the hot-reload problem, and I find that one a rather peculiar nut to crack.

badlogic commented 5 years ago

Ay, working on it. I'm using our example project as the baseline so we talk about the same thing. I'm documenting my findings here, so you may want to disable notifications for today :)

The game module recompiles and hot reloads fine. Both the SpineEditorPlugin and SpinePlugin do recompile, but not hot reload. There is no "hot reload succeeded" message in the editor. Worse, I have a map open with an actor that has Spine components on it, and it just disappears (06-cpp example map).

I've added a local variable in SpineSkeletonRendererComponent and recompiled the SpinePlugin module in the UE editor. Compilation succeeds, but no hot reload success toast is displayed (as it is for the game module).

The output log shows this:

Candidate modules for hot reload:
  SpinePlugin
Launching UnrealBuildTool... [C:/unrealengine/UE_4.20/Engine/Binaries/DotNET/UnrealBuildTool.exe  -ModuleWithSuffix=SpinePlugin,4596 Win64 Development -TargetType=Editor -Project="D:/workspaces/esotericsoftware/spine-runtimes/spine-ue4/SpineUE4.uproject" -canskiplink "D:/workspaces/esotericsoftware/spine-runtimes/spine-ue4/SpineUE4.uproject" ]
CompilerResultsLog: New page: Compilation - Sep 25, 2018, 1:42:45 PM
CompilerResultsLog: Using 'git status' to determine working set for adaptive non-unity build.
CompilerResultsLog: Creating makefile for hot reloading SpineUE4Editor (modules to compile have changed)
CompilerResultsLog: Compiling game modules for hot reload
CompilerResultsLog: Using Visual Studio 2017 14.15.26726 toolchain (C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726) and Windows 10.0.17134.0 SDK (C:\Program Files (x86)\Windows Kits\10).
CompilerResultsLog: D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Source\SpinePlugin\SpinePlugin.Build.cs: warning: Referenced directory 'C:\unrealengine\UE_4.20\Engine\Source\SpinePlugin\Public' does not exist.
CompilerResultsLog: D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Source\SpinePlugin\SpinePlugin.Build.cs: warning: Referenced directory 'C:\unrealengine\UE_4.20\Engine\Source\SpinePlugin\Public\spine-cpp\include' does not exist.
CompilerResultsLog: D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Source\SpineEditorPlugin\SpineEditorPlugin.Build.cs: warning: Referenced directory 'C:\unrealengine\UE_4.20\Engine\Source\SpineEditorPlugin\Public' does not exist.
CompilerResultsLog: D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Source\SpineEditorPlugin\SpineEditorPlugin.Build.cs: warning: Referenced directory 'C:\unrealengine\UE_4.20\Engine\Source\SpinePlugin\Public\spine-cpp\include' does not exist.
CompilerResultsLog: D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Source\SpineUE4\SpineUE4.Build.cs: warning: Referenced directory 'D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Source\SpinePlugin\Public' does not exist.
CompilerResultsLog: D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Source\SpineUE4\SpineUE4.Build.cs: warning: Referenced directory 'D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Source\SpinePlugin\Classes' does not exist.
CompilerResultsLog: Building 3 actions with 8 processes...
CompilerResultsLog:   [1/3] Module.SpinePlugin.cpp
CompilerResultsLog:   [2/3] UE4Editor-SpinePlugin-4596.lib
CompilerResultsLog:      Creating library D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Intermediate\Build\Win64\UE4Editor\Development\SpinePlugin\UE4Editor-SpinePlugin-4596.lib and object D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Intermediate\Build\Win64\UE4Editor\Development\SpinePlugin\UE4Edi
tor-SpinePlugin-4596.exp
CompilerResultsLog:   [3/3] UE4Editor-SpinePlugin-4596.dll
CompilerResultsLog:      Creating library D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Intermediate\Build\Win64\UE4Editor\Development\SpinePlugin\UE4Editor-SpinePlugin-4596.suppressed.lib and object D:\workspaces\esotericsoftware\spine-runtimes\spine-ue4\Plugins\SpinePlugin\Intermediate\Build\Win64\UE4Editor\Development\SpinePl
ugin\UE4Editor-SpinePlugin-4596.suppressed.exp
CompilerResultsLog: Total build time: 32.01 seconds (Parallel executor: 27.19 seconds)
LogMainFrame: MainFrame: Module compiling took 32.245 seconds
LogClass: SpineEvent HotReload.
LogClass: SpineAnimationStateMixData HotReload.
LogContentBrowser: Native class hierarchy updated for 'SpinePlugin' in 0.0003 seconds. Added 9 classes and 2 folders.
Display: HotReload successful (52 functions remapped  2 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0095 seconds. Added 2587 classes and 612 folders.
Display: HotReload took 32.4s.
Warning: HotReload operation took 32.4s.

Apart from the include path and duration warning, everything looks in order, no error is reported.

GryphonWorx commented 5 years ago

I may but I find it interesting, I might also learn something. But I also want to add that what you wrote above is the exact behavior I have as well, just as verification.

badlogic commented 5 years ago

Welp, I found the culprit. Shared library hot reloading doesn't work with constant data...

We have a custom RTTI implementation that allows us to tag specific classes and use that info to differentiate between these classes. When UE4 hot reloads a class, a new constant data section is created, while the old instances of the classes loaded via the old shared library remain in memory as well. The RTTI implementation compares based on address (yeah, dangerous, but fast) and obviously the constant data in the new shared library has a different address than the constant data in the old shared library.

Leading to funky stuff like this:

https://libgdx.badlogicgames.com/uploads/24-cnY2.png

The old RTTI instance has a different address than the new RTTI instance.

I can fix this by comparing the tags instead of addresses. But I worry that there might be other places where constant data is messing up hot reloading.

badlogic commented 5 years ago

Confirmed that my fix in https://github.com/EsotericSoftware/spine-runtimes/commit/f534058fefb45b9ef7dc5d65844e3c1e14b09d62 is working in UE4. I can now reload changes in all modules (game, editor plugin, non-editor plugin).

Please pull from the 3.7-beta-cpp branch and copy the latest spine-cpp/ over to your UE4 Spine plugin directory (<projectDir>\Plugins\SpinePlugin\Source\SpinePlugin\Public\).

Let me know if you still run into hot reloading issues. I looked through the entire UE4/C++ Spine code base and couldn't find any other static data offenders.

Thanks for reporting and helping pin point the issue!