Unity3d Animator的Recycle 复用

这次在Animator上遇到了一些问题,折腾了几天,主要是关于Animator的复用问题。

这次项目中的Monster的出现和消失有点频繁,故而想用对象池来复用它,但是在第二使用的时候,发现某些SpriteRenderer的alpha = 0, 且手动修改后,下一帧又会被重置回来。刚开始以为是其中的Animation(修改alpha的Die Animation)一直在Run,后来用StateMachineBehaviourOnStateEnter, OnStateExit, OnStateUpdate日志发现AnimatorState是正确的,排除Animation State的问题。

接着就仔细查看State面板上的属性参数。在查询到WriteDefault的时候,发现了一些端倪。

WriteDefault 有的人解释是动画播放完毕后是否将状态重置为默认状态,这是不正确的

官方的解释是

Whether or not the AnimatorStates writes back the default values for properties that are not animated by its Motion

翻译一下是在State中不被Motion修改的属性值都会变为默认值(DefaultValues),这里的属性是Animator所有Motion修改属性中集合。

这里的DefaultValues,是怎么计算的呢?官方的解释是

When the Animator is Initialized, we go through all the clips in the current AnimatorController, and we collect all the animated values of all the clips. It also collects the current value (from the scene) of all those, and saves this as the default value. When you play a state with WriteDefaults that doesn't animate a value, the default value is written.

官方技术人员给出了一种挺好的解决方案:

animator.Crossfade("DefaultPose", 0f); //Force switch to Default Pose State, instant transition
animator.Update(0f); //force transition completion, your object should now be in default pose
go.SetActive(false); //disabled in default pose

整理一下:

    public static void ResetState(this Animator self) {
        self.CrossFade("Init", 0);

        // update 2 or 3 times
        self.Update(0);
        self.Update(0);
        //  self.Update(0);
        self.gameObject.SetActive(false);
    }

这里的Init是一个特殊的State,满足下面的条件:

  1. Motion = null
  2. WriteDefaults = true

我测试发现执行一次Update(0)状态不能完成重置,故而这里选了2次,或者3次


参考

AnimatorStates中的write defaults详解

Write Defaults Confusion / Bug