一般咱們在遊戲裏面建立的精靈好比玩家主角,它在移動的過程當中通常會帶有一些動畫的效果,好比兩隻腳先後地移動,那麼這種動畫效果的實現和控制就能夠經過Unity2D的動畫系統來實現。html
要添加這樣的動畫,首先咱們須要先在Hierarchy視圖裏面選中精靈,而後在Animation視圖裏面建立一個動畫文件【Create New Clip】,以下圖所示:程序員
建立好動畫的文件以後,就能夠把精靈的各個狀態拉到時間軸上,而後拖動紅色的線條就能夠看到動畫的預覽效果。c#
對於一個精靈能夠建立多個動畫,各個動畫之間能夠進行切換,下面咱們再看一下動畫以前的切換和精靈動畫的管理。windows
建立了動畫以後,在動畫文件的文件夾裏面會發現多了一個後綴爲controller的文件,這個就是動畫控制器的文件,是跟精靈搭配起來的,名字也是跟精靈的名字一致,表示是對精靈動畫的控制。如圖所示:ide
點擊Palyer.controller文件,能夠在Unity裏面看到其可視化的界面如圖所示:oop
在上圖中咱們能夠看到左下角有一個添加參數的功能,這個功能通常會用來控制動畫以前的切換,或者動畫的終止等。動畫以前是能夠互相關聯的,在可視化的控制器裏面右鍵動畫,就能夠添加其下一個關聯的動畫,如上圖中的兩個動畫是互相關聯的。點擊動畫之間的「箭頭」,而後再Inspector視圖裏面就能夠查看或者設置動畫以前的切換條件,以下圖所示,經過Warking參數來控制動畫以前的切換:post
這時候在精靈的Inspector視圖裏面,已經自動給精靈添加了動畫控制器的組件了,如圖所示。測試
接下來咱們就能夠在精靈對應的腳本里面來獲取動畫控制器Animator來進行相關的操做。動畫
private Animator playerAnimator = null;// 動畫控制器
void Start() { playerAnimator = GetComponent<Animator>(); } ...... playerAnimator.SetBool("Walking", false); ...... playerAnimator.SetBool("Walking", true);
咱們能夠在腳本里面設置動畫控制器參數的值,經過這個參數來控制動畫以前的切換。ui
http://www.xuanyusong.com/archives/3243
Unity2D的製做流程
一、拿到美術給的幀動畫
二、打開Animation windows 手動建立動畫文件
三、建立AnimationController 手動連線
四、建立Prefab文件。
這也太麻煩了。全都手動來美術每次給你好幾十個動畫資源那豈不是要累死程序員了。因此咱們不能手動,必須自動。
以下圖所示,先看看我生成出來的結果。
咱們的目標是Raw文件夾下放全部美術提供的幀動畫,每一個文件夾就是一組幀動畫,文件夾名子就是動畫的名子,代碼以下所示。
using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
public class BuildAnimation : Editor
{
//生成出的Prefab的路徑
private static string PrefabPath = "Assets/Resources/Prefabs";
//生成出的AnimationController的路徑
private static string AnimationControllerPath = "Assets/AnimationController";
//生成出的Animation的路徑
private static string AnimationPath = "Assets/Animation";
//美術給的原始圖片路徑
private static string ImagePath = Application.dataPath +"/Raw";
[MenuItem("Build/BuildAnimaiton")]
static void BuildAniamtion()
{
DirectoryInfo raw = new DirectoryInfo (ImagePath);
foreach (DirectoryInfo dictorys in raw.GetDirectories())
{
List<AnimationClip> clips = new List<AnimationClip>();
foreach (DirectoryInfo dictoryAnimations in dictorys.GetDirectories())
{
//每一個文件夾就是一組幀動畫,這裏把每一個文件夾下的全部圖片生成出一個動畫文件
clips.Add(BuildAnimationClip(dictoryAnimations));
}
//把全部的動畫文件生成在一個AnimationController裏
AnimatorController controller = BuildAnimationController(clips,dictorys.Name);
//最後生成程序用的Prefab文件
BuildPrefab(dictorys,controller);
}
}
static AnimationClip BuildAnimationClip(DirectoryInfo dictorys)
{
string animationName = dictorys.Name;
//查找全部圖片,由於我找的測試動畫是.jpg
FileInfo []p_w_picpaths = dictorys.GetFiles("*.jpg");
AnimationClip clip = new AnimationClip();
AnimationUtility.SetAnimationType(clip,ModelImporterAnimationType.Generic);
EditorCurveBinding curveBinding = new EditorCurveBinding();
curveBinding.type = typeof(SpriteRenderer);
curveBinding.path="";
curveBinding.propertyName = "m_Sprite";
ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[p_w_picpaths.Length];
//動畫長度是按秒爲單位,1/10就表示1秒切10張圖片,根據項目的狀況能夠本身調節
float frameTime = 1/10f;
for(int i =0; i< p_w_picpaths.Length; i++){
Sprite sprite = Resources.LoadAssetAtPath<Sprite>(DataPathToAssetPath(p_w_picpaths[i].FullName));
keyFrames[i] = new ObjectReferenceKeyframe ();
keyFrames[i].time = frameTime *i;
keyFrames[i].value = sprite;
}
//動畫幀率,30比較合適
clip.frameRate = 30;
//有些動畫我但願天生它就動畫循環
if(animationName.IndexOf("idle") >=0 )
{
//設置idle文件爲循環動畫
SerializedObject serializedClip = new SerializedObject(clip);
AnimationClipSettings clipSettings = new AnimationClipSettings(serializedClip.FindProperty("m_AnimationClipSettings"));
clipSettings.loopTime = true;
serializedClip.ApplyModifiedProperties();
}
string parentName = System.IO.Directory.GetParent(dictorys.FullName).Name;
System.IO.Directory.CreateDirectory(AnimationPath +"/"+parentName);
AnimationUtility.SetObjectReferenceCurve(clip,curveBinding,keyFrames);
AssetDatabase.CreateAsset(clip,AnimationPath +"/"+parentName +"/" +animationName+".anim");
AssetDatabase.SaveAssets();
return clip;
}
static AnimatorController BuildAnimationController(List<AnimationClip> clips ,string name)
{
AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath(AnimationControllerPath +"/"+name+".controller");
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;
}
static void BuildPrefab(DirectoryInfo dictorys,AnimatorController animatorCountorller)
{
//生成Prefab 添加一張預覽用的Sprite
FileInfo p_w_picpaths = dictorys.GetDirectories()[0].GetFiles("*.jpg")[0];
GameObject go = new GameObject();
go.name = dictorys.Name;
SpriteRenderer spriteRender =go.AddComponent<SpriteRenderer>();
spriteRender.sprite = Resources.LoadAssetAtPath<Sprite>(DataPathToAssetPath(p_w_picpaths.FullName));
Animator animator = go.AddComponent<Animator>();
animator.runtimeAnimatorController = animatorCountorller;
PrefabUtility.CreatePrefab(PrefabPath+"/"+go.name+".prefab",go);
DestroyImmediate(go);
}
public static string DataPathToAssetPath(string path)
{
if (Application.platform == RuntimePlatform.WindowsEditor)
return path.Substring(path.IndexOf("Assets\\"));
else
return path.Substring(path.IndexOf("Assets/"));
}
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; } }
}
}
由於新版的動畫系統Unity沒有提供直接的API來設置動畫的循環狀態,因此咱們只能經過寫文件的形式來修改動畫的天生屬性。須要用到本身寫封裝的類 AnimationClipSettings 具體方法請看上面的代碼。
有了自動生成動畫的代碼,就不怕美術一次給你多少組圖片,或者更新了多少組圖片都能很快的生成出來。
隨便寫一條測試腳本,來測試一下播放動畫。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
usingUnityEngine; using System.Collections;
public classNewBehaviourScript:MonoBehaviour{
Animator animator; voidStart() { animator=GetComponent<Animator>(); }
voidOnGUI() { if(GUILayout.Button("idle")) { animator.Play("idle");
} } } |
動畫播放的很正常的。