Unity Animator。播放如何同时过渡到另一个动画

时间:2019-02-04 01:39:01

标签: unity3d animation

我目前有一个基于Sprite的动画,播放器正在其中运行。我还有另一个动画,其中播放器正在运行并握住枪支并射击,其播放速度与不使用枪的情况下运行的速度完全相同。问题是,我正在使用Animator.Play();

我想要的是在正在运行动画的播放器所在的帧处开始以枪支动画运行的播放器。例如,如果玩家正在运行的动画位于第20帧,并且玩家按下了拍摄按钮,则在第20帧使用枪支动画来运行奔跑。

这是到目前为止我的代码的粗略示例:

if (!shooting) {animator.Play("PlayerRunning");}

if (shooting) {animator.Play("PlayerRunningShoot");}

我认为最好的例子是NES超人游戏的超人射击动画之一,当您在跑步时按'B'时,他的手臂会立即弹出进行射击。

如果这让我困惑,请告诉我。

1 个答案:

答案 0 :(得分:3)

看来实际上使用Animation Layers对您来说会更有趣!我无法在此处重新创建完整的手册-查看文档和this tutorial


但是,Animator.Play 有一个可选参数

  

normalizedTime :介于零和一之间的时间偏移。

因此您可以使用当前动画所在的偏移量开始新动画

您可以使用Animator.GetCurrentAnimatorStateInfo来获取当前状态,而normalizedTime则是当前剪辑位于

Animator.GetCurrentAnimatorClipInfo获取剪辑的信息(例如长度)。

然后引用您的目标剪辑(我希望这样做),或者您可以使用Animator.runtimeAnimatorController获取所有AnimationClip,然后使用LinQ FirstOrDefault查找具有目标名称的剪辑:

(在我的智能手机上键入此内容,因此没有保修)

using System.Linq;

// ...

if (!shooting)
{
    // assuming layer 0
    var state = animator.GetCurrentAnimatorStateInfo(0);
    var clipInfo = animator.GetCurrentAnimatorClipInfo(0);

    // so the time you want to start is currentNormalizedTime * current.length / newClip.length
    // if your clips will allways have the exact same length offcourse you can
    // simply use the currentNormalizedTime
    var currentNormalizedTime = state.normalizedTime;
    var currentRealtime = currentNormalizedTime * clipInfo[0].clip.length;

    var newClip = animator.runtimeAnimatorController.animationClips.FirstOrDefault(c => string.Equals(c.name, "PlayerRunning"));

    var newNormalizedTime = currentRealtime / newClip.length;

    // for some reason it seems you can not use the optional parameters as you usually would
    // like ("PlayerRunningShoot", normaizedTime = newNormalizedTime)
    animator.Play("PlayerRunning", -1, newNormalizedTime);
}

if (shooting)
{
    var state = animator.GetCurrentAnimatorStateInfo(0);
    var clipInfo = animator.GetCurrentAnimatorClipInfo(0);
    var currentNormalizedTime = state.normalizedTime;
    var currentRealtime = currentNormalizedTime * clipInfo[0].clip.length;

    var newClip = animator.runtimeAnimatorController.animationClips.FirstOrDefault(c => string.Equals(c.name, "PlayerRunning"));

    var newNormalizedTime = currentRealtime / newClip.length;

    animator.Play("PlayerRunningShoot", -1, newNormalizedTime);
}

您还可以使用

在运行时创建平滑过渡

Animator.CrossFadeAnimator.CrossFadeInFixedTime

if (!shooting) 
{
    // ...       

    // here the transition takes 0.25 % of the clip
    animator.CrossFade("PlayerRunning", 0.25f, -1, 0, newNormalizedTime);
}

if (shooting) 
{
    // ...

    // here the transition takes 0.25 seconds
    animator.CrossFadeInFixedTime("PlayerRunningShoot", 0.25f, -1, 0, newNormalizedTime);
}