Closed kass-kass closed 3 years ago
Update: tested the same project on a normal Android mobile phone, with no VR or Oculus involved. Same crash.
So this is definitely an Android problem, maybe general UE mobile, but I can't test on iOS, so at least Android for sure.
Essentially this makes RMC unusable on mobile for 4.26
The project settings for the mobile build are very standard, here they are just in case (ini file, but renamed to txt to upload): DefaultEngine.txt
Another bit of information: this is not an engine bug, as creating an empty subsystem and getting it in exactly the same way works fine.
Details: This is the function that crashes with a failed assertion (starts at line 906 in RuntimeMesh.cpp):
URuntimeMeshComponentEngineSubsystem* URuntimeMesh::GetEngineSubsystem()
{
URuntimeMeshComponentEngineSubsystem* RMCSubsystem = GEngine->GetEngineSubsystem<URuntimeMeshComponentEngineSubsystem>();
check(RMCSubsystem); // RMCSubsystem is nullptr here somehow on Android.
return RMCSubsystem;
}
So the first line in the function gets a nullptr from the standard UE GetEngineSubsystem
function for some reason. However, creating another engine subsystem class (i.e. UMyEngineSubsystem), and getting it with the exact same templated GetEngineSubsystem
function on an actor's BeginPlay does not return a nullptr.
This means it's either something specific to URuntimeMesh::GetEngineSubsystem()
, such as never actually getting created, or it getting garbage collected; or something wrong with getting a subsystem that is part of a plugin module, as opposed to a game module.
The call that crashes happens after Engine subsystems get initialized, as logging something in Initialize() prints way before the crash in the log. So it's strange that the GetEngineSubsystem
returns nullptr, as clearly a valid subsystem gets created at one point before that.
Will continue investigating and updating here.
Thre is alternative getenginesubsystem method
https://github.com/EpicGames/UnrealEngine/blob/c3caf7b6bf12ae4c8e09b606f10a09776b4d1f38/Engine/Source/Runtime/Engine/Classes/Engine/Engine.h#L3207
try use it, i.e. change RuntimeMesh code to:
URuntimeMeshComponentEngineSubsystem* RMCSubsystem = (URuntimeMeshComponentEngineSubsystem)GEngine->GetEngineSubsystemBase(URuntimeMeshComponentEngineSubsystem);
Thre is alternative getenginesubsystem method https://github.com/EpicGames/UnrealEngine/blob/c3caf7b6bf12ae4c8e09b606f10a09776b4d1f38/Engine/Source/Runtime/Engine/Classes/Engine/Engine.h#L3207 try use it, i.e. change RuntimeMesh code to:
URuntimeMeshComponentEngineSubsystem* RMCSubsystem = (URuntimeMeshComponentEngineSubsystem)GEngine->GetEngineSubsystemBase(URuntimeMeshComponentEngineSubsystem);
Thank you! I tried it out, but still crashes.
The syntax I used is URuntimeMeshComponentEngineSubsystem* RMCSubsystem = Cast<URuntimeMeshComponentEngineSubsystem>( GEngine->GetEngineSubsystemBase(URuntimeMeshComponentEngineSubsystem::StaticClass()) );
This issue gets weirder the more I look into it.
Getting with GetEngineSubsystem
an empty newly-made subsytem I called UMyEngineSubsystem
worked fine, but getting the URuntimeMeshComponentEngineSubsystem
just returned nullptr, when done in BeginPlay
of any actor. That is very strange, as BeginPlay
should happen after Engine subsystems get initialized (as it's part of the World, which initializes after Engine).
Logging on initialize in both subsystems revealed that UMyEngineSubsystem
's function override for Initialize()
gets called, but URuntimeMeshComponentEngineSubsystem
's doesn't. It just never gets initialized.
The only difference I saw is one subsystem was part of a plugin, and one of a game module, so I converted the RuntimeMeshComponent module from a plugin to a game module. All of a sudden, everything works. The subsystem gets initialized, it can be gotten with GetEngineSubsystem
, no crash on Android, everything works.
To convert a module from a plugin to a game module, these were the steps:
IMPLEMENT_MODULE(FRuntimeMeshComponentPlugin, RuntimeMeshComponent);
to IMPLEMENT_GAME_MODULE( FDefaultGameModuleImpl, RuntimeMeshComponent);
."RuntimeMeshComponent"
to the ExtraModuleNames.AddRange
line of ProjectName.target.cs
, to the PublicDependencyModuleNames.AddRange
line of the ProjectName.build.cs
(the primary game module), and to the "Modules":
in the ProjectName.uproject
.So after discovering this, I assumed it might be an engine bug with making engine subsystems in plugin modules. But it's not. I made a new empty plugin, made a new engine subsystem in it, and tried to get it on BeginPlay the same way. It works fine, on PC and on Android.
So there's something specific about the URuntimeMeshComponentEngineSubsystem
, which makes it never initialize only when part of a plugin, only on Android, only in 4.26. I can't really find any explanation, I looked through the code so many times, but it seems like the subsystem is declared in a very standard way, and should by all means be initialized automatically by the Engine. Yet it doesn't happen.
Fixed in 7765cc4ccdb9d6929e11335b5d17c3d30b0c2c4d
Found a bug when trying to run RMC on Android (Oculus Quest is the hardware I'm using, not sure if the same crash happens on other devices).
I have a simple BP that makes a box from a hard-coded list of verts/tris, simplest thing I could think of, and calls "create section from components" on a default RMCStatic.
This runs on PC fine. However, the Android ASTC packaged build crashes when the "create section" node gets called, giving critical error in the log:
Assertion failed: RMCSubsystem [File:D:/Unreal Projects/RMC_OculusQuest/Plugins/RuntimeMeshComponent/Source/RuntimeMeshComponent/Private/RuntimeMesh.cpp] [Line: 909]
The line in question is simply
check(RMCSubsystem);
I have the latest GitHub source, and default 4.26.2 from the epic launcher. Did anyone encounter this issue? Here are the nodes, and the box that gets created:
This is all in a completely empty project, to make sure this is exactly what causes the issue. These nodes are the only non-default-engine code that runs.
Here is the whole project (2MB zip file): RMC_OculusQuest.zip
Here is the full log, with the callstack for the critical error at the very end: RMC_OculusQuest.log