Hi, in the engine you should find that there is always one less frame in an animation sequence vs the number of keys. So there is a final key in each animation which is not necessarily the same pose as the final frame of the animation. Another way to think of it is that the frames sit between each of the keys.
I’ve included a screenshot below as an example from the final frame of one of the locomotion animations in the Gameplay Animation Sample. If you set the animation to use stepped rather than linear interpolation, you can see what the poses in each frame looks like:
[Image Removed]And in that example, the final frame (the 120th frame, which is frame number 119) has a different pose than frame 0 (and also a different pose than the final key, which is the same as the first key).
With that in mind, I’ll go through each of the APIs that you mentioned.
> UAnimSequenceBase::GetNumberOfFrames - deprecated function, returns GetNumberOfSampledKeys() as the number of frames.
This method is really old at this point and has been deprecated for a long time. But back in the UE4 days when it was used, the implementation was wrong and it caused problems since number of frames != number of keys. I wouldn’t use that function, and we’ve removed it in 5.6.
> UAnimationBlueprintLibrary::GetNumFrames - the number of frames is GetNumberOfSampledKeys() - 1
This is as expected based on the info above.
> UAnimDataModel::PostLoad - initializes NumberOfFrames to NumberOfKeys - 1
Also as expected.
> UAnimSequenceBase::GetFrameAtTime - the maximum frame number (0-indexed) is GetNumberOfSampledKeys() - 1 in the clamp, which implies the number of frames is actually GetNumberOfSampledKeys()
This one is interesting. I think we have a bug in UAnimSequenceBase::GetNumberOfSampledKeys which is called from UAnimSequenceBase::GetFrameAtTime. UAnimSequenceBase::GetNumberOfSampledKeys is just doing a straight conversion of sequence length into frame time and returning that as the number of keys. So if you have a 2 second clip at 30fps, that will return 60 keys. But that’s not correct - it’s 60 frames and 61 keys. I’ll need to confirm this with the dev team next week. That API is only used by montages, which is possibly why we haven’t seen it causing problems. Anim sequences all use the UAnimSequence::GetNumberOfSampledKeys implementation instead.
> UAnimToTextureBPLibrary::GetAnimationFrameRange - again treats GetNumberOfSampledKeys() - 1 as the end frame index, where the start frame index is 0, again implying GetNumberOfSampledKeys() is the number of frames.
There is also a bug in this method by the looks of it, but it’s not the OutEndFrame calculation. That method also returns the number of frames in the animation. But it’s calculated by doing `OutEndFrame - OutStartFrame + 1;` which means we’re effectively returning the number of keys, not frames. Back in UAnimToTextureBPLibrary::AnimationToTexture we use that to calculate the time to sample from so we’ll effectively try and sample frame 60 (which is frame 0). That would mean a duplicate frame in the texture that gets generated.
However, looking at the material function, when we sample the texture we always subtract 1 from the total number of frames stored in the data asset. So I think in practice, that means we never sample the duplicate frame when playing back the material. But if you see a duplicated frame during playback, please let me know. It’s hard to say for sure without testing a working setup.
> BlendSpaceAnalysis.h under the Persona module - uses GetNumberOfSampledKeys() - 1 as the number of sampled keys (???) but later seems to use it as the last sample key index.
I’ll need to check with the dev team and follow up on this one. The variable naming doesn’t help here, but it is effectively working with frames rather than keys.