AnimatorOverrideController

作者:追风剑情 发布于:2018-11-22 21:49 分类:Unity3d

示例: 一个兼容新旧动画系统的适配器类

如果动画剪辑是用Unity5.0之前版本创建的,需要去掉Legacy勾选项,如果需要循环播放就勾上Loop Time

Legacy设为true,则新动画系统无法替换动画剪辑

11111.png

动画控制器示例

Animator窗口

222.png

让非loop动画播放完后指向一个空状态,否则播放完后无法通过播放API继续播放此剪辑

Project窗口

3333.png

可以点击这个+号添加更多剪辑

4444.png

示例代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 适配不同版本动画系统
/// 注意: 新版动画系统无法向控制器中新增剪辑,只能替换剪辑
/// </summary>
public class AnimateAdapter
{
    //是否为旧动画系统
    private bool legacy = true;
    //旧动画系统组件
    private Animation animation = null;
    //新动画系统组件
    private Animator animator = null;
    //当前animator的控制器(使用GetAnimatorOverrideController()代替直接访问)
    private AnimatorOverrideController _animatorOverrideController = null;

    private AnimatorOverrideController GetAnimatorOverrideController() {
        if (this.animator == null)
            return null;
        if (this.animator.runtimeAnimatorController is AnimatorOverrideController) {
            _animatorOverrideController = this.animator.runtimeAnimatorController as AnimatorOverrideController;
        }else{
            if (_animatorOverrideController == null)
                _animatorOverrideController = new AnimatorOverrideController();
            _animatorOverrideController.runtimeAnimatorController = this.animator.runtimeAnimatorController;
        }
        return _animatorOverrideController;
    }

    public void AttachRoot(GameObject go)
    {
        if (go == null)
            return;
        animator = go.GetComponent<Animator>();
        if (animator != null) {
            animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
        }else{
            animation = go.GetComponent<Animation>();
            if (animation != null) {
                animation.playAutomatically = true;
                animation.cullingType = AnimationCullingType.AlwaysAnimate;
            }
        }
        legacy = (animation != null);
    }

    //暂停播放
    public bool enabled {
        get {
            bool b = false;
            if (legacy) {
                if (this.animation != null)
                    b = this.animation.enabled;
            }else{
                if (this.animator != null)
                    b = this.animator.enabled;
            }
            return false;
        }
        set {
            if (legacy) {
                if (this.animation != null) {
                    this.animation.enabled = value;
                }
            }else{
                if (this.animator != null) {
                    //enabled=false相当于暂停
                    this.animator.enabled = value;
                }
            }
        }
    }

    //停止播放
    public void Stop()
    {
        if (legacy) {
            if (this.animation != null)
                this.animation.Stop();
        }else{
            if (this.animator != null)
                this.animator.enabled = false;
        }
    }

    //判断是否存在某个剪辑动画
    public bool HasClip(string name)
    {
        bool b = false;
        if (legacy) {
            b = (this.animation != null && this.animation[name] != null);
        }else{
            AnimatorOverrideController ctrl = GetAnimatorOverrideController();
            if (ctrl != null) {
                b = ctrl[name] != null;
            }
        }
        return b;
    }

    //获取剪辑
    public AnimationClip GetClip(string name)
    {
        AnimationClip clip = null;
        if (legacy) {
            if (this.animation != null)
                clip = this.animation.GetClip(name);
        }else{
            AnimatorOverrideController ctrl = GetAnimatorOverrideController();
            if (ctrl != null) {
                clip = ctrl[name];
            }
        }
        return clip;
    }

    //是否正在播放
    public bool IsPlaying(string name)
    {
        bool b = false;
        if (legacy) {
            if (this.animation != null) {
                b = this.animation.IsPlaying(name);
            }
        }else{
            if (this.animator == null) {
                return b;
            }
            if (!this.animator.enabled) {
                return b;
            }
            AnimatorStateInfo state = this.animator.GetCurrentAnimatorStateInfo(0);//0: Base Layer
            if (!state.IsName(name)) {
                return b;
            }
            AnimationClip clip = GetClip(name);
            if (clip == null) {
                return b;
            }
            if (clip.isLooping) {
                b = true;
            }else{
                //判断已播放时长是否小于剪辑的总时长
                b = state.normalizedTime <= state.length;
            }
        }
        return b;
    }

