- Изменено
Setting Atlas and Skeleton using Spine UMG Widget [UE4]
Hello hello!
I'm working with Spine (4.0.64) in Unreal (4.27.2) with the newest spine-cpp and spine-ue4 runtimes and I'm running into some problems with the UMG UI widget.
Specifically trying to load a spine animation into an empty Spine Widget (i.e. one that doesn't have any Atlas or Skeleton Data set at runtime). When I do (using the blueprint nodes below) nothing happens, the widget continues to be blank.
I've confirmed that they do get set using the Widget Reflector in Unity. I'm guessing I need to run some kind of initialization or something?
To add some more info, I was hoping to be able to use Unreal DataTables to store relevant information about spine animations. The row struct is as follows, which is what is being passed into the custom event in the picture above.
USTRUCT(BlueprintType)
struct FNpcAnimations : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString NpcName;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString AccompanyingBackgroundAnimation;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftObjectPtr<USpineAtlasAsset> SpineAtlasAsset;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftObjectPtr<USpineSkeletonDataAsset> SpineSkeletonDataAsset;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FNpcAnimationInfo> BackgroundAnimations;
};
Did you wire up the Tick event as well?
Yeah, Tick is wired up.
It works if another Data and Skeleton have been set before running the game. It's only when they are left blank that nothing happens.
The files I'm setting are called NPC_RoadkillBBQ-atlas and NPC_RoadkillBBQ-data. If I try to do that when the widget is setup like this before running:
then nothing happens, the widget is just blank. But if I set it up with another spine animation like this:
then it works fine.
One thing I was wondering if there's some in-editor setup being performed that isn't done when both are empty. If I change the Atlas from bakery-atlas to NPC_RoadkillBBQ-atlas or the Skeleton Data without clearing them of the bakery files the Unreal editor to crash with the following message:
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0xffffffffffffffff
UE4Editor_SpinePlugin!spine::SkeletonBinary::readSkin() [C:\Users\Bjorn\Documents\Unreal Projects\NT2\Plugins\SpinePlugin\Source\SpinePlugin\Public\spine-cpp\src\spine\SkeletonBinary.cpp:450]
UE4Editor_SpinePlugin!spine::SkeletonBinary::readSkeletonData() [C:\Users\Bjorn\Documents\Unreal Projects\NT2\Plugins\SpinePlugin\Source\SpinePlugin\Public\spine-cpp\src\spine\SkeletonBinary.cpp:274]
UE4Editor_SpinePlugin!USpineSkeletonDataAsset::GetSkeletonData() [C:\Users\Bjorn\Documents\Unreal Projects\NT2\Plugins\SpinePlugin\Source\SpinePlugin\Private\SpineSkeletonDataAsset.cpp:298]
UE4Editor_SpinePlugin!USpineWidget::CheckState() [C:\Users\Bjorn\Documents\Unreal Projects\NT2\Plugins\SpinePlugin\Source\SpinePlugin\Private\SpineWidget.cpp:164]
UE4Editor_SpinePlugin!USpineWidget::SynchronizeProperties() [C:\Users\Bjorn\Documents\Unreal Projects\NT2\Plugins\SpinePlugin\Source\SpinePlugin\Private\SpineWidget.cpp:96]
UE4Editor_UMG!UWidget::PostEditChangeProperty() [D:\Build\++UE4\Sync\Engine\Source\Runtime\UMG\Private\Components\Widget.cpp:1106]
UE4Editor_CoreUObject!UObject::PostEditChangeChainProperty() [D:\Build\++UE4\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\Obj.cpp:461]
UE4Editor_PropertyEditor!FPropertyNode::NotifyPostChange() [D:\Build\++UE4\Sync\Engine\Source\Editor\PropertyEditor\Private\PropertyNode.cpp:2356]
Hm, I'd have to debug this. Could you maybe send me a simple UE4/5 project that let's me reproduce this reliably? contact@esotericsoftware.com.
I figured out how to fix this eventually, but forgot to come back here to inform you of how I fixed it.
So if no Atlas og Skeleton Data is set at the start some initialization is skipped in SynchronizeProperties in SpineWidget.cpp.
That function isn't marked BlueprintCallable so I created a function in my Spine Manager BP that calls it.
UFUNCTION(BlueprintCallable)
void SynchronizeProperties(USpineWidget* Widget);
.....
void ANT2SpineManager::SynchronizeProperties(USpineWidget* Widget)
{
Widget->SynchronizeProperties();
}
Then I'm calling it Blueprints like so
Thanks for getting back to us! SynchronizeProperties()
is responsible for setting the skeleton data on the underlying slate widget. From my original reading of the docs, I was under the impression, that this would be invoked on every property change, be it in editor or at runtime. Looks like it isn't. I've created an issue for it here:
https://github.com/EsotericSoftware/spine-runtimes/issues/2144
So, SynchronizeProperties()
is only called when the widget is constructed, or the editor signals property changes. It is not called when properties are changed at runtime. Looks like the docs have been updated since.
I have now fixed this in both the 4.1 and 4.2-beta branches. The solution is to set the skeleton data on the slate widget in CheckState()
conservatively.