AddNativeStateEntryBinding - Bad Machine Ptr

I’m using UAnimInstance::AddNativeStateEntryBinding which is useful. But some times it is not working because of warning “bad machine ptr”.

I have three sub StateMachine.

  1. AMachine,
  2. BMachine,
  3. CMachine

I can successfully binding delegate for AMachine and BMachine and it is working fine!, but it is not working for CMachine. (actually only few anim states working and others newer working (after change name still not working!))

I debugged BindNativeDelegates and delegate is newer added to OnGraphStatesEntered.

Version UE4.8.1


Uploaded screenshoot and you can see PRIVATE_MachineDescription is null. Not sure why :\ Other StateMachines working fine.

Note: Updated to UE4.8.3 and same problem here.


Update 3

My AnimGraph design is:

         RootStateMachine
                 |
                 |
AStateMachine <-------> BStateMachine

Default AStateMachine is always active but BStateMachine active when transitiun rule is true. And having problem with BStateMachine :slight_smile:


Update 4

class UMTCharAnim : public UAnimInstance

void UMTCharAnim::NativeInitializeAnimation()
{
	Super::NativeInitializeAnimation();

	auto ForEachStateLambda = [&](UAnimBlueprintGeneratedClass* AnimBlueprintGeneratedClass, TFunctionRef<void(FBakedAnimationStateMachine&, const FBakedAnimationState&, int32)> Predicate)
	{
		for (FBakedAnimationStateMachine& StateMachine : AnimBlueprintGeneratedClass->BakedStateMachines)
		{
			int32 StateIndex = 0;
			for (const FBakedAnimationState& State : StateMachine.States)
			{
				Predicate(StateMachine, State, StateIndex);
				StateIndex++;
			}
		}
	};

	UAnimBlueprintGeneratedClass* AnimBlueprintGeneratedClass = Cast<UAnimBlueprintGeneratedClass>(GetClass());
	if (AnimBlueprintGeneratedClass != nullptr)
	{
		ForEachStateLambda(AnimBlueprintGeneratedClass, [&](FBakedAnimationStateMachine& StateMachine, const FBakedAnimationState& State, int32 StateIndex) {
			FString StateNameString = State.StateName.ToString();

			if (IsMovementStateName(State.StateName))
			{
				AddNativeStateEntryBinding(StateMachine.MachineName, State.StateName, FOnGraphStateChanged::CreateUObject(this, &UMTCharAnim::OnMovementStateEntry));
				AddNativeStateExitBinding(StateMachine.MachineName, State.StateName, FOnGraphStateChanged::CreateUObject(this, &UMTCharAnim::OnMovementStateExit));
			}
		});
	}
}

Everytime compile AnimGraph you will get “bad machine ptr”

Actually I’m doing this because I have lot of states, armored, unarmored, coversystem and they have crazy transition rules :slight_smile: so I just added to submachine for every stances. And I just relaized your roadmap for “Macro support in anim graph” Trello that will solve my problem I think.

Hey MSTF,

Thanks for report! I’ve assigned a member of our support staff to look into this issue, and they’ll post here if they have any questions.

Hi,

We haven’t seen this issue here, although we haven’t fully used native bindings yet with sub-state machines. However there are a few potential gotchas with native bindings that are worth running through to check:

  • Are you calling AddNativeStateEntryBinding in your UAnimInstance-derived class constructor? You must do this for systems to be set up in correct order.
  • Is your state machine getting Initialize() called on it when your UAnimInstance starts up (i.e. called from UAnimInstance::InitializeAnimation())? If not it could be disconnected from anim graph somehow.

Could you post some more examples of code from your project so we can help narrow down problem?

Just updated my answer.

Ah, I see that you are adding your native bindings in NativeInitializeAnimation(). This is generally not a good idea as NativeInitializeAnimation() can be called many times on an existing UAnimInstance, meaning you could have duplicate (or stale) entries left in bindings array. You can bypass this however by checking if a binding already exists before you add it, which I would recommend here.

There is a bug present here however. reason your PRIVATE_MachineDescription is NULL in this case is that only default states have Initialize() called on them, so your other sub-state machines that are not default entry state will not be properly set up. This means that at present you cannot use native bindings with sub state machines.

There is an interim fix for this if you are able to modify engine code. I need to test it to make sure but I think changing line in UAnimInstance::BindNativeDelegates:

const FBakedAnimationStateMachine* MachineDescription = StateMachine->GetMachineDescription();

…to:

const FBakedAnimationStateMachine* MachineDescription = AnimBlueprintGeneratedClass->BakedStateMachines.IsValidIndex(StateMachine->StateMachineIndexInClass) ? &(AnimBlueprintGeneratedClass->BakedStateMachines[StateMachine->StateMachineIndexInClass]) : NULL;

…should work. That way we don’t rely on node initialization to bind. I’ll enter an issue on our end to get this added to our Main branch once I’ve tested it.

This was submitted recently in this commit. It should be present in 4.10.