Unity3D初学之2D动画制
作者:Alex Rose
Unity最近宣布推出额外的2D游戏支持,添加了Box 2D物理和一个精灵管理器。
但这里还是有些技巧需要牢记在心。逐帧更改图像只是动画制作的冰山一角,若要让你的游戏出色运行,你还得使用转换和旋转等功能。
现在让我们先从基本技巧开始。
更改帧
如果你已经准备好了制作动画的纹理,你可能会使用SpriteManager脚本的付费版本,或者Unity的新版本。假设你使用的是2D位面和纹理。这就是一个低效率的方法,但如果你是在制作一个game jam的项目,你可能会想塞入一些可行而好看,但却不一定有效的元素。这也是一种覆盖了所有步骤的全面方法,如果是在精灵管理器中则可能被删除某些步骤。
首先,你将需要一个公开的Texture[] 阵列,所以你可以将纹理拖入到Unity编辑器中的对象,以及一个在Start()中初始化到0的整数currentTexturep。下一步你需要一个像这样运行的NextTexture() 函数:
NextTexture(){
currentTexture++;
if(currentTexture>=textureArray.Length) currentTexture=0;
AnimatedPlane.renderer.material.mainTexture = textureArray[currentTexture];}
有两种简便的方法可以调用这种函数:协同程序递归和固定间隔。
使用固定间隔是最快的方法(但较不精确)。你需要一个整数计数器,在你的Start()函数中初始化到0,以及一个FixedUpdate() 函数(游戏邦注:每次都会更新,你可以在Unity时间管理器中自己调整)。
在FixedUpdate()中放置你的条件句(例如if(walking)),并在其中用conter++增加你的计时器,之后设置如下声明:
if(counter>=animationDelay){
counter=0;
NextTexture();
}
这里的animationDelay可以是你自己选择的任意值。这将以持续速度(取决于你在Unity时间管理器中设置的速度)推进帧。
第二个方法是使用递归。但这一方法的劣势在于不易处理条件句,但你还是能够获得所需要的准确延时。如果你想让特定帧延长或缩短,这一方法就尤其管用。你需要一个IEnumerator TextureChanger() 以及to StartCoroutine(TextureChanger()) in Start().
IEnumerator TextureChanger(){
yield return new WaitForSeconds(timeInterval);
if([conditions]) NextTexture();
}
这里timeInterval也是你自己选择的任意值。有了这些函数,你就可以将任意数量的纹理拖到GameObject,这样只要你提供正确的条件,它就会正确运行动画。
现在让我们做一些更有趣的操作。
平滑移动到一个点
以下公式是制作Unity 2D动画的一个诀窍:
where 0 < slidespeed < 1. I recommend 0.1f as a good slidespeed value.
这个公式允许你把对象完美移动到一个点。在滑动GUI、角色控制、关卡生成、摄像跟随、褪色/移位等操作中尤其管用。

descension(from gamasutra)
这是我即将发布的新游戏《Rotation Station》中的一个高级版本,是从一个较低点移到一个较高点,最后变成一个小泡。每个贴图都会根据该公司向下移动,但每个贴图都有随机的延时,随机的初始化旋转(也使用这一公式旋转至它所期望的方向)。
关于角色控制的例子可以参考我最近推出的《Rude Bear Radio》,在这个项目中,该公式运用于制作流畅的鼠标控制方法。

Bearo-Wing(from gamasutra)
那么,让我们看看如何将其运用于上述例子。
首先,我们需要知道鼠标位于2D区域。为了找到它,我们要先将这个代码放置于滑动GameObject的FixedUpdate()函数中:
Vector3 MousePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,
Input.mousePosition.y, transform.position.z-Camera.main.transform.position.z));
这里使用了鼠标的X和Y轴位置,以及从摄像机到滑动GameObject的距离来确定鼠标的2D位置和3D坐标。现在我们要从这个环节的开端来调整该公式。所以,要记住Unity中的2D步骤。
transform.position += new Vector3((MousePosition.x-transform.position.x),
(MousePosition.y-transform.position.y),0)*slidespeed;
你就只要这两行代码就搞定了!至于GUI这类东西,你可以在之后编写一个声明:
if(Mathf.Abs(finalvalue-currentvalue)
让我们再看另一个例子,《Rude Bear Radio》中的困难模式Mario台阶。

Super-Bario-Bros(from gamasutra)
其中的背景使用以下公式由黑变白:
background.renderer.material.color =
(1-factor)*background.renderer.material.color+factor*desiredcolor;
你从中可以看到它遵从的基本形式,简写就是Next = current+(final-current)*factor。代码会检查R值是否处于一定的色彩范围,如果是,它就会更改factor,令其更为迅速地褪色。如果R值非常接近于1,它就会将其所需颜色设置为黑。你还可以检查下R、G和B,并以一个阵列推进颜色。你可以在我的第二个案例项目《Rude Bear Rising》的背景中看到这种例子。
目前来看,这些都很简单,你可以照搬公式做。而下一步操作则需要考虑更多因素。
三角法和数学的重要性
三角法对动画制作来说非常重要。就算有了优秀的帧,也不一定能够令它们看起来生动美丽,有时候你根本不需要帧就能做事。
例如,我首次进入Ludum Dare工作室时,我的室友就给我画了几张图。我至今仍然记得其中的每个角色,用什么方法呢?像木偶一样将角色绑在棍子上操作。

RudeBear(from gamasutra)
这种移动方式非常简单,转换时用正弦(sin),旋转时用余弦(cos)。
为了创造这种动画,你要让波纹停止并在你松手和输入时继续,否则这种动作就会极端分散。
所以你需要一个首要变量(即我所谓的walkbob),只要对象还在移动,它就会在FixedUpdate中增加Time.deltaTime。之后就制作你的函数:
translation = maxHeight*Mathf.Sin(speed*walkbob);
rotation = maxRoll*Mathf.Cos(speed*walkbob/2);
然后将位置和旋转设为这些值(例如transform.position = new Vector3(transform.position.x,translation,transform.position.y))。
这可以处理类似那种动作,但是还有一种动画需要考虑更多因素,这就是我所谓的三角舞,它用于制作可爱角色随着音乐摇摆起舞,例如下图:

Rude-Bear-Radio(from gamasutra)
首先,你在打算移动游戏对象时,就要选取一个浮动的initialtime = Time.time,这样你的对象才能以正确的位置和方向开始,并且不会突然跳入动作。
下一步,我们就要想想三角函数的概念。
我们使用简谐运动,其形式如下:
Y是指当前值,A是振幅,f是频率,t是运行时间,phi是指阶段。首先,我们很容易确定振幅。它是我们希望对象所具有的最大化高度或旋转。
下一个就是运行时间和阶段。我们将用(Time.time-initialtime)轻松取代t而一次性处搞定这两者。这会将φ降为0,所以最后我们只需要得到频率。我强烈推荐令此频率与你的音乐频率吻合(如果你是自己作曲,这一点很容易办到)。
如果你还不知道自己音乐的BPM,那就去摸索每个节拍,直到弄懂为止。如果你已经有节奏感,这就很好办了。如果你没有,那也不用担心,我们会利用中心极限定理。持续点触你的整首歌,每欠点触都会减少平均值中的错误。
现在你就知道它每分钟如何打节拍了。你将以60来划分这个值,找到每秒多少拍。如果你只想在半小节或一个完整的小节中使用一次动作,那就可以按2或4数值来划分。这个数值就是频率,你可以从 Mathf.PI获得pi。所以现在你要将对象的位置设为该数值。此时你只是在调整高度:
transform.position = new Vector3(transform.position.x,maxheight*
Mathf.Sin(2*Mathf.PI*frequency*(Time.time-initialtime)),transform.position.z);
但这还不够好。首先,我们要让对象合拍,这样它就得从其最大振幅开始。我们此时要使用余弦。但更重要的是,要让它从一端跳跃到另一端,这样它就不会像波纹一样滑上滑下。这时要用cos^2,这样它才会突然停在0标记,并再次走向正数。因此:
transform.position = new Vector3(transform.position.x,maxheight*Mathf.Pow(Mathf.Cos(
2*Mathf.PI*frequency*(Time.time-initialtime)),2),transform.position.z)
这里要注意舞动的高度。最终旋转要使用正弦,这样其旋转和转化就是异相的。因此:
transform.rotation = Quaternion.EulerAngles(0, maxRotation*
Mathf.Cos(2*Mathf.PI*frequency*Mathf.Sin(Time.time-initialtime)), 0);
这里要记住两件事:如果你使用一个位面,并希望它面对摄像机,这些值就不能是0和0,而必须是pi/2和–pi/2。这里我使用的是EulerAngles而不是Euler,因为Euler使用的是度数,而EulerAngles使用的是弧度。我们要做一些数学运算,我们现在要运用弧度,所以得使用EulerAngles!否则你之扣就得输入一个换算因数。
在此你可以看到我新游戏的一种类似动画,你可以用同种方法更改比例而不是位置。

RoStlogo(from gamasutra)
现在我们要讨论最后一种动画类型:
纹理补偿
你可以用自己所学到的一切来操作2D纹理补偿,以制作美妙的动画背景。你可以在《Rude Bear Radio》及其主界面中看到我对《VVVVVV》的拙劣模仿。抓取一个位面,在其上粘附一个重复纹理,编写一个FixedUpdate() 函数,并根据下属性进行调整:
renderer.material.mainTextureOffset
renderer.material.color
这将导致墙体四处滑动并改变颜色。最后,如果你想让它们看起来更有趣,还可以运用renderer.material.mainTextureScale。这可以制作一个真正有趣的视觉效果,但它很有干扰性,不要让它影响你的主要游戏玩法。
最后,你还得看一下其中的插值。这可以让动画制作更轻松,但我个人认为在第二部分中最好使用公式
http://express.ruanko.com/ruanko-express_56/tech-overnight5.html
作为一款制作3D的跨平台的游戏引擎,相对与其他2D游戏的开发工具(如cocos2d、cocos2d-x等),Unity有许多优点,如可视化、所见即所得;如跨平台;如开放的插件平台等等。作为一个初学者,简单分享一下Unity3D制作2D动画的经验。
Unity3D制作2D动画方法也有多种:
1、动画帧序列
作为常见的方法,相信很多开发者都会用。与cocos2d一样,Unity中也可以使用动画帧使你的角色动起来。示例代码:
using UnityEngine; |
这里代码很详细,没有执行过,到时动画帧按照这种思路可以轻松实现。AnimaOne方法可以在动画最后一帧的时候实现其他控制;AnimaAlways方法则一直循环播放动画。
2、动画渲染
有些情况动画帧太多或者太浪费资源,我们就把动画做在一张图片上,控制相机或者材质渲染图片的位置。个人认为这种方法比较适合数据,Tag的动态显示。
例如:
public Texture imgTexture; //申明一张图片 |
3、上面介绍了简单的动画效果,其实在游戏中,我们经常要使游戏里的角色们动起来,位移,旋转,等等。
在Unity中,没有刚体的Object的位移和旋转都是通过Transform属性来控制的。transform下有position和rotation属性,且Unity提供了普通旋转和位移的方法。最常用的就是通过坐标增量来控制Object的动作。这里比较难缠的一点就是相对位移和绝对位移。所以在做object移动的时候要格外小心,是相对世界坐标还是其parent的坐标。
其次iTween是做2D动画比较常用的插件。其官网和其他博客对方法的使用有比较详细的介绍。这里叙述一点,就是关于iTween.Hash().iTween提供了hash表,使得简单的动画更加自然和多样。hash的参数根据iTween不同的方法而稍有差异。
比较常用的:
- x,y,z,表示目标Vectore3的量;
- time,时间;
- easeType,过渡方式,平滑,直线,或者其他;
- incomplete,当前iTween动画结束调用的动作或这方法;等等。
Unity3D初学之2D动画制的更多相关文章
- Unity3D 之2D动画机
这里来讲解一下2D动画机的使用 2D的时候,默认的情况下,可以调用默认的站立之类的动画,然后通过触发,可以变化自己的动画. 一:将一个图切成一些一个元素 二:创建一个精灵,给精灵添加一个动画机 三:给 ...
- Unity3D ShaderLab 模拟精灵动画
Unity3D ShaderLab 模拟精灵动画 在上一篇,介绍了通过Shader 模拟纹理运动,那么更深一步讲,我们也可以把帧动画的精灵纹理运动通过shader实现. 虽然大家都是在游戏脚本中做更高 ...
- 2D动画如何做出3D体积感
https://cowlevel.net/article/1959026 <AngerForce>幕后故事 这篇文章是个老坑,最近有时间开始写,也是对之前项目的一个总结和记录吧. 本篇文章 ...
- 2D动画的制作
通过css3的transform transition可以实现平移,旋转,缩放,拉伸等效果 1.缩放 -webkit-transform: scale(1); -moz-transform: sca ...
- css 2D动画
2D动画: 通过 CSS3 transform转换,我们能够对元素进行移动.缩放.转动.拉长或拉伸. 2D移动:translate().使用translate()函数,你可以把元素从原来的位置移动. ...
- 手游[追忆之青]动画导演:2D动画制作技巧
转自:http://www.gamelook.com.cn/2016/09/264591 GameLook报道/由一般法人计算机娱乐协会(CESA)主办的CEDEC2016日前在日本横滨举行,诸多开发 ...
- css3-11 如何实现2D动画
css3-11 如何实现2D动画 一.总结 一句话总结:就是transform属性,属性值为1.translate() 2.rotate() 3.scale(),而这是哪个属性值是带参数的 ...
- 利用Unity3D制作简易2D计算器
利用Unity3D制作简易2D计算器 标签(空格分隔): uiniy3D 1. 操作流程 在unity3DD中创建一个新项目 注意选择是2D的(因为默认3D) 在Assets框右键新建C#脚本 在新建 ...
- 记录 Spine骨骼动画导入unity 步骤[unity3d 4.6.6版本 2d动画]
1:准备好unity使用Spine所需要的运行库,可到如下地址 https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine ...
随机推荐
- celipse关联hadoop源码
可以在这里下载hadoop的源码包 https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/ 我自己下载的是hadoop2.6.0的源码包 ...
- KVM CPU线程等学习记录
绝大多数操作系统调度单位是线程.线程是调度和分配的基本单位,进程是资源拥有的基本单位.linux下fork的叫进程pthread叫线程创建进程比线程性能要差好多5-100倍,因进程不同而异.进程之间共 ...
- Django跨域问题
相关博客地址 同源策略与Jsonp 同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可 ...
- 在oracle中创建自动增长字段
参考http://www.cnblogs.com/jerrmy/archive/2013/03/13/2958352.html http://www.jb51.net/article/43382.ht ...
- 02-spark sql
1.概念 Spark SQL是一个用来处理结构化数据的Spark组件. 优点: ①SparkSQL是一个SQL解析引擎,将SQL解析成特殊的RDD(DataFrame),然后在Spark集群中运行 ...
- python类脚本
一在windows主机上探测主机是否存活 下面以多线程的方式: import osimport timeimport subprocessfrom concurrent.futures import ...
- tree-data
[{ label: '一级 1', children: [{ label: '二级 1-1', children: [{ label: '三级 1-1-1' }] }] }, { label: '一级 ...
- 【转】R语言 RStudio快捷键
链接地址 http://blog.sina.com.cn/s/blog_403aa80a0101ar8q.html 控制台 功能 Windows & Linux Mac 移动鼠标到控制台 C ...
- jquery的ajax,请求JSON数据。
第一个页面:1.htm <!DOCTYPE html> <html> <head> <title></title> <script t ...
- 《算法》第四章部分程序 part 1
▶ 书中第四章部分程序,加上自己补充的代码,包含无向 / 有向图类 ● 无向图类 package package01; import java.util.NoSuchElementException; ...