将animator改为animation

本文介绍了一种在Unity中将Animator组件转换为Animation组件的方法,并提供了详细的代码实现。该方法包括生成新的AnimationClip并设置legacy属性,以及在场景中替换对应的Prefab。

最近由于项目需要,要将以前实现ui动画的animator全部改为animation组件。

思路:(1)获取目标路径内的所有object路径,在场景内生成ui预制体,查找并替换所有animator为animation,删除原prefab,由场景内的gameobject在原文件位置生成同名预制体,保存。

(2)由于animator使用的animationclip的legacy属性为false,不能再animation上使用,又由于手动在debug界面上修改此值,运行一次后会还原,故将所有animationclip使用代码复制一份并设置legacy,删除原clip并在原文件位置保存。

以下为代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;

public class Animator2Animation : MonoBehaviour {

	// Use this for initialization
	void Start () {
        Invoke("ChangeClipForAnimation", 3);
	}
	



    /// <summary>
    /// 将目录内所有的animationClip复制一份,将其legacy设置为true,保存同名clip并删除旧的animationclip
    /// </summary>
    public void ChangeClipForAnimation()
    {
        print("change Clip start !!!");
        //获取所有object的路径
        string[] allPath = Directory.GetFiles(Application.dataPath + "/animator2animation", "*", SearchOption.AllDirectories);
        //循环遍历每一个路径,单独加载
        foreach (string strobjPath in allPath)
        {
            if (strobjPath.EndsWith(".anim"))
            {
                //替换路径中的反斜杠为正斜杠       
                string strTempPath = strobjPath.Replace(@"\", "/");
                //截取我们需要的路径
                strTempPath = strTempPath.Substring(strTempPath.IndexOf("Assets"));
                //根据路径加载资源
                Object obj = AssetDatabase.LoadAssetAtPath(@strTempPath, typeof(Object));
                AnimationClip clip = obj as AnimationClip;
                AnimationClip newclip = new AnimationClip();
                newclip.name = clip.name;
                newclip.legacy = true;
                AnimationClipSettings clipSetting = AnimationUtility.GetAnimationClipSettings(clip);//获取AnimationClipSettings

                AnimationUtility.SetAnimationClipSettings(newclip, clipSetting);//设置新clip的AnimationClipSettings

                newclip.frameRate = clip.frameRate;//设置新clip的帧率

                EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);//获取clip的curveBinds

                for (int i = 0; i < curveBindings.Length; i++)
                {
                    AnimationUtility.SetEditorCurve(newclip, curveBindings[i], AnimationUtility.GetEditorCurve(clip, curveBindings[i]));//设置新clip的curve
                }

                GameObject.DestroyImmediate(clip, true);
                strTempPath = strTempPath.Substring(0, strTempPath.LastIndexOf('/'));
                AssetDatabase.CreateAsset(newclip, strTempPath + "/" + newclip.name + ".anim");
            }
        }
        print("change clip over!!!");
    }

