Play Light Switch Animation and c++

Maybe I’m over thinking this or over engineering it, but I’m stumped

I created a light switch skeletal mesh model in Blender. It has 2 animations, ON and OFF.

I imported it into UE4 and all is good so far

I then have a ULightSwitchObject class, derived from AActor, which has a bool variable on it, to say if the light switch is on or off
Lets say the bool name is bState (false = off, true = on)

I have a Use() method that’s called when you interact with the mesh, that toggles bState perfectly. all is working well so far.

my question now, how do I play the required animation, based on the bState value?
I’ve searched everywhere and the only examples I find, are either serious blend space animations for character movement, or blueprint examples

I need something simple, to play a single animation, based on a variable in the class.

Please help!!!

GetYourMesh()->Play(bool bLooping);

Yeah that doesn’t work… still stuck

Darn it, i used that to drop my gate but have not tested it yet. Sounds like i need to find a different way to play the animation. Thanks for the info

ok, it’s 3 days later, and I still havn’t gotten any further

so i’m asking for help again please

here’s is the code snippet that fires when I click on a light switch object

I’m seeing all the UE_LOGs so I know that the code block is executing

Here is my Anim Montage

Is there another blueprint I need to create that I’m not aware off?

Please help!

I’m gonna throw up

So I found my problem:

My BeginPlay method was empty… as in, it didn’t even call the Super::BeginPlay();

Thus, the actor was in the world, but never actually “activated”

ARGHGASDFR!@(u$(!@J

4 days of debugging and it’s something so stupid

does this work?



GetYourMesh()->Play(bool bLooping);


I’m sure that would. I ended up using SkeletalMeshComponent->GetAnimInstance()->Montage_Play(AnimMontage), that’s only cause the 2 animations are in the montage. But I’m sure the ->PlayAnimation() method will work

Glad you figured that out , that kinda issue can be tough to find.

I’d be interested in comparing notes on how you are loading the montages in code. This works (we have the additional requirement of being able to pause and reverse montages from code at any point) but can it be simplified? Especially having to load a blueprint to play it. :frowning:

.h file:



private:

/**
* Animation montage used for custom keyframe animations
* Must be loaded in constructor.
* There can only be one montage.
*/
UAnimMontage* _animationMontage = nullptr;

/**
* Animation instance at runtime.
* Used to update the currently playing animation montage.
* Reference automatically set at BeginPlay() when montage is set.
*/
UAnimInstance* _animationInstance = nullptr;

/**
* Montage instance at runtime.
* Used to update the currently playing animation montage.
* Reference automatically set at BeginPlay() when montage is set.
*/
FAnimMontageInstance* _montageInstance = nullptr;

/**
* Length of currently assigned animation montage.
* Automatically calculated at BeginPlay() when montage is set.
*/
float _montageLength = 0.0f;

public:

/**
* Set the montage animation position as a percentage from 0-1.
* Montage will snap to position adjusted for length of the montage.
*/
void SetMontageAnimationPosition(float position);

/**
* Set up animation montage at BeginPlay().
* Plays montage, pauses it, and saves references to control it.
* Required or montage will not work.
*/
void SetMontageAnimation(FString montageAssetNameAndPath, FString blueprintAssetNameAndPath);

protected:

/**
* Set up animation montage at BeginPlay().
* Required or animation montage will not play.
*/
void InitializeAnimationMontage();


.cpp file:



/**
* Set the montage animation position as a percentage from 0-1.
* Montage will snap to position adjusted for length of the montage in seconds.
*/
void UInteractiveSkeletalMesh::SetMontageAnimationPosition(float position)
{
  if (_animationInstance )
  {
    if (_montageInstance)
    {
      _montageInstance->SetPosition(_montageLength * position);
    }
    else LOG_ERROR("SetMontageAnimationPosition(): montage instance is null: %s", *GetLocalUniqueName());
  }
  else LOG_ERROR("SetMontageAnimationPosition(): animation instance is null: %s", *GetLocalUniqueName());
}

/**
* Set a single montage for mesh to play.
* Object can interpolate and play montages.
* Object cannot play keyframe animations and montages.
*/
void UInteractiveSkeletalMesh::SetMontageAnimation(FString montageAssetNameAndPath, FString blueprintAssetNameAndPath)
{
  // load montage and enable tick
  _animationMontage = ConstructorHelpers::FObjectFinder<UAnimMontage>(*montageAssetNameAndPath).Object;
  if (_animationMontage == nullptr)
  {
    LOG_ERROR("%s: anim montage load failed: %s", *GetLocalUniqueName(), *montageAssetNameAndPath);
    return;
  }

  // load animation blueprint
  // this is a dummy blueprint animation required to control animation montage from code
  FString animBlueprintClassPath = blueprintAssetNameAndPath;
  animBlueprintClassPath += "_C";
  const ConstructorHelpers::FObjectFinder<UAnimBlueprintGeneratedClass> AnimBlueprintInstance(*animBlueprintClassPath);
  if(AnimBlueprintInstance.Succeeded())
  {
    SetAnimInstanceClass(AnimBlueprintInstance.Object);
  }
    else LOG_ERROR("%s: anim blueprint load failed %s", *GetLocalUniqueName(), *animBlueprintClassPath);
  }
}

/**
* Set up animation montage at BeginPlay().
* Plays montage, pauses it, and saves references to control it.
* Required or montage will not work.
*/
void UInteractiveSkeletalMesh::InitializeAnimationMontage()
{
  if (_animationMontage)
  {
    _animationInstance = GetAnimInstance();
    if (_animationInstance)
    {
      _montageLength = _animationInstance->Montage_Play(_animationMontage);
      _animationInstance->Montage_Pause();
      _montageInstance = _animationInstance->GetActiveMontageInstance();
      if (_animationInstance == nullptr)
      {
        LOG_ERROR("BeginPlay(): failed get montage instance: %s", *GetLocalUniqueName());
      }
    }
    else LOG_ERROR("BeginPlay(): failed get animation instance: %s", *GetLocalUniqueName());
  }
}


i just added a component to my start gate class in my map and in details panel i added in the animation in the animation section and set it to play no blueprints but play my in model made animation. and i’m running one line to activate it.


GetYourMesh()->Play(bool bLooping);

I have 3 states in my gate code in tick. when my game timer runs out to 0 it activate my gate drop state and then its tick runs the gate drop state code and it runs that animation to drop the gate. Something i need to figure out is how to get a hold of the component i added, where is it at in code? I hate blueprints < can not see what is really going on. Like we can in code

EDIT: I want to load the model and animation right into my class, but i can not seem to figure out how, it crashes my class every time i try. So i did the add component to my class in editor in its details panel for the time being. I am still figuring all this animation stuff out. how it done in this engine. or how to do it.