using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Text.RegularExpressions;
using System.IO;
using UnityEngine.UI;
using UnityEditor.Animations;
public class SpriteAnimationCreator : MonoBehaviour
{
//默认帧间隔
private static float defaultInterval = 0.1f;
[MenuItem("MyTest/Create/SpriteAnimation")]
public static void Create()
{
//获取project面板中选中的sprite
List<Sprite> selectedSprites = new List<Sprite>(Selection.GetFiltered(typeof(Sprite), SelectionMode.DeepAssets).OfType<Sprite>());
//如果选中了纹理则获取精灵
Object[] selectedTextures = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);
foreach(Object texture in selectedTextures)
{
selectedSprites.AddRange(AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(texture)).OfType<Sprite>());
}
if(selectedSprites.Count < 1)
{
Debug.LogWarning("no sprite selected...");
return;
}
//按照精灵末尾的连续编号进行排序
string suffixPattern = "_?([0-9]+)$";
selectedSprites.Sort((Sprite ls, Sprite rs)=>
{
Match lsMatch = Regex.Match(ls.name, suffixPattern);
Match rsMatch = Regex.Match(rs.name, suffixPattern);
if (lsMatch.Success && rsMatch.Success)
{
return (int.Parse(lsMatch.Groups[1].Value) - int.Parse(rsMatch.Groups[1].Value));
}
else
{
return ls.name.CompareTo(rs.name);
}
});
//后续将资源保存在第一个精灵所在文件夹
string baseDir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(selectedSprites[0]));
//将第一个精灵的不含连续编号的名称设置为动画的名称
string baseName = Regex.Replace(selectedSprites[0].name, suffixPattern, "");
if (string.IsNullOrEmpty(baseName))
{
baseName = selectedSprites[0].name;
}
//没有画布的话创建一个画布
Canvas canvas = FindObjectOfType<Canvas>();
if (canvas == null)
{
GameObject canvasObj = new GameObject("CanvasSpriteAnimation");
canvas = canvasObj.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvasObj.AddComponent<CanvasScaler>();
canvasObj.AddComponent<GraphicRaycaster>();
canvasObj.layer = LayerMask.NameToLayer("UI");
}
//创建图像
GameObject obj = new GameObject(baseName);
obj.transform.parent = canvas.transform;
obj.transform.localPosition = Vector3.zero;
Image image = obj.AddComponent<Image>();
image.sprite = selectedSprites[0];
image.SetNativeSize();
//添加animator
Animator animator = obj.AddComponent<Animator>();
//创建动画剪辑
AnimationClip animationClip = AnimatorController.AllocateAnimatorClip(baseName);
//使用EditorCurveBinding将关键帧和图像的Sprite属性进行关联
EditorCurveBinding editorCurveBinding = new EditorCurveBinding();
editorCurveBinding.type = typeof(Image);
editorCurveBinding.path = "";
editorCurveBinding.propertyName = "m_Sprite";
//创建关键帧,数量为所选中的精灵数量,为各关键帧分配精灵
ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[selectedSprites.Count];
for (int i = 0; i < selectedSprites.Count; i++)
{
keyFrames[i] = new ObjectReferenceKeyframe();
keyFrames[i].time = i * defaultInterval;
keyFrames[i].value = selectedSprites[i];
}
AnimationUtility.SetObjectReferenceCurve(animationClip, editorCurveBinding, keyFrames);
//由于Loop Time属性无法直接从脚本中进行设置 因此使用SerializedProperty进行设置
SerializedObject serializedAnimationClip = new SerializedObject(animationClip);
SerializedProperty serializedAnimationClipSettings = serializedAnimationClip.FindProperty("m_AnimationClipSettings");
serializedAnimationClipSettings.FindPropertyRelative("m_LoopTime").boolValue = true;
serializedAnimationClip.ApplyModifiedProperties();
//将创建的动画剪辑作为资源保存
SaveAsset(animationClip, baseDir + "/" + baseName + ".anim");
//创建动画控制器
AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPathWithClip(baseDir + "/" + baseName + ".controller", animationClip);
animator.runtimeAnimatorController = animatorController;
}
private static void SaveAsset(Object obj, string path)
{
Object existingAsset = AssetDatabase.LoadMainAssetAtPath(path);
if (existingAsset != null)
{
EditorUtility.CopySerialized(obj, existingAsset);
AssetDatabase.SaveAssets();
}
else
{
AssetDatabase.CreateAsset(obj, path);
}
}
}
//移植《Unity UI 设计与开发从入门到精通》书本上代码运行思考并记录
//unity 2018已验证可行
网友评论