【Unity3D基礎】讓物體動起來①--基於UGUI的鼠標點擊移動html
【Unity3D基礎】讓物體動起來②--UGUI鼠標點擊逐幀移動數組
時光煮雨 Unity3D讓物體動起來③—UGUI DoTween&Unity Native2D實現網絡
時光煮雨 Unity3D實現2D人物動畫① UGUI&Native2D序列幀動畫函數
時光煮雨 Unity3D實現2D人物動畫② Unity2D 動畫系統&資源效率工具
看過前篇的朋友,必定能猜到這篇的內容了,2D人物動畫,這是一個老生常談的話題,不少人都寫過或者提供過相似的代碼,本文仍是遵照着重原理,代碼次之的原則。下面是根據之前本身學習的時候學習「深藍色右手」WPF遊戲教程的「WPF/Silverlight動畫及遊戲系列教程」,先結合Unity3d技術改編的原理文字oop
動態實現2D人物角色動畫目前有兩種主流方法,下面我會分別進行介紹。
第一種方法我稱之爲圖片切換法,準備工做:首先經過3DMAX等工具3D渲染2D的方法制做出角色,而後將角色每一個動做均導出8個方向每方向若干幀的系列圖片(若是是有方向的魔法圖片,不少2D-MMORPG每每會導出16個方向的系列幀圖片以求更爲逼真),即將每一個人物每一個動做的各方向的每幀均存成一張圖片,以下圖僅以從破天一劍遊戲中提取的素材爲例:性能(特別申明:本系列教程所使用的若有註明歸屬權的圖片素材均來源於網絡,請勿用於商業用途,不然形成的一切後果均與本人無關。)學習
從上圖能夠看到,我將人物向右方跑步共8幀圖片經過Photoshop分別將畫布等比例擴大成150*150象素圖片(由於是提取的素材,初始寬和高是不均衡值,因此必須擴大成本身的需求,這樣人物會在圖片中居中,而且爲後期加入武器或坐騎留好餘地。稍微的偏離也能夠在後期進行微調),並將他們從開始到結束分別命名爲0.png,1.png,2.png,3.png,4.png,5.png,6.png,7.png,而後將這8張圖片保存到相關目錄下,到此準備工做終於結束了動畫
這裏在WPF中有一個UI線程級別的定時器DispatcherTimer,而Unity中沒有提供相似的機制(或許是我不知道),Unity主要是心跳來控制的也就是Update函數了,可是這裏的原理就是幀動畫,每一個多少幀變化一下player的動做圖片便可,但咱們知道幀就是和時間相關的。ui
簡單的說:就是定義一個圖片數組,而後實現一個定時器,時間到了就獲取數組裏的一張圖,替換精靈的背景圖片。
這裏咱們把問題分解主要是兩個子問題,1、定時獲取圖片替換精靈背景,簡稱定時器;2、數組的圖片循環獲取,簡稱數組順序遍歷
先從軟柿子開始,二比較簡單,一個數組,加一個全局基數器變量 搞定
private int currentTexture = 0;
public Sprite[] textureArray;
private SpriteRenderer spriteRenderer;//遍歷數組 到數組未從新回到0索引
void NextTexture()
{
currentTexture++;
if (currentTexture >= textureArray.Length)
{
currentTexture = 0;
}spriteRenderer.sprite = textureArray[currentTexture];
}
1、定時器,稍微麻煩點,Unity3d並無提供像樣的UI定時器封裝,這裏爲了驗證 這種定幀動畫的原理,我用幾種Unity3d中定時器機制分別實現了動畫功能,實際開發中用的A和D方法比較多,至少我查了很多教程基本是A和D
首先是變量
private float animationDeltaTime;
private float animationDelay = 5 / 60f;
A、Update 心跳延時定時器
void Update()
{
animationDeltaTime += Time.deltaTime;
// Debug.Log(animationDeltaTime);
if (animationDeltaTime >= animationDelay)
{
animationDeltaTime = 0;NextTexture();
}
}
B、協程遞歸定時器
void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>() as SpriteRenderer;
StartCoroutine(TextureChanger());
}IEnumerator TextureChanger()
{
yield return new WaitForSeconds(animationDelay);
if (true)
{
//Debug.Log(animationDeltaTime);
NextTexture();
StartCoroutine(TextureChanger());
}
}
C、InvokeRepeating定時器
void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>() as SpriteRenderer;
InvokeRepeating("NextTexture", 1, 0.1f);//1秒後調用LaunchProjectile () 函數,以後每5秒調用一次
}
D、時長求餘法(我本身起的名字,比較巧妙可能也是用的比較多的方法)
using UnityEngine; using System.Collections; public class PlayerAnimator : MonoBehaviour { public Sprite[] sprites; public float framesPerSecond; private SpriteRenderer spriteRenderer; // Use this for initialization void Start () { spriteRenderer = GetComponent<Renderer>() as SpriteRenderer; } // Update is called once per frame void Update () { int timeIndex = (int)(Time.timeSinceLevelLoad * framesPerSecond); int index = timeIndex % sprites.Length; spriteRenderer.sprite = sprites[index]; } }
原理的代碼分析和代碼展現完畢,下面是本身在網上找的前人分享的一些代碼,自測能夠運行,主要的問題仍是一句老話,「原理很簡單,現實很殘酷」,實際一個簡單的2d動畫涉及的東西不少,好比性能效率,狀態控制,封裝合理性等等吧。
A、Unity3d UGUI序列幀動畫 實現 (原文地址:http://www.cnblogs.com/mrblue/p/5191183.html)
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using System; [RequireComponent(typeof(Image))] public class UGUISpriteAnimation : MonoBehaviour { private Image ImageSource; private int mCurFrame = 0; private float mDelta = 0; public float FPS = 5; public List<Sprite> SpriteFrames; public bool IsPlaying = false; public bool Foward = true; public bool AutoPlay = false; public bool Loop = false; public int FrameCount { get { return SpriteFrames.Count; } } void Awake() { ImageSource = GetComponent<Image>(); } void Start() { if (AutoPlay) { Play(); } else { IsPlaying = false; } } private void SetSprite(int idx) { ImageSource.sprite = SpriteFrames[idx]; ImageSource.SetNativeSize(); } public void Play() { IsPlaying = true; Foward = true; } public void PlayReverse() { IsPlaying = true; Foward = false; } void Update() { if (!IsPlaying || 0 == FrameCount) { return; } mDelta += Time.deltaTime; if (mDelta > 1 / FPS) { mDelta = 0; if(Foward) { mCurFrame++; } else { mCurFrame--; } if (mCurFrame >= FrameCount) { if (Loop) { mCurFrame = 0; } else { IsPlaying = false; return; } } else if (mCurFrame<0) { if (Loop) { mCurFrame = FrameCount-1; } else { IsPlaying = false; return; } } SetSprite(mCurFrame); } } public void Pause() { IsPlaying = false; } public void Resume() { if (!IsPlaying) { IsPlaying = true; } } public void Stop() { mCurFrame = 0; SetSprite(mCurFrame); IsPlaying = false; } public void Rewind() { mCurFrame = 0; SetSprite(mCurFrame); Play(); } }
B、Native2D 序列幀動畫 實現
這部分代碼已經在上文「D、時長求餘法(我本身起的名字,比較巧妙可能也是用的比較多的方法)」中貼出,這裏再也不重複
實際上「序列幀動畫」的實現原理很簡單,就是一個定時器,可是Unity3d恰恰沒有封裝定時器,因此就須要咱們深入瞭解其的特性,而後選最優的方式(雖然前人已經栽樹了),萬里長征第一步繼續吧。