Split Animation Clip From FBX and Multiply Mode Sprite
2015-06-02 14:45
375 查看
Use Script To Creat 2D Animation Clip From Multiply Mode Sprite
很多时候美工拿过来的一张序列帧图片,我们需要转换成 Multiply Mode,切片生成动画,然后绑定Prefab,可以考虑些一个脚本省略重复劳动。直接上代码结果:
Main Procede
using UnityEngine; using UnityEditor; using UnityEditorInternal; ///AnimatorController public static string Altas_FrameConfigAssetPath = "Assets/test_frameConfig.txt"; [MenuItem("MyTest/Test")] public static void Test() { ///Get sprites Sprite[] sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(Altas_AssetPath).Select(x => x as Sprite).ToArray(); ///Get frame config ///run:0-11 ///idle:12-21 ///charge:22-33 ///attack:34-49 ///dead:50-63 TextAsset textAsset = AssetDatabase.LoadAssetAtPath(Altas_FrameConfigAssetPath, typeof(TextAsset)) as TextAsset; string[] configs = textAsset.text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); ///Create clips List<AnimationClip> clips = new List<AnimationClip>(); foreach (string curConfig in configs) { /// run:0-11 string clipName = curConfig.Split(":"[0])[0]; string length = curConfig.Split(":"[0])[1]; /// 0-11 int startIndex = int.Parse(length.Split("-"[0])[0]); int endIndex = int.Parse(length.Split("-"[0])[1]); Sprite[] curSprites = sprites.Where((t, index) => index >= startIndex && index <= endIndex).ToArray(); AnimationClip curClip = BuildAnimationClip(curSprites, "Assets/" + clipName + ".anim", true); clips.Add(curClip); } ///Create AnimatorController with clips AnimatorController curAnimatorController = BuildAnimationController(clips, "Assets/test.controller"); ///Create Prefab add AnimatorController BuildPrefab(curAnimatorController, "Assets/test.prefab"); }
BuildAnimationClip
static AnimationClip BuildAnimationClip(Sprite[] Sprites, string AssetPath, bool IsNeedLoop) { AnimationClip clip = new AnimationClip(); /// Setting it as generic allows you to use the animation clip in the animation controller /// public enum ModelImporterAnimationType /// { /// None = 0, /// Legacy = 1, /// Generic = 2, /// Human = 3, ///} AnimationUtility.SetAnimationType(clip, ModelImporterAnimationType.Generic); /// First you need to create e Editor Curve Binding EditorCurveBinding curveBinding = new EditorCurveBinding(); /// I want to change the sprites of the sprite renderer, so I put the typeof(SpriteRenderer) as the binding type. curveBinding.type = typeof(SpriteRenderer); /// Regular path to the gameobject that will be changed (empty string means root) curveBinding.path = ""; curveBinding.propertyName = "m_Sprite"; /// An array to hold the object keyframes ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[Sprites.Length]; ///动画长度是按秒为单位,1/10就表示1秒切10张图片,根据项目的情况可以自己调节 float frameTime = 1 / 10f; for (int i = 0; i < Sprites.Length; i++) { keyFrames[i] = new ObjectReferenceKeyframe(); keyFrames[i].time = frameTime * i; keyFrames[i].value = Sprites[i]; } ///动画帧率,30比较合适 ///也就是说1秒 切成 30份,然后 每3份 切换一次图片 ///如果动态修改clip.frameRate = 15 ///就是说1秒 切成 15份,然后 每3份 切换一次图片, 但是每一份的时间加倍了 clip.frameRate = 30; //set AnimationClip loop //clip.wrapMode = WrapMode.Loop; //no use //UnityEditor.AnimationClipSettings clipSettings = AnimationUtility.GetAnimationClipSettings(clip); //no use //clipSettings.loopTime = true; if (IsNeedLoop) //use { SerializedObject serializedClip = new SerializedObject(clip); AnimationClipSettings clipSettings = new AnimationClipSettings(serializedClip.FindProperty("m_AnimationClipSettings")); clipSettings.loopTime = true; serializedClip.ApplyModifiedProperties(); } AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyFrames); ///Create animation AssetDatabase.CreateAsset(clip, AssetPath); AssetDatabase.SaveAssets(); return clip; }
BuildAnimationController
static AnimatorController BuildAnimationController(List<AnimationClip> clips, string AssetPath) { AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath(AssetPath); AnimatorControllerLayer layer = animatorController.GetLayer(0); UnityEditorInternal.StateMachine sm = layer.stateMachine; foreach (AnimationClip newClip in clips) { State state = sm.AddState(newClip.name); state.SetAnimationClip(newClip, layer); //Transition trans = sm.AddAnyStateTransition(state); //trans.RemoveCondition(0); } AssetDatabase.SaveAssets(); return animatorController; }
BuildPrefab
static void BuildPrefab(AnimatorController animatorCountorller, string AssetPath) { GameObject go = new GameObject(); go.name = "test"; SpriteRenderer spriteRender = go.AddComponent<SpriteRenderer>(); Animator animator = go.AddComponent<Animator>(); animator.runtimeAnimatorController = animatorCountorller; PrefabUtility.CreatePrefab(AssetPath, go); }
AnimationClipSettings.cs
public class AnimationClipSettings { SerializedProperty m_Property; private SerializedProperty Get (string property) { return m_Property.FindPropertyRelative(property); } public AnimationClipSettings(SerializedProperty prop) { m_Property = prop; } public float startTime { get { return Get("m_StartTime").floatValue; } set { Get("m_StartTime").floatValue = value; } } public float stopTime { get { return Get("m_StopTime").floatValue; } set { Get("m_StopTime").floatValue = value; } } public float orientationOffsetY { get { return Get("m_OrientationOffsetY").floatValue; } set { Get("m_OrientationOffsetY").floatValue = value; } } public float level { get { return Get("m_Level").floatValue; } set { Get("m_Level").floatValue = value; } } public float cycleOffset { get { return Get("m_CycleOffset").floatValue; } set { Get("m_CycleOffset").floatValue = value; } } public bool loopTime { get { return Get("m_LoopTime").boolValue; } set { Get("m_LoopTime").boolValue = value; } } public bool loopBlend { get { return Get("m_LoopBlend").boolValue; } set { Get("m_LoopBlend").boolValue = value; } } public bool loopBlendOrientation { get { return Get("m_LoopBlendOrientation").boolValue; } set { Get("m_LoopBlendOrientation").boolValue = value; } } public bool loopBlendPositionY { get { return Get("m_LoopBlendPositionY").boolValue; } set { Get("m_LoopBlendPositionY").boolValue = value; } } public bool loopBlendPositionXZ { get { return Get("m_LoopBlendPositionXZ").boolValue; } set { Get("m_LoopBlendPositionXZ").boolValue = value; } } public bool keepOriginalOrientation { get { return Get("m_KeepOriginalOrientation").boolValue; } set { Get("m_KeepOriginalOrientation").boolValue = value; } } public bool keepOriginalPositionY { get { return Get("m_KeepOriginalPositionY").boolValue; } set { Get("m_KeepOriginalPositionY").boolValue = value; } } public bool keepOriginalPositionXZ { get { return Get("m_KeepOriginalPositionXZ").boolValue; } set { Get("m_KeepOriginalPositionXZ").boolValue = value; } } public bool heightFromFeet { get { return Get("m_HeightFromFeet").boolValue; } set { Get("m_HeightFromFeet").boolValue = value; } } public bool mirror { get { return Get("m_Mirror").boolValue; } set { Get("m_Mirror").boolValue = value; } } }
参考:
Unity3D研究院之Machine动画脚本自动生成AnimatorController(七十一)
Unity2D研究院之自动生成动画、AnimationController、Prefab(一)
lack-of-scripting-functionality-for-creating-2d-animation-clips-by-code
accessing-loop-time-through-c
can-mecanim-animation-clip-properties-be-edited-in-script
Use Script To Split ModelImporterClipAnimation From FBX
同理,有些美工导出的FBX只有一个动画,但是带有帧数说明,需要我们写个脚本自动切结果:
public class mTest2 : AssetPostprocessor { public static string FBX_FrameConfigAssetPath = "Assets/test2/test2_frameConfig.txt"; //Add this function in a subclass to get a notification when a model has completed importing. public void OnPostprocessModel(GameObject go) { Debug.Log(assetPath); ///Get frame config ///run:0-20 ///idle:21-31 ///charge:32-42 ///attack:43-58 ///dead:59-75 TextAsset textAsset = AssetDatabase.LoadAssetAtPath(FBX_FrameConfigAssetPath, typeof(TextAsset)) as TextAsset; string[] configs = textAsset.text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); ///Model importer lets you modify model import settings from editor scripts. ModelImporter modelImporter = assetImporter as ModelImporter; List<ModelImporterClipAnimation> clips = new List<ModelImporterClipAnimation>(); foreach (string curConfig in configs) { clips.Add(ParseAnimationClip(curConfig)); } modelImporter.clipAnimations = clips.ToArray(); ///Import any changed assets. ///call OnPostprocessModel twice cause call once nerver show split anim clips on FBX in project view AssetDatabase.Refresh(); } static ModelImporterClipAnimation ParseAnimationClip(string curConfig) { ///run:0-20 string clipName = curConfig.Split(":"[0])[0]; string length = curConfig.Split(":"[0])[1]; /// 0-20 int startIndex = int.Parse(length.Split("-"[0])[0]); int endIndex = int.Parse(length.Split("-"[0])[1]); ModelImporterClipAnimation clip = new ModelImporterClipAnimation(); clip.firstFrame = Convert.ToSingle(startIndex); clip.lastFrame = Convert.ToSingle(endIndex); clip.loopTime = true; clip.name = clipName; return clip; } }
参考:
how-to-split-animations-via-script-in-editor
项目工程源码
Split Animation Tool
相关文章推荐
- 上传文件
- Linux Shell脚本系列教程(一):Shell入门
- 网络拓扑简析
- ExtJS结合WCF/Jquery结合WCF 分别开发的非常优秀的网页聊天工具,持续更新
- 隐藏浏览器中php,apache,varnish,nginx版本信息
- Unity区分平台编译
- 为什么在重写equals方法时都要重写equals方法呢:
- 常用的C++库总结
- 从fragment跳转到activity , 返回到指定fragment页面
- 关于Class.forName(className).newInstance()介绍
- SPRING 整合IBATIS或者hibernate等持久数据层流程与实现
- QTcreator的一些设置
- HDU 2377 Bus Pass 最短路
- Objective-C编码规范
- Http协议简介
- [iOS]图片压缩&保存View为内容Img
- struts2漏洞修复
- jQuery学习笔记1--表格展开关系
- 《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联
- 一款已上市MMO手游地图同步方案总结