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

Split Animation Clip From FBX and Multiply Mode Sprite的更多相关文章

  1. Unity中有两种Animation Clip

    http://blog.csdn.net/zzxiang1985/article/details/51291861 在Unity中,我们有两种方法创建Animation Clip. 一种(后面简称方法 ...

  2. Unity3D中通过Animator动画状态机获取任意animation clip的准确播放持续时长

    Unity3d 4及之前的版本中动画的播放用的animation,可直接获取其播放持续长度.但5.x及以后的版本中都是用animator来播放动画了. https://docs.unity3d.com ...

  3. Uni2D 入门 -- Animation Clip 和 Animation API

    转载 csdn kakashi8841 http://blog.csdn.net/kakashi8841/article/details/17599505 Animation Clip 一个anima ...

  4. Unity之如何从fbx提取Animation clip文件

    见代码: static void CreateAnim(string fbx, string target) { AnimationClip src = AssetDatabase.LoadAsset ...

  5. Unity3D之Mecanim动画系统学习笔记(三):Animation View

    动画组件之间的关系 我们先看一张图: 这里我们可以看到,我们在GameObject之上绑定的Animator组件是控制模型进行动画播放的. 而其属性Controller则对应一个Animator Co ...

  6. Uni2D入门

    转载 http://blog.csdn.net/kakashi8841/article/details/17558059 开始 Uni2D增加了一些新的便利的特性给Unity,它们用于推动你2D工作流 ...

  7. Model&Animation

    [Model&Animation] 1.FBX文件是一个完整的模型,通常内含Mesh,Material,Texture,Animation,即内含构成一个完成GameObject所需要的一切组 ...

  8. 进口fbx角色动画read-only解

    原文链接:http://answers.unity3d.com/questions/8172/how-to-add-new-curves-or-animation-events-to-an-im.ht ...

  9. Unity导入FBX自动进行动画切分

    手动处理动画分割 在导入FBX模型过程中,若带有动画呢,需要对它进行切分. 当然这个工作可以在Unity中完成. 比如: 这样手动来分割进行. 自动动画切分   这就需要代码了. 把代码保存成cs文件 ...

随机推荐

  1. python 中sshpass的使用

    如何用SSH连接远程服务器有两种方式 1.利用远程软件控制:sshclient.Puttty.secureCRT等 2.终端命令 ssh -p 22 root@服务器ip  密码需要手工交互式输入(2 ...

  2. xampp 通过pear安装PHP_UML

    1.在环境变量中添加D:\xampp\php   // 如果前面已经有其他环境变量了,那么要用分号;跟前面的隔开 2.ctrl+R , cmd , pear install PHP_UML 3.如果提 ...

  3. mysql 文本搜索

    全文本搜索 MySQL支持几种基本的数据库引擎,但并非所有的引擎都支持全文本搜索.两个最常使用的引擎为MyISAM和InnoDB,前者支持全文本搜索,后者就不支持. 理解全文本搜索 在前面的学习中,我 ...

  4. 蒟蒻的9个背包的浩大工程(更新中)(无限延期)(太长了不舍删虽然写的lj的一匹)

    所以说这就是一篇写炸的废文!!!! 所以说背包直接看dd大神的就好了,算了瞎写写吧. 0/1背包 有n件物品和一个容量为C的背包.第i件物品的重量是w[i],价值是v[i].求解将哪些物品放入背包可使 ...

  5. 灯泡游戏 (Kruskal)(并查集)

    灯泡游戏 时间限制: 1 Sec  内存限制: 64 MB提交: 9  解决: 4[提交][状态][讨论版] 题目描述 有 一个n行m列的矩阵,左上角坐标是(0,0),右下角坐标是(n-1,m-1). ...

  6. ba resme

    Resume Name: Zhou Heng Gender: Male Email : jackyzhouheng@gmail.com Self Assessment: I have more tha ...

  7. 【最小割】【Dinic】bzoj3275 Number

    每个点拆点,分别向源/汇连a[i]的边,满足条件的相互连INF的边,答案为sum-maxflow*2. 因为若有几个点不能同时被选,我们要贪心地选择其中和尽量大的部分,这可以由最小割来保证. #inc ...

  8. 工作流Activiti新手入门学习路线整理

    写在前面: 最近项目中使用到了工作流,虽然此部分不是自己需要完成的,但是也涉及到了要调用写的接口.正好有时间,就了解下,以便之后能在其他项目中用到时,不至于什么都不知道什么都不了解. 这里就主要整理下 ...

  9. ProgressDialog进度条对话框

    (一) 1.效果图: 2.activity_main.xml <?xml version="1.0" encoding="utf-8"?> < ...

  10. 选择改变事件OnCheckedChange

    1.效果图:选择正确的提示选对,选择错误提示选错 2.activity_main.xml <?xml version="1.0" encoding="utf-8&q ...