    //覆盖原来的动画控制器
    public void SetOverrideController(AnimatorOverrideController overrideController) 
    {
        if (legacy || this.animator == null)
            return;
        
        //注意: 这里分情况处理
        AnimatorOverrideController ctrl = this.animator.runtimeAnimatorController as AnimatorOverrideController;
        if (ctrl != null) {
            ctrl.runtimeAnimatorController = null;
            ctrl.runtimeAnimatorController = overrideController.runtimeAnimatorController;
        }else{
            this.animator.runtimeAnimatorController = null;
            this.animator.runtimeAnimatorController = overrideController;
        }

        Resources.UnloadUnusedAssets();
    }

    //替换动画剪辑
    public void ReplaceAnimationClip(List<KeyValuePair<string, AnimationClip>> list)
    {
        if (list == null || list.Count == 0)
            return;

        KeyValuePair<string, AnimationClip> kv;
        if (legacy) {
            if (this.animation == null)
                return;
            for(int i=0; i<list.Count; i++) {
                kv = list[i];
                if (string.IsNullOrEmpty(kv.Key) || kv.Value == null)
                    continue;
                this.animation.AddClip(kv.Value, kv.Key);
            }
        }else{
            AnimatorOverrideController overrideController = new AnimatorOverrideController();
            for(int i=0; i<list.Count; i++) {
                kv = list[i];
                if (string.IsNullOrEmpty(kv.Key) || kv.Value == null)
                    continue;
                //不支持传统动画剪辑,需要美术去掉勾选项.
                if (kv.Value.legacy) {
                    Debug.LogWarningFormat("detected legacy clip({0})", kv.Value.name);
                    kv.Value.legacy = false;
                }
                overrideController[kv.Key] = kv.Value;
            }
            SetOverrideController(overrideController);
        }
    }

    //播放动画
    public AnimationState PlayAni(string aniname, int layer = 0, WrapMode wrapMode = WrapMode.Once, float fadeIn = 0F, float speed = 1F)
    {
        AnimationState state = null;
        if (legacy) {
            if (this.animation == null)
                return state;
            state = this.animation[aniname];
            if (state != null) {
                state.wrapMode = wrapMode;
                state.speed = speed;
                state.layer = layer;
                this.animation.CrossFade(aniname, fadeIn, PlayMode.StopAll);
            }
            return state;
        }else{
            if (this.animator == null)
                return state;
            if (!this.animator.enabled)
                this.animator.enabled = true;
            AnimationClip clip = GetClip(aniname);
            if (clip != null) {
                clip.wrapMode = wrapMode;
            }
            this.animator.speed = speed;
            this.animator.CrossFade(aniname, fadeIn, layer);
        }
        return state;
    }

    //播放动画
    public void CrossFadeQueued(string aniname, WrapMode wrapMode, float fadeIn = 0F, float speed = 1f)
    {
        if (legacy) {
            if (this.animation && this.animation[aniname]) {
                this.animation[aniname].wrapMode = wrapMode;
                this.animation[aniname].speed = speed;
                this.animation.CrossFadeQueued(aniname, fadeIn);
            }
        }else{
            //没CrossFadeQueued这类接口,直接以CrossFade()方式播放
            PlayAni(aniname, 0, wrapMode, fadeIn, speed);
        }
    }

    //是否存在动画组件
    public bool HasAniComponent()
    {
        return (this.animation != null) || (this.animator != null);
    }

    public Animation GetAnimation()
    {
        return this.animation;
    }

    public Animator GetAnimator()
    {
        return this.animator;
    }

    public void Dispose()
    {
        animator = null;
        animation = null;

        if (_animatorOverrideController != null) {
            if (_animatorOverrideController.runtimeAnimatorController != null) {
                _animatorOverrideController.runtimeAnimatorController = null;
            }
            _animatorOverrideController = null;
        }
        Resources.UnloadUnusedAssets();
    }
}

标签: Unity3d

Powered by emlog  蜀ICP备18021003号   sitemap

川公网安备 51019002001593号