Having an skeletal mesh animation I wanted to spawn a static mesh and attach it to the socket of skeletam mesh.
First idea
Just create UPROPERTY() UStaticMeshComponent* MeshComponent;
and allow it to be modified in the editor, so that any1 can pick proper mesh per animation.
tl;dr: it simply was crashing at some point (it was probably when it was attached to a different component but I can’t remember now). Could it possibly be that due to notification not having World reference it won’t create attachable components?
Second idea idea - construct static mesh component
UAnimNotifyState deriving class seemed to be a perfect candidate for just it because it features NotifyBegin
and NotifyEnd
methods - that seems to be super handy. There were 2 additional variables that I wanted to expose for change:
- Mesh - so that you can tell what mesh should be spawned in the editor,
- SocketName - so that you can also pick where the mesh should be bound to,
So I came with a class like this (you might find a more comfortable preview on GitHub):
#pragma once
#include "AnimNotifyWithComponent.generated.h"
/*
* A solution based on manually creating UStaticMeshComponent in NotifyBegin function.
* It work ingame no problem, but causes weird freeze in the editor anim preview.
*/
UCLASS()
class UAnimNotifyWithComponent : public UAnimNotifyState
{
GENERATED_UCLASS_BODY()
// Exposed Mesh property, so that mesh can be changed in the editor.
UPROPERTY( EditAnywhere )
UStaticMesh* Mesh;
// Name of the socked, where the item will be placed.
UPROPERTY( EditAnywhere )
FName SocketName;
private:
UPROPERTY()
UStaticMeshComponent* MeshComponent;
virtual void NotifyBegin( USkeletalMeshComponent * MeshComp, UAnimSequenceBase * Animation, float TotalDuration ) override;
virtual void NotifyEnd( USkeletalMeshComponent * MeshComp, UAnimSequenceBase * Animation ) override;
};
You may find cpp file here.
In game it works just fine.
Issue
The code was not working in the editor prview. Once editor hits my notification (and calls NotifyBegin
) it freezes for couple seconds giving an error on assigning reference to UPROPERTY()
, here’s a dump:
UE4Editor-Core.dll!FWindowsPlatformStackWalk::StackWalkAndDump() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\core\private\windows\windowsplatformstackwalk.cpp:175]
UE4Editor-Core.dll!FDebug::EnsureFailed() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\core\private\misc\outputdevice.cpp:276]
UE4Editor-Core.dll!FDebug::OptionallyLogFormattedEnsureMessageReturningFalse() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\core\private\misc\outputdevice.cpp:385]
UE4Editor-Engine.dll!UActorComponent::RegisterComponent() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\components\actorcomponent.cpp:866]
UE4Editor-sample1-6656.dll!UAnimNotifyWithComponent::NotifyBegin() [c:\users\mlewandowski\documents\unreal projects\sample1\source\sample1\animnotifywithcomponent.cpp:59]
UE4Editor-Engine.dll!UAnimInstance::TriggerAnimNotifies() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\animation\animinstance.cpp:1213]
UE4Editor-Engine.dll!UAnimInstance::UpdateAnimation() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\animation\animinstance.cpp:433]
UE4Editor-Engine.dll!USkeletalMeshComponent::TickAnimation() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\components\skeletalmeshcomponent.cpp:479]
UE4Editor-Engine.dll!USkeletalMeshComponent::TickPose() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\components\skeletalmeshcomponent.cpp:588]
UE4Editor-Engine.dll!USkinnedMeshComponent::TickComponent() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\components\skinnedmeshcomponent.cpp:451]
UE4Editor-Engine.dll!USkeletalMeshComponent::TickComponent() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\private\components\skeletalmeshcomponent.cpp:600]
UE4Editor-UnrealEd.dll!UDebugSkelMeshComponent::TickComponent() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\editor\unrealed\private\animation\debugskelmeshcomponent.cpp:728]
(...)
Third approach - spawn AStaticMeshActor
Let me just note at the very begining that this is overkill The idea was to:
- Spawn AStaticMeshActor that would be owned by Animation Skeletal Mesh owner.
- Hijack it’s StaticMeshComponent and attach it to the Skeletal Mesh.
- Destroy AStaticMeshActor because… I don’t need it for anything beside constructing StaticMeshComponen!
This idea is totally crazy, but implementation can be found in AnimNotifyWithActor class.
Issue
Here’s the thing: it works both for the editor and game. It’s the worst solution, yet it works the best.
The code
I decided to push all the code to a GitHub repository, feel free to see it there.