Assigning TObjectPtr to raw pointer results in null

I am working with storing UAnimMontage in a struct so that I can assign them in the editor, and then use them in either C++ or Blueprints if need be

USTRUCT(BlueprintType)
struct FDefaultAnim
{
    GENERATED_USTRUCT_BODY()
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TObjectPtr<UAnimMontage> Punch;
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TObjectPtr<UAnimMontage> Kick;
};
UENUM(BlueprintType)
enum class EAnimLookup
{
    NONE = 0,
    Punch = 1,
    Kick = 2
};
bool GetDefaultAnim(EAnimLookup inLookup, UAnimMontage* returnAnim)
{
     switch( inLookup )
     {
         case EAnimLookup::Punch:
              // 'the anim in the struct has a value'
              // 'but the assignment does not complete'
              returnAnim = DefaultAnims.Punch;
              // 'returnAnim is NULL here'
              break;
         case EAnimLookup::Kick:
              returnAnim = DefaultAnims.Kick;
              break;
         default:
              break;
     }
     return (returnAnim != nullptr)
}

I have set the animation in the blueprint, and I have checked the instance of the Object that holds the struct that it is set in the editor and both are a valid UAnimMontage.
when I attach the Visual Studio Debugger and set a breakpoint at the assignment, and on the break following the assignment.
for example DefaultAnims.Punch will have value and returnAnim will be NULL when the line for the assignment is executed, then on the line for the break returnAnim is still NULL

I have found a couple answers that don’t work out or don’t make sense in the situation:

  • change Arg1 to TObjectPtr<UAnimMontage> but then I can’t have it be a UFUNCTION
  • pass the arg1 as UAnimMontage*& which is supposed to fix this it doesn’t work.
  • use Get() on the retrieving side which still does nothing.
  • pass arg1 as UAnimMontage** then de-reference on the return variable this doesn’t work and doesn’t make sense.

Not sure if you can trust the debugger in this specific scenario, there’s a decent chance your assigment is optimized away since it doesn’t really have any effect there.

You’d have better visibility with logs or print strings.

switch (inLookup)
{
    case EAnimLookup::Punch:
        returnAnim = DefaultAnims.Punch;
        UE_LOG(LogTemp, Warning, TEXT("%s -> %s"), *AActor::GetDebugName((AActor*)DefaultAnims.Punch), *AActor::GetDebugName((AActor*)returnAnim));
        break;
}

Anyhow, the proper argument would be UAnimMontage*&, although UAnimMontage** could work too but won’t support blueprints.

thanks for the markup help.
that UE_LOG() looks really cool too.
I wasn’t setting the animation into its home, before checking that member to see if it was OK to work with the animation :eyes:
" Set the variable before checking the variable "

putting the Debugger on the Log statement does show the assignment working…

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.