我目前有一个基于精灵的动画,其中播放器正在运行。我还有另一个动画,其中玩家奔跑并举起枪射击,其播放速度与玩家不带枪奔跑的速度完全相同。问题是,我正在使用 Animator.Play();
我想要的是在玩家运行动画当前所在的帧开始播放枪动画。例如,如果玩家奔跑动画位于第 20 帧,并且玩家按下射击按钮,则在第 20 帧播放持枪奔跑动画。
这是到目前为止我的代码的一个粗略示例:
if (!shooting) {animator.Play("PlayerRunning");}
if (shooting) {animator.Play("PlayerRunningShoot");}
Run Code Online (Sandbox Code Playgroud)
我认为最好的例子是 NES 洛克人游戏的洛克人射击动画之一,当你在跑步时按“B”时,他的手臂会立即弹出来射击。
如果这些内容对我的要求有任何困惑,请告诉我。
看起来实际使用动画层对您来说会更有趣!我无法在这里重新创建完整的手册 - 请查看文档和本教程。
但是,Animator.Play 有一个可选参数
NormalizedTime:零和一之间的时间偏移。
这样您就可以使用当前动画所在的偏移量来启动新动画
您可以使用Animator.GetCurrentAnimatorStateInfo来获取当前状态和normalizedTime当前剪辑位于
并Animator.GetCurrentAnimatorClipInfo获取剪辑的信息(例如长度)。
要么引用您的目标剪辑(我更喜欢这样),要么您可以使用Animator.runtimeAnimatorController来获取所有AnimationClips ,而不是使用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 always have the exact same length of course 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);
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用以下命令在运行时创建平滑过渡
Animator.CrossFade或Animator.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);
}
Run Code Online (Sandbox Code Playgroud)