Hi,
if I try to “Play Anim Montage” from within the characterBlueprint, it does not work, it used to work fine,
of course “MontagePlay” works fine from within characterAnimationBlueprint and I could test all the AnimationMontages so everything is right there.
I’ve spent hours on this and can’t see why this is happening, log doesn’t say nothing, and if I check for duration of the AnimationMontage being played I get 0 which means for some reason it failed to play it.
Confusing…
Would you mind posting a screenshot of your setup?
Hey, I added the screenshot now,
this used to work untill 4.5.1 version and it doesn’t work in 4.7.1,
I haven’t tested on 4.6 yet.
As I mentioned the duration returned by the Play Anim Montage function is 0.0,
which means that it failed to play, as I’ve read in the docs.
This was done in a blueprint extended from C++ character class.
Maybe it could have something to do with that in code from 4.5.1 version I was doing the spawning of these CharacterBPs from the code - gamemode class,
then in 4.6 → 4.7.1 this method stopped working so I changed the code to handle the spawning parts from withing GameModeBlueprint.
I explained it here in my answer: https://answers.unrealengine.com/questions/142829/spawnactor-failed-spawning-a-blueprint.html
However animations play great if triggered from the CharacterAnimationBlueprint using “Montage Play” function…
So obviously a different solution would be to use MontagePlay function in CharacterAnimationBlueprint ,
but that would mean I’d need to check some variables from the CharacterBP on each “onUpdateAnimation” event and play MontagePlay when needed, but this method would take a lot more checking and processing, considering I have many Characters in the game it seems a lot more optimized solution to play the animations only for the Character that was recently clicked.
I am thinking I should just rewrite all the blueprints to code, it’ll take some time but it’ll work.
I have been testing this further, I rewrote all blueprint parts into code, and the problem remained.
I now have only 2 blueprints remaining in my game now, these are the AnimationBlueprint(with basic setup and named slot) and the HUD blueprint.
Once I switched to using my c++ gamemode class instead of blueprinted one for my world settings,
I avoided problems with spawning blueprints I had in the Question link - posted above,
and then I also changed my character to be a C++ class, not a blueprint so that problem is now avoided twice.
Anyway to get back to the topic, I tested 3 ways of playing animation from the Character class:
1.PlayAnimMontage (didn’t work)
2.PlayAnimation (works)
3.MontagePlay (works, but you need to cast your AnimInstance to Character class)
and again I can confirm PlayAnimMontage() returns 0.0 duration right off, like it wouldn’t be able to find the UAnimMontage or the skeletalMesh. Then I looked at the code again, and discovered the problem, when I called PlayAnimMontage, I called it in my character class, and character.h parent class has a variable “Mesh” so you can use that to plug in your skeletal mesh , in other words when you call PlayAnimMontage() it will automatically want to play the animation on the “Mesh” , in my case I created FrogSkelMesh Subobject so that’s why it didn’t work,
once I plugged in my skeletalMesh to the “Mesh” instead, then it played fine.
Here’s the code:
First the Constructor part:
AJumpyFrogCharacter::AJumpyFrogCharacter()
{
struct FConstructorStatics
{
ConstructorHelpers::FObjectFinderOptional<USkeletalMesh> skelMesh;
ConstructorHelpers::FObjectFinderOptional<UMaterial> BlueMaterial;
ConstructorHelpers::FObjectFinderOptional<UMaterial> OrangeMaterial;
FConstructorStatics()
: skelMesh(TEXT("/Game/Characters/FrogChar/SkelMesh/FrogSkelMesh"))
, BlueMaterial(TEXT("Material'/Game/Characters/FrogChar/Materials/BlueDartFrog_mat.BlueDartFrog_Mat'"))
, OrangeMaterial(TEXT("/Game/Characters/FrogChar/Materials/OrangeFrog_Diffuse_Mat"))
{
}
};
static FConstructorStatics ConstructorStatics;
// Create dummy root scene component
DummyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("Dummy0"));
RootComponent = DummyRoot;
// Create skeletal mesh component
FrogSkelMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Frog0"));
FrogSkelMesh->SetSkeletalMesh(ConstructorStatics.skelMesh.Get());
FrogSkelMesh->SetRelativeScale3D(FVector(1.f, 1.f, 0.25f));
FrogSkelMesh->SetRelativeLocation(FVector(0.f, 0.f, 0.6f));
FrogSkelMesh->SetMaterial(0, ConstructorStatics.OrangeMaterial.Get());
FrogSkelMesh->AttachTo(DummyRoot);
FrogSkelMesh->OnClicked.AddDynamic(this, &AJumpyFrogCharacter::FrogClicked);
FrogSkelMesh->OnInputTouchBegin.AddDynamic(this, &AJumpyFrogCharacter::OnFingerPressedFrog);
FrogSkelMesh->SetCollisionProfileName("BlockAll");
const ConstructorHelpers::FObjectFinder<UAnimBlueprint> AnimObj(TEXT("/Game/Characters/FrogChar/Blueprints/FrogAnimBP"));
FrogSkelMesh->SetAnimInstanceClass(AnimObj.Object->GeneratedClass);
Obviously I shouldn’t have created FrogSkelMesh but assign those things to the “Mesh” instead, so once I assigned my skeletal Mesh to the “Mesh” variable, then PlayAnimMontage worked:
GetMesh()->SetSkeletalMesh(ConstructorStatics.skelMesh.Get());
GetMesh()->SetAnimInstanceClass(AnimObj.Object->GeneratedClass);
1.PlayAnimMontage():
this->PlayAnimMontage(JumpRightMontage, 1);
2.PlayAnimation():
this->FrogSkelMesh->PlayAnimation(JumpRightMontage, 1);
3.MontagePlay():
UJumpyFrogsAnimInstance* AnInstnc = Cast<UJumpyFrogsAnimInstance>(FrogSkelMesh->GetAnimInstance());
if (AnInstnc)
{
AnInstnc->Montage_Play(JumpRightMontage, 1);
}
To wrap this up, it was basically a very little sloppy mistake, all I would need to do is assign my skeletal mesh to the “Mesh” inherited variable in the CharacterBlueprint, and for some reason when I was rebuilding this project I added a SkeletalMesh component instead of just using the “Mesh” variable, I’m including a screenshot.