    /// <summary>
    /// 此方法会:(1)将目录内所有的prefab在场景内生成,查找其包含的animator并修改为animation,将原prefab删除并在原位置生成新的同名prefab
    ///           (2)将目录内所有的animationClip复制一份,将其legacy设置为true,保存同名clip并删除旧的animationclip
    /// </summary>
    public void AnimatorTurnToAnimation()
    {
        print("Animator to Animation start !!!");
        //获取所有object的路径
        string[] allPath = Directory.GetFiles(Application.dataPath + "/YLResources/Prefabs/UI", "*", SearchOption.AllDirectories);
        //循环遍历每一个路径,单独加载
        foreach (string strobjPath in allPath)
        {
            if (strobjPath.EndsWith(".prefab"))
            {
                bool needsave = false;
                //替换路径中的反斜杠为正斜杠       
                string strTempPath = strobjPath.Replace(@"\", "/");
                //截取我们需要的路径
                strTempPath = strTempPath.Substring(strTempPath.IndexOf("Assets"));
                //根据路径加载资源
                Object obj = AssetDatabase.LoadAssetAtPath(@strTempPath, typeof(Object));


                GameObject prefab = obj as GameObject;
                GameObject newprefab = Instantiate(prefab) as GameObject;
                newprefab.name = prefab.name;
                Animator animator = newprefab.GetComponent<Animator>();
                if (animator != null)
                {
                    needsave = true;
                    Change(animator);
                }
                Animator[] animators = newprefab.GetComponentsInChildren<Animator>(true);
                if (animators != null && animators.Length > 0)
                {
                    needsave = true;
                    foreach (Animator item in animators)
                    {
                        Change(item);
                    }
                }
                if (needsave == true)
                {
                    GameObject.DestroyImmediate(prefab, true);
                    strTempPath = strTempPath.Substring(0, strTempPath.LastIndexOf('/'));
                    //AssetDatabase.CreateAsset(newprefab, strTempPath + "/" + newprefab.name + ".prefab");
                    PrefabUtility.CreatePrefab(strTempPath + "/" + newprefab.name + ".prefab", newprefab);
                    LoggerHelper.Debug(strTempPath + "/" + newprefab.name + ".prefab");
                }
                GameObject.DestroyImmediate(newprefab);
            }
        }


        foreach (string strobjPath in allPath)
        {
            if (strobjPath.EndsWith(".anim"))
            {
                //替换路径中的反斜杠为正斜杠       
                string strTempPath = strobjPath.Replace(@"\", "/");
                //截取我们需要的路径
                strTempPath = strTempPath.Substring(strTempPath.IndexOf("Assets"));
                //根据路径加载资源
                Object obj = AssetDatabase.LoadAssetAtPath(@strTempPath, typeof(Object));
                AnimationClip clip = obj as AnimationClip;
                //if (clip.legacy == false)
                //{
                    AnimationClip newclip = new AnimationClip();
                    newclip.name = clip.name;
                    newclip.legacy = true;
                    AnimationClipSettings clipSetting = AnimationUtility.GetAnimationClipSettings(clip);//获取AnimationClipSettings

                    AnimationUtility.SetAnimationClipSettings(newclip, clipSetting);//设置新clip的AnimationClipSettings

                    newclip.frameRate = clip.frameRate;//设置新clip的帧率

                    EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);//获取clip的curveBinds

                    for (int i = 0; i < curveBindings.Length; i++)
                    {
                        AnimationUtility.SetEditorCurve(newclip, curveBindings[i], AnimationUtility.GetEditorCurve(clip, curveBindings[i]));//设置新clip的curve
                    }

                    GameObject.DestroyImmediate(clip, true);
                    strTempPath = strTempPath.Substring(0, strTempPath.LastIndexOf('/'));
                    AssetDatabase.CreateAsset(newclip, strTempPath + "/" + newclip.name + ".anim");
                //}
            }
        }

        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        print("Animator to Animation end!");
    }

    public static void Change(Animator animator)
    {
        RuntimeAnimatorController ac = animator.runtimeAnimatorController;
        if (ac != null)
        {
            AnimationClip[] tAnimationClips = ac.animationClips;
            if (tAnimationClips != null && tAnimationClips.Length > 0)
            {
                Animation animation = animator.gameObject.GetComponent<Animation>(true);
                foreach (AnimationClip clip in tAnimationClips)
                {
                    //不改成true无法添加到animation组件上,但是改动了以后运行一次又会还原,所以只能代码创建新的同名clip,把数据复制进去同时将此值设为true,再将原clip删除就可以了
                    clip.legacy = true;
                    animation.AddClip(clip, clip.name);
                }
                GameObject.DestroyImmediate(animator, true);
            }
        }
    }
}

 

<think>好的,我现在需要在Unity中通过代码将AnimationClip添加到Animator中。首先,我需要理解Animator组件和AnimationClip之间的关系。Animator使用Animator Controller来管理多个动画状态和过渡,而AnimationClip是具体的动画数据。 根据用户提供的引用,特别是引用[3]提到了使用Animator创建动画的基础知识,可能涉及状态机的配置。但用户的问题是通过脚本动态添加AnimationClip,这可能与传统的在编辑器内配置不同。我需要查证Unity是否支持在运行时动态添加AnimationClip到Animator Controller。 通常,Animator Controller是在编辑器中预先配置好的,包含状态机和动画剪辑。如果要在运行时动态添加,可能需要通过修改Animator Controller的运行时版本,或者使用AnimatorOverrideController来替换现有的动画剪辑。例如,AnimatorOverrideController允许替换控制器中的动画剪辑,而无需修改原始控制器资源。 接下来,我需要编写脚本示例。首先获取Animator组件,然后创建或获取现有的AnimatorOverrideController,替换其中的某个动画状态对应的AnimationClip,最后将修改后的控制器赋值给Animator。需要注意的是,直接修改原始的RuntimeAnimatorController可能会导致不可预料的结果,因此应该使用AnimatorOverrideController来避免修改原始资源。 此外,引用[1]中的代码示例使用了Animation组件而不是Animator,这可能是一个混淆点。用户需要明确区分旧的Animation系统和新的Animator系统。用户的问题是关于Animator的,因此应使用Animator相关API。 最后,需要验证代码的正确性,并确保在Unity中正确应用组件和脚本。同时,要提醒用户注意使用AnimatorOverrideController的注意事项,比如需要有一个基础的Animator Controller作为模板,然后在运行时进行覆盖。</think>在Unity中通过代码为Animator添加AnimationClip需要使用AnimatorOverrideController实现动态替换动画资源,以下是具体实现步骤: ### 一、核心实现原理 1. Unity的Animator系统基于状态机设计,默认需要在编辑器中配置Animator Controller[^3] 2. 运行时动态替换动画需使用AnimatorOverrideController类 3. 该控制器通过覆盖原始控制器的动画剪辑实现动态更新 ### 二、具体实现代码 ```csharp using UnityEngine; public class AnimationLoader : MonoBehaviour { public Animator animator; public AnimationClip newClip; void Start() { // 获取原始控制器 RuntimeAnimatorController originalController = animator.runtimeAnimatorController; // 创建覆盖控制器 AnimatorOverrideController overrideController = new AnimatorOverrideController(); overrideController.runtimeAnimatorController = originalController; // 替换第一个动画状态的剪辑(根据实际需求调整) overrideController["OriginalClipName"] = newClip; // 应用新控制器 animator.runtimeAnimatorController = overrideController; } } ``` ### 三、操作步骤 1. 创建Animator Controller并配置状态机 2. 将脚本挂载到带有Animator组件的GameObject 3. 在Inspector面板拖拽引用: - 目标Animator组件 - 需要添加的AnimationClip 4. 确保原始控制器中存在名为"OriginalClipName"的动画状态 ### 四、注意事项 1. 原始Animator Controller必须包含至少一个动画状态[^3] 2. 覆盖控制器不会修改原始.asset文件 3. 可通过遍历overrideController.clips获取所有可替换剪辑 4. 支持批量替换: ```csharp AnimatorOverrideController.GetOverrides(list); foreach(var clip in list) { clip.overrideClip = newClip; } overrideController.ApplyOverrides(list); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值