时光煮雨 Unity3D实现2D人物动画① UGUI&Native2D序列帧动画

系列目录

【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个方向的系列帧图片以求更为逼真),即将每一个人物每一个动做的各方向的每帧均存成一张图片,以下图仅以从破天一剑游戏中提取的素材为例:性能

(特别申明:本系列教程所使用的若有注明归属权的图片素材均来源于网络,请勿用于商业用途,不然形成的一切后果均与本人无关。)学习

1

从上图能够看到,我将人物向右方跑步共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(1)

实现

这里咱们把问题分解主要是两个子问题,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恰恰没有封装定时器,因此就须要咱们深入了解其的特性,而后选最优的方式(虽然前人已经栽树了),万里长征第一步继续吧。

相关文章
相关标签/搜索