ChuanXin 发表于 2021-12-5 18:52

Unity开发笔记-Animancer(1)

在网上没啥中文教程,看有些大佬又在用这个插件,动画机动画一多也头疼.就试着使用这个插件看看能不能代替Controller吧.仅做一些记录吧.以防自己忘了能不用再翻英文文档瞎看.只是做了一些马虎甚至不正确的翻译,
一方面是我的记性比较差,这个东西很早以前就看过一遍了,最近半个月都在想怎么实现自己的简单游戏框架,半个月过去了还没设计出大体的结构,准备十一月底找工作所以还是先做出个作品混口饭吃再说.另一方面是觉得说明一遍能让自己理解的更加透彻.
第一次开贴记录.希望别烂尾.第一课 - Quick Play

需求的Component


[*]Animator(不需要设置Animator Controller)
[*]AnimancerComponent(这是一个与Animator一起工作的Component,不是自己编辑的脚本,而是插件自带的脚本,直接添加就好)


编写脚本

using Animancer;
using UnityEngine;

public class PlayAnimationOnClick : MonoBehaviour
{
    // 这是上述说的两个必要Component中的一个.
    private AnimancerComponent _Animancer;

    // 这是自己的动画Clip
    private AnimationClip _Idle;
    private AnimationClip _Action;

    private void OnEnable()
    {
      // 播放动画靠<AnimancerComponent>组件来控制(目前的教程来看)
      _Animancer.Play(_Idle);
    }

    private void Update()
    {
      if (Input.GetMouseButtonDown(0))
      {
            var state = _Animancer.Play(_Action);
            // state.Events.OnEnd 动画播放结束时触发的事件
            state.Events.OnEnd = OnActionEnd;

      }
    }

    private void OnActionEnd()
    {
      _Animancer.Play(_Idle, 0.25f);
    }
}
总结


[*]需要添加Animator(不用指定Controller)和AnimancerComponent两个组件
[*]自己编写的动画控制脚本需要添加AnimancerComponent 属性并且指定其对象.
[*]使用成员的方式添加自己的动画
[*]通过调用AnimancerComponent .Play(动画成员变量名)来调用动画
[*]state.Events.OnEnd在动画结束时会调用指定的方法.PS:但是这好像有个bug,你的一个跑步动画如果是循环的话他会在第一次动画结束时调用,然后每一帧都调用这个事件.
第二课 Playing And Fading

接着上述的内容,这一节是讲解动画过度(渐变?)?反正是这么个意思.
// 动画衔接的简写形式,把一个代码块中的两句话写成一句话罢了
public void PlayThenIdle()
{
    _Animancer.Play(_Action).Events.OnEnd = () => _Animancer.Play(_Idle);
}

// 指定动画播放的时间,0就是从头播放
_Animancer.Play(_Action).Time = 0;Time Scale

Time Scale组件可以控制动画的播放速度.不知道是插件自带的还是系统自带的.

过渡

_Animancer.Play(_Idle, 0.25f);这个0.25f就是动画过度的时长,以秒为单位
注意 : 这个0.25f不是从idle过过渡到其他动画的时长,而是其他动画过度到Idle的时长.不要搞混了,如果你想从idle平滑过度到Walk你需要_Animancer.Play(_Walk, 0.25f);而不是idle.我设置了过渡动画为2秒,这里为了更好的看清楚就用了TimeScale做了慢放,可以看出来是在Idle结束之后在Action开头进行的过渡,根据Weight可以看到权重(不知道翻译过来是不是权重)



过渡动画演示

愚蠢的过渡策略

public void BadCrossFadeFromStart()
{
    _Animancer.Play(_Action, 0.25f).Time = 0;
}


官方演示愚蠢的过渡策略

根据官方给出的GIF可以看出来这个代码从Idle到Swing时拥有过渡动画,但是在Swing动作自身一直播放的时候却没有过渡效果,官方给出的原因是
anAnimancerStateonly has oneTimevalue. It can either be at its previous value or at the beginning, but not both and trying to interpolate between the two would mean it plays backwards for a moment which isn't very useful either.这里不是很懂,到时候学到后面看看能不能理解吧,这个previous value和 at the beginning的意思是先前的值和开始的值,先前的值是Idle的Time吗?没太懂.希望有人解答一下.
正确的做法

public void GoodCrossFadeFromStart()
{
    _Animancer.Play(_Action, 0.25f, FadeMode.FromStart);
}


好的过渡策略

官方这里的解释说 FadeMode.FromStart 尝试过渡一个正在已经在播放的动画,他会创造第二个AnimancerState来播放同一个AnimationClip,就叫Copy Clip吧,因为原先的能够正常播放,这可能就是解释了上面的那个问题,就相当于两个相同动作不同对象的成员变量吧?
注意 : 官方说你创造五个以上的这种Copy Clip的时候会报错,觉得你的代码有bug.想要解决这个问题也很简单调用`AnimancerLayer.SetMaxStateDepth`来预先增加Copy Clip的最大值一个好的从开始到结束的例子

public void GoodCrossFadeFromStartThenIdle()
{
    _Animancer.Play(_Action, 0.25f, FadeMode.FromStart)
      .Events.OnEnd = () => _Animancer.Play(_Idle, 0.25f);
}这里因为可能重复调用_Action,所以加上了过渡延迟和 FadeMode.FromStart.以防玩家重复的触发这个方法.

结语

第一次写文章,英语也学的不太好,勉强靠google翻译,图片加代码理解.花了大概一个小时完成了这次记录.代码或解释有问题不到位,错误的地方还望指出.

RedZero9 发表于 2021-12-5 18:58

[拜托]感谢分享。
页: [1]
查看完整版本: Unity开发笔记-Animancer(1)