Myo plugin crash fix
The current version of the Myo plugin (0.7.11) is still crashing the UE4 editor when Myo Connect is not running.
I’ve traced crash to an assert in a function being called after plugin startup.
The actual error is:
"Assertion failed: O != NULL [File:C:\Users\<*user*>\Desktop\<*project*>\Plugins\MyoPlugin\Intermediate\Build\Win64\UE4Editor\Inc\MyoPlugin\MyoPlugin.generated."
UE4Editor_Core!FDebug::AssertFailed() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.8\engine\source\runtime\core\private\misc\outputdevice.cpp:355]
UE4Editor_MyoPlugin!IMyoInterface::Execute_DeviceDisabled() [c:\users\<user>\desktop\<project>\plugins\myoplugin\intermediate\build\win64\ue4editor\inc\myoplugin\myoplugin.generated.cpp:196]
UE4Editor_MyoPlugin!FMyoPlugin::SetDelegate() [c:\users\<user>\desktop\<project>\plugins\myoplugin\source\myoplugin\private\fmyoplugin.cpp:814]
UE4Editor_MyoPlugin!MyoDelegate::MyoStartup() [c:\users\<user>\desktop\<project>\plugins\myoplugin\source\myoplugin\private\myodelegate.cpp:206]
Here’s what’s happening…
In MyoPlugin.generated.cpp:
void IMyoInterface::Execute_DeviceDisabled(UObject* O){
check(O != NULL); // is where the assert is failing.
...
In FMyoPlugin.cpp:809:
void FMyoPlugin::SetDelegate(MyoDelegate* newDelegate){
collector->myoDelegate = newDelegate;
collector->Startup();
//Emit disabled event if we didn't manage to create the hub
if (!collector->Enabled){
collector->myoDelegate->MyoDisabled(); // Here is where IMyoInterface::Execute_DeviceDisabled is ultimately getting called.
...
The reason assert is failing is that the pointer to the interface delegate (_interfaceDelegate) is null after startup/initialization of the plugin when Myo Connect is not running.
In MyoDelegateBlueprint.cpp:211
void MyoDelegateBlueprint::SetInterfaceDelegate(UObject* newDelegate)
{
UE_LOG(LogClass, Log, TEXT("InterfaceDelegate passed: %s"), *newDelegate->GetName());
//Use format to support both blueprint and C++ form
if (newDelegate->GetClass()->ImplementsInterface(UMyoInterface::StaticClass()))
{
_interfaceDelegate = newDelegate;
}
else
{
//Try casting as self
if (ValidSelfPointer->GetClass()->ImplementsInterface(UMyoInterface::StaticClass()))
{
_interfaceDelegate = (UObject*)this;
}
else
{
//If you're crashing its probably because of setting causing an assert failure
_interfaceDelegate = NULL;
}
There is a function which can be used to check for condition called MyoDelegateBlueprint::IsValidDelegate().
**In MyoDelegateBlueprint.cpp:187
**
bool MyoDelegateBlueprint::IsValidDelegate()
{
return (_interfaceDelegate != NULL);
}
So, IsValidDelegate() can be used to detect condition and fix the crash.