我们的项目中并没有要求那么精确的动作表现,但是因为有攻击动作的存在,如果抬手就算伤害的话,表现有些奇怪。所以做了如下改动:
1,播放动作中间帧执行伤害判断
2,播放动作时长>攻速,加快播放速度
2,播放动作时长<=攻速,速度为1
测试代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestAtkAnim : MonoBehaviour
{
public Animator anim;
public float atkSp = 1f;
public float sp = 0.2f;
// Start is called before the first frame update
void Start()
{
//初始化动作模型
AnimationClip[] clips = anim.runtimeAnimatorController.animationClips;
Debug.Log(clips.Length);
foreach (AnimationClip clip in clips)
{
Debug.LogError(clip.name + " " + clip.length);
if (clip.name == "attack")
{
atkSp = clip.length;
break;
}
}
}
public void SetAnimationSpeed(Animation ani, string name, float speed)
{
if (null == ani) return;
AnimationState state = ani[name];
if (!state) state.speed = speed;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
var _sp = 1f;
if (atkSp > sp) _sp = atkSp / sp;
anim.speed = _sp;
anim.SetTrigger("attack");
}
}
/// <summary>
/// 获得animator下某个动画片段的时长方法
/// </summary>
/// <param animator="animator">Animator组件</param>
/// <param name="name">要获得的动画片段名字</param>
/// <returns></returns>
public float GetAnimatorLength(Animator animator, string name)
{
//动画片段时间长度
float length = 0;
AnimationClip[] clips = animator.runtimeAnimatorController.animationClips;
Debug.Log(clips.Length);
foreach (AnimationClip clip in clips)
{
Debug.LogError(clip.name + " " + clip.length);
if (clip.name.Equals(name))
{
length = clip.length;
break;
}
}
return length;
}
}
这里主要用了runtimeAnimatorController.animationClips取到动画时长,然后使用 动画时长/攻速时间=动画倍速 。最后表现为攻速越快,人物动作越快。
测试效果如下:
原攻击时长为1.3;当攻速时长设置为0.2时候,动画在0.2秒内播完。
至于伤害判断,可以进一步通过状态机划分来实现。这里就不再赘述。