unity3d为什么添加unity mousepositionn动画

Unity3D 的 Mecanim 动画系统可以直接复用 3DS MAX 中制作的动画文件中的位移,这个就是通过 applyRootMotion 来达成的,我们只需要在使用 Animator 控制动画播放的同时,设置 Animator 的 applyRootMotion 字段为 True 就 OK 了。
那么怎么来利用这个特性达成我们想要的一些效果呢?这个 applyRootMotion 到底指的是啥呢?
ApplyRootMotion,从字面上理解来看,是『应用根节点的运动』,听起来貌似像那么一回事。可是我们可以从官方文档上看到这样一段话:
The Root Transform is a projection on the Y plane of the Body Transform and is computed at runtime. At every frame, a change in the Root Transform is computed. This change in transform is then applied to the Game Object to make it move.
翻译过来的意思,应该是这样的:
根节点的运动变换其实就是整个物体运动变换通过 Y 轴垂直在水平面上的一个投影。根节点的运动变换在动画的每一帧中都会进行计算。计算出来的根节点变换结果都会应用在播放动画的对象上,让该对象按照根节点的运动变换进行移动。
这段话大体的意思就是,RootMotion 这个玩意就是作用于动画物体在 X 轴和 Z 轴上的位移的,而且这个位移是根据实际播放的动画中每一帧物体的位移在 X 和 Z 轴上投影计算出来的。
这个特性非常赞特别是对于某些技能动画,整个动画是有一定位移的,但是动画的位移是动作设计师在设计时根据动作需要调出来的,位移是跟动作的幅度直接相关和匹配的。
那么在释放技能的时候就只需要直接播放动画,并且应用这个 Root Motion 的特性就可以很好的完成角色在播放攻击动作的同时进行移动,动作播放完毕之后就在动画结束帧角色所在的位置,切换为待机动作就 OK 了。
看起来很牛逼的样子对不对?是的,确实很牛逼。但是还有很多事情需要我们都一一了解以后,我们才能做出我们想要的东西的。
下面我们先岔开一下话题,好好说说这个 Animation Import Settings 中『Animations』Tab 页中各项设置的作用。
Import Animation,勾选这个才可以导入动画到 Unity 工程中;
Bake Animations,这个选项只在使用 Humanoid 动画并且使用到了 IK 特性的时候才可用;
pression,这个是关于动画压缩选项的,默认会选择 Keyframe Reduction 这个是『压缩关键帧』,就是 Unity 会自行重采样动画的关键帧,还有两个选项『Off 和 Optimal』,一个是关闭动画压缩,一个是最优化压缩(应该是压缩效率最高,动画效果失真度可能也较高)
选择了 Keyframe Reduction 或者 Optimal 压缩选项,就会有三个用于控制压缩选项的系数配置, Rotation Error,Position Error 和 Scale Error,这个三个参数默认都是 0.5,越小呢精度就越高也就是说动画的失真度越小。
Clips,这个下面列出了这个 FBX 文件下包含的所有动画,我们在默认的动画文件基础上新建和删除动画片段 (Animation Clip),当然每个动画片段都是可以指定起始帧和结束帧的; 以下的设置都是针对单个动画片段滴:
Loop Time,勾选这个选项之后,如果 Animator 处于播放这个动画状态时,在播放完第一遍这个动画片段之后,会自动循环从起始帧再次开始播放动画,如此循环往复。如果我们不勾选这个选项,例如 Animator 一直处于播放这个动画的状态,那么动画会定格在动画的结束帧,直到我们通过 Animator 切换这个 Animator 状态机的状态,切换到其他的动画;
Loop Pose 和 Cycle Offset,在勾选了 Loop Time 之后生效的两个选项,Loop Pose 用于控制动画循环播放时,从结束帧切换到起始帧时,动画的动作可以无缝的衔接上,Cycly Offset 就是用于控制循环的时候起始帧偏移用的;
Root Transform Rotation,根节点的旋转信息
Bake Into Pose,勾选后会将根节点每一帧的旋转方向信息烘焙到动画的骨骼运动中,在整个动画播放的过程中,根节点的旋转信息就不会在通过 Root Motion 作用到播放该动画的 GameObject 上了,这就意味着这个动画播放的过程中,该物体的 Transform 中的 Rotation 值不会因为动画中物体做了任何旋转而发生改变,而是会保持一个恒定的值,和该动画播放之前的旋转值保持一致;
Based Upon (at Start) 或者 Based Upon,根节点旋转的参考基准,有两个选项『Original 和 Root Node Rotation』这两个分别指的是动画文件中指定的旋转值和根节点旋转信息,其实我更愿意将 Original 理解为动画中原点的旋转值,因为在整个动画播放的过程中,所有骨骼肯定都会有旋转和位移的变换,但是动画的原点其实一定都是确定的,这样理解感觉更简单也更形象一些,勾选了 Bake Into Pose 之后,就会变成 Based Upon 而不勾选 Bake Into Pose 就会保持为 Based Upon (at Start),这个目前还木有理解为啥;
Offset,旋转角度与参考基准的偏移(以度为单位);
Root Transform Position(Y),根节点位移信息(Y 轴)
Bake Into Pose,勾选后会将根节点每一帧在垂直 Y 轴方向上的运动信息烘焙到动画的骨骼运动中,在整个动画播放的过程中,根节点在 Y 轴方向的所有位移信息不会通过 Root Motion 作用到播放该动画的 GameObject 上,这就意味着我们在场景中看到物体在 Y 轴上有位移,例如向上或者向下移动,但是该物体的 Transform 中的 Position 信息不会发生改变,会跟动画播放之前的 Position 信息保持一致;
Based Upon 或者 Based Upon (at Start),这个貌似有点不一样哦,在选中 Bake Into Pose 之后会变成 Based Upon (at Start),不勾选的时候是 Based Upon,不过这个就能理解了。不烘焙的话,那么 Root Motion 中 Y 轴的变化就依赖于选择的『Original 或者 Root Node Position』的 Y 轴位移变化,如果选择烘焙的话,那么就以这个动画的起始帧的 Y 轴作为整个动画 Root Motion 的 Y 轴位移,在整个动画播放的过程中,Y 轴的位移都是恒定不变的;
Offset,垂直方向上的偏移;
Root Transform Position(XZ),根节点位移信息(水平面,XZ 轴)
Bake Into Pose,勾选后会将根节点每一帧在水平面(X 和 Z 轴)方向上的运动信息烘焙到动画的骨骼运动中,在整个动画播放的过程中,根节点在 X 和 Z 轴方向的所有位移信息不会通过 Root Motion 作用到播放该动画的 GameObject 上,这就意味着我们在场景中看到物体在水平面上移动,但是该物体的 Transform 中的 Position 信息不会发生改变,会跟动画播放之前的 Position 信息保持一致,假如动画中物体会向前移动 3 米,我们会看到物体在整个动画播放过程中确实在向前移动,播放到最后一帧时确实向前移动了 3 米,但是当这个动画播放完毕之后,切换到任何其他的动画时,物体会直接闪回这个动画播放前物体所在的位置,所以通常我们需要保留动作位移的动画都不会勾选这个选项。那这个选项有神马用捏?例如某些待机动画,我们其实希望物体只是做一个待机动作,但是实际上不想让物体在水平方向上有位移,这个时候就可以勾选这个选项了,到时候看起来物体就像是钉在水平面上了;
Mask,这个掩码主要是用于控制动画播放过程中,各个骨骼之间的运动变换的
Definition,可以选择从动画文件创建也可以选择使用其他动画文件中已经创建好的配置;
Transform,这个就是动画文件中所有骨骼的层级关系,可以选择勾选那些需要应用动画中运动变换的骨骼;
Curves,这个主要用于设置某些跟动画相关的参数用,例如控制整个动画播放过程中的速度参数之类的,在动画播放的过程中可以通过 Animator.GetFloat(ParamName) 函数来读取曲线的值,曲线的 X 轴为动画的时间轴,Y 轴为曲线的值,曲线可以通过曲线编辑器进行增加关键点,调整曲线斜率进行编辑,读取时默认会根据当前动画播放的进度作为 X 轴的值进行读取,一个动画片段可以有多个曲线;
Events,这个是用于在动画播放的过程中触发事件的,例如整个动画中有起跳和落地两个事件需要在准确的时间点触发并通知到游戏中其他的对象,那么就可以在 Events 时间轴上新增事件通知,设置好触发的方法名称和参数,在播放该动画的 GameObject 上确保有某个脚本中有与该事件通知的方法签名一致的方法就好了,当动画播放到触发通知时间时,就会向 GameObject 广播该时间通知,脚本中方法签名一致的方法就会被回调了,那我们就可以做我们需要做的事情了。
说了这么多貌似跟 Root Motion 不是很相关的东西,那么究竟我们今天的主题是啥呢?肯定还是 Root Motion 这货。主要因为动画导入时的设置对于 Root Motion 的应用影响非常直接,所以前面絮絮叨叨地把这个动画导入设置都罗列了一遍。
回到正题,Generic 动画应用 Root Motion 有以下几个特点:
Root Motion 仅仅作用于 GameObject 在 X 和 Z 轴上的位移变换,不影响 Y 轴上的位移。例如现在播放一个从地上向前空翻之后落地的动画,设置 Animator 的 applyRootMotion 为 True,也就是应用 Root Motion,那么动画在播放过程中,物体会在水平方向和垂直方向上都按照实际动画的运动轨迹进行运动,如果将 applyRootMotion 设置为 False,那么我们就只能看到动画在原地起跳然后再落地,动画中原本应有的在水平方向的位移就没有了;
Root Motion 与导入动画时设置 Root Transform Position(XZ) 是直接相关的,如果我们选择了将 X 和 Z 轴方向上根节点的位移烘焙到动画骨骼运动中的话,那么动画播放过程中不论我们是否将 Animator 的 applyRootMotion 设置为 True 还是 False,动画播放过程中物体在 X 和 Z 上的移动是一定的,因为这个已经被烘焙到骨骼动画中,只要动画播放,物体就会移动,但是在动画播放的过程中 GameObject 的 Position 值不会改变,在动画结束后我们切换到其他动画的时候,其他动画开始播放时的 GameObject 的位置会回到这个动画播放前的位置,所以如果我们需要对某个动画应用 Root Motion 的话,那么这个动画在导入的时候就不要烘焙其在 X 和 Z 轴方向上的 Root Transform Position,让 Unity 自行根据动画中根节点的位移进行位移计算 GameObject 的位置信息;
注意 Root Motion 与 Rigidbody.Velocity 属性的关系,如果有两个动画 A 和 B,播放 A 动画的时候,希望 A 动画应用 Root Motion,而在播放 B 动画的时候不想应用 Root Motion,那么就直接在切换到动画 B 的时候,将 Animator 的 applyRootMotion 设置为 False 就 OK 了。但是如果播放动画的 GameObject 带有 Rigidbody 组件,那么需要注意一点,在播放 A 动画时 Rigidbody 的 Velocity 并不会在切换到 B 动画时清零,也就是说如果 A 动画的运动速度较快,那么切换到 B 动画的时候,如果希望 B 动画播放的时候 GameObject 按照自己的设定轨迹运动,就需要自行手动在切换到 B 动画之前将 Rigidbody 的 Velocity 属性清零,防止 GameObject 按照 A 动画的运动惯性继续运动。这个问题在没有 Rigidbody 组件的 GameObject 上不会存在;
这边再岔开一下,说说这个动画跟 Rigidbody 之间的关系:
如果我们没有将 Root Transform Position 的 Y 和 XZ 轴进行烘焙的话,那么在动画播放的过程中,Rigidbody 将会自动获得动画中物体运动的速度信息,直接通过 Rigidbody.Velocity 属性就可以获得;
如果我们将 Y 轴进行烘焙,那么 Rigidbody.Velocity 在 Y 轴上的值将会一直为 0,对于 XZ 轴也是一样的,如果烘焙了 XZ 轴的位移,那么整个动画播放过程中,Rigidbody.Velocity 在 X 和 Z 轴上的值都会为 0;
如果播放动画的物体没有 Rigidbody 组件,那么动画的运动都会仅仅按照动画实际的位移来进行逐帧播放,不会出现上文中提到的动画播放切换之后还存在的运动惯性问题,因为物理引擎依赖于 Rigidbody 组件,如果没有该组件,所有动画的播放都只是逐帧播放动画,不会存在速度的概念只有移动位移。
Rigidbody 使用使用重力对于动画在 Y 轴上的位移没有任何影响,不论是否对 Root Transform Position 的 Y 轴进行了烘焙。
转自:/?p=528
阅读(...) 评论()在Unity引擎中使用Easing Function制作动画 | Unity3D教程手册
当前位置 :
>> 在Unity引擎中使用Easing Function制作动画
在Unity引擎中使用Easing Function制作动画
在制作游戏的时候,动画是不可或缺的一部份,即使是与游戏核心无关的 GUI 部份,若少了动画就显得粗制滥造。然而大多数的 GUI 效果:像是视窗飞进画面中央、按下按钮时放大效果之类的动画等等,其内容都有很高的相似性,也就是「在某段时间内,把物件的某些状态转移到另一个状态」。若要使用 3D Max 之类的软件一一制作,将显得麻烦而没有效率。
在这篇文章中,以 Unity 作为范例,介绍如何实作一个简单的 easing function 元件。
想像一下我们正在制作游戏过程中的暂停按钮。当玩家按下暂停钮时,画面上会出现暂停的面板以及三个按钮。当然,直接让它们出现是很粗糙的作法,因此我们希望面板及按钮可以从画面外飞进来。
使用线性内插
最简单的呈现方式是使用线性内插法,指定好某个物件的起始状态(位置、大小、顏色等)与结束状态,再指定动画时间。只要有了这些资讯,我们可以用简单的数学运算内插出动画播放时每一格 frame 的物件状态。
&&&01using UnityEngine;02using System;03&04public class EasingDemo : MonoBehaviour {05public Vector3 destination;06public float duration = 1;07public float delay = 0;08&09private Vector3 source;10private Vector3 delta;11private float elapsed = 0;12&13void Start()14{15source = transform.position;16delta = destination − source;17}18&19void Update()20{21elapsed += Time.deltaTime;22if(elapsed & delay && elapsed & (delay+duration)){23float ratio = Math.Min(1, (elapsed−delay)/duration);24transform.position = source + ratio*delta;25}26}27}
这个简单的元件让我们可以在 Unity 编辑器中直接设定物件的起始位置、结束位置及动画播放的时间。接下来,我们把面板与按钮放在镜头外面,然后把它的结束位置设定在画面内,按下 play 后马上可以看到它的效果……
这个动画之所以看起来很无聊,大部份的原因在于我们使用了很无聊的线性内插法。想像一下如果这个按钮是用以下的方式飞进画面:
很快地冲进来,然后紧急剎车停在目的地。
冲过头然后拉回目的地。
撞到目的地后像皮球般反弹,最后再落回目的地。
这样的动画,显然会比死板的等速度飞入更活泼、更有动感。然而制作这种动画效果就没办法用线性内插了。当然,若使用 3D Max 就可以借由贝兹曲线 (Bézier curve) 来编辑这种较复杂的动画,或是直接用 Unity 的动画编辑器也能办到。然而编辑贝玆曲线的各个控制点却是一件很花时间的工作,尤其像第三个例子,为了达到反弹的效果,我们得额外加入两三个 key frame 才行。过程并不是很难,但就是很花时间。
Unity 使用 Easing Function 制作动画
使用非线性内插法
我们不希望动画是平板的线性内插法,但又觉得编辑贝兹曲线的控制点太麻烦,那么答案就呼之欲出了:使用其它的数学曲线来代替直线。比如说如下的曲线:
在Unity引擎中使用Easing Function制作动画
尽管物理上并不正确,但它看起来就像是「很快地冲进来,然后紧急剎车」的样子。因此我们可以把它套用到内插计算式中:
&&&1void Update()2{3elapsed += Time.deltaTime;4if(elapsed & delay && elapsed & (delay+duration)){5float x = Math.Min(1, (elapsed−delay)/duration);6float ratio = (float)Math.Pow(x−1, 3) + 1;7transform.position = source + ratio*delta;8}9}
结果如下,同样都是一秒钟的动画,感觉起来是不是有微妙的差异呢?
Easing Function 惯例格式
Easing function 具有一项优势:只要抽换不同的 easing function,不需要另外编辑 key frame 或是曲线控制点,就马上可以得到另一种动画。但为了达到这个「可抽换」的目的,我们得要使用大家所惯用的写法:
&&&01public class Easing {02public static float Linear(float t, float b, float c, float d)03{04return c*(t/d) + b;05}06&07public static float OutCubic(float t, float b, float c, float d)08{09t /= d;10t−−;11return c*(t*t*t+1)+b;12}13}
一般化的 easing function 有四个参数:
t (time): 代表动画开始播放到现在所经过的时间。
b (beginning): 代表某项属性的初始值。
c (change): 代表到动画结束时,该属性的变化值。亦即动画结束后,这项属性的值应為 b+c。
d (duration): 代表整段动画的播放时间。
因此我们可以改写原本的 Update():
&&&01public delegate float EasingFunction(float t, float b, float c, float d);02EasingFunction easing = new EasingFunction(Easing.OutCubic);03&04void Update()05{06elapsed += Time.deltaTime;07if(elapsed & delay && elapsed & (delay+duration)){08Vector3 p = new Vector3();09float t = elapsed − delay;10p.x = easing(t, source.x, delta.x, duration);11p.y = easing(t, source.y, delta.y, duration);12p.z = easing(t, source.z, delta.z, duration);13transform.position = p;14}15}
这么一来,我们就可以利用别人写好的 easing function 套用到我们的动画元件中。事不迟疑,马上就来看看范例。
上述「像是皮球般地弹跳」显然是一种很困难的曲线,但早就有人写好了它的 easing function,只要 google 一下马上就能找到如下的程式码:
&&&01public static float Bounce(float t, float b, float c, float d)02{03if ((t /= d) & (1.0f / 2.75)) {04return c * (7.5625f * t * t) + b;05}06else if (t & (2.0f / 2.75)) {07return c * (7.5625f * (t−=(1.5f/2.75f)) * t + 0.75f) + b;08}09else if (t & (2.5f / 2.75)) {10return c * (7.5625f * (t−=(2.25f/2.75f)) * t + 0.9375f) + b;11}12else {13return c * (7.5625f * (t−=(2.625f/2.75f)) * t + 0.984375f) + b;14}15}
然后我们把 EasingDemo 中的 easing function 设定为 Easing.Bounce,马上就能看到弹跳的面板与按钮:
这样的效果是不是比前面慢慢飞进来的动画要生动许多呢?
只要指定起始状态、结束状态、播放时间及 easing function 的种类,即可组合出千变万化的各种效果,因此 easing function 是相当广泛的 2D 动画技术。知名的 JavaScript 函式库 jQuery 也内建了许多不同种类的 easing function。
&Unity 范例场景可以在 这边 。可导入Unity看到范例程式码及实际的动画效果。
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!19:16 提问
unity3d关于自动寻路和animator动画控制,问题我和代码放一起了,求教,谢谢~~~
navMeshAgent的框自己先跑过去目标position了,但navMeshAgent停止后,动画也停止了,导致模型没走到目标位置(方向是对的) 为什么会这样?求指点,谢谢~~
难道是我设置navMeshAgent.updatePosition=false 但这个必须设置, 动画控制,速度和旋转速度都是动态计算的,代码如下
void Awake()
navAgent =GetComponent();
navAgent.destination= Wayspoint[index].//将巡逻的初始位置赋值,目标位置
navAgent.updatePosition =
navAgent.updateRotation =
print(Mathf.Abs((Wayspoint[0].position - Wayspoint[1].position).magnitude ));
private void EnemyAnimator()
float angle = Vector3.Angle(transform.forward, navAgent.desiredVelocity);
if (angle & 90)//如果没有,来判断机器人与期望速度,之间的夹角,如果大于90度的话只进行转身,不运动,所以在这个只把speed设置为0
anim.SetFloat("speed", 0, StoppingTime, Time.deltaTime);
else//小于90度的时候//即目标方向在机器人朝向上的投影,求得实时移动速度,达到平滑过渡目的;走向过程中呈弧形,并慢慢加速
Vector3 project = Vector3.Project(transform.forward, navAgent.desiredVelocity);//在这里这样写是因为如果让他运动的时候,之间有夹角,直接给他赋值速度,他的期望运动路径不发生变化
anim.SetFloat("speed", project.magnitude, StartingTime, Time.deltaTime);
print("speed" + project.magnitude);
Vector3 crossFaction = Vector3.Cross(transform.forward, navAgent.desiredVelocity);//这里利用的是叉乘运算,来判断转身的方向,y值大于0,y值小于0
if (crossFaction.y & 0)
float angleRed = Mathf.Deg2Rad * //这个是把角度转化为弧度
anim.SetFloat("anglarSpeed", angleRed, StartingTime, Time.deltaTime);//这个是把角度转化为弧度,让机器人进行转身运动
按赞数排序
其他相关推荐为什么ugui 做动画position的xy被锁了【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:77,957贴子:
为什么ugui 做动画position的xy被锁了收藏
51CTO学院11年行业品牌,1400万用户选择,中国专业IT技能学习平台,unity能做什么.通过在线学习的方式,帮助广大技术人员实现技能提升,高薪就业的职业梦想,unity能做什么.
只能修改z轴……
求大神帮帮萌新
登录百度帐号推荐应用今天看啥 热点:
【跟我一起学Unity3D】代码中切割图片并且加载帧序列动画,unity3d切割
在Cocos2dx中,对大图的处理已经封装好了一套自己的API,但是在Unity3D中貌似没有类似的API(好吧,实际上是有的,而且功能更强大),或者说我没找到。不过这也在情理之中,毕竟Unity3D是做3D的,要切割图片的地方还是很少的。
因为我用Unity3D主要是用于做2D游戏的(PS:很蛋疼吧?我也觉得),所以就不得不考虑切图和播放序列帧这两个在2D上常见的功能了,下面废话不多说。我的任务是把下面这张图切割成16块,并且按照动画的序列播放出来。
查Unity3D的使用手册的过程中,我发现了一个类:Texture2D,他是继承Texture的,主要是用于创建2D纹理的,非常符合切图的需要。
首先,我们需要加载大图,加载大图有一个非常简单的方法,就是创建一个public的Texture2D类成员变量,然后在编辑器中直接拖动到上去给他赋值就可以了。
当然也可以采用动态加载图片资源的方法,这种方法比较麻烦,需要把图片先转换成二进制流,然后赋值给Texture2D
//加载图片资源
void LoadTexture()
using (FileStream file = File.Open (Application.dataPath + &/Textures/Player.png&, FileMode.Open))
using (BinaryReader reader = new BinaryReader(file))
m_texPlayer = new Texture2D (192, 256, TextureFormat.ARGB4444, false);
texture.LoadImage (reader.ReadBytes((int)file.Length));
加载完之后就要切割了,主要思路就是,两个for循环,一个表示行,一个表示列,然后再循环每个像素点,把每个像素点里面的颜色复制出来给切割的Texture2D,最后把Texture2D组合成一个4x4的矩阵数组。
下面是第一步:
for (int i = 0; i & m_iMinPicColumnC ++i)
for (int j = 0; j & m_iMinPicRowC ++j)
DePackTexture(i, j);
上面的最终处理调用了一个DePackTexture,这个函数是用于实际上的切割的。
void DePackTexture(int i, int j)
int cur_x = i * m_iMinPicW
int cur_y = j * m_iMinPicH
Texture2D newTexture = new Texture2D(m_iMinPicWidth, m_iMinPicHeight);
for (int m = cur_y; m & cur_y + m_iMinPicH ++m)
for (int n = cur_x; n & cur_x + m_iMinPicW ++n)
newTexture.SetPixel(n - cur_x, m - cur_y, m_texPlayer.GetPixel(n, m));
newTexture.Apply();
m_texPlayers[i, j] = newT
} 切图值得注意的就是两点,一点就是找好位置,另一点就是执行完SetPixel操作后一定要执行Apply,不然是没有效果的。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面是帧序列动画,帧序列动画实际上就是将图片按照一定的顺序加载上去,值得注意的是所有的GUI操作一定要放到OnGUI里面。
void DrawAnimation(Texture[,] tex, Rect rect)
//绘制当前帧
GUI.DrawTexture(rect, tex[m_iCurFram, m_iCurAnimation], ScaleMode.StretchToFill, true, 0.0f);
//计算限制帧的时间
m_fTime += Time.deltaT
//超过限制帧切换贴图
if (m_fTime &= 1.0 / m_fFps && m_bStop == false)
//帧序列切换
m_iCurFram = ++m_iCurFram % m_iMinPicRowC
//限制帧清空
m_fTime = 0;
//超过帧动画总数从第0帧开始
if (m_iCurFram &= tex.Length)
m_iCurFram = 0;
然后没有什么了,代码还是很简单的。下面附上全部的代码,这个我做成了一个小的demo,含有动画的开始和暂停功能,而且还有动画的帧速调整的功能。(最后会附上demo的地址)
using UnityE
using System.C
public class CTexture : MonoBehaviour
//大图的人
public Texture2D m_texP
//小图的人
private Texture2D[,] m_texP
private int m_iCurF
//当前动画
private int m_iCurA
//限制帧的时间
private float m_fTime = 0;
//小图的宽和高
public int m_iMinPicWidth = 48;
public int m_iMinPicHeight = 64;
//一行有多少个小图
public int m_iMinPicRowCount = 4;
//一列有多少个小图
public int m_iMinPicColumnCount = 4;
//动画控制
private bool m_bStop =
//一秒多少帧
private float m_fFps = 4;
private string m_sFps = &&;
void Start()
m_texPlayers = new Texture2D[4, 4];
m_iCurAnimation = 0;
m_sFps = m_fFps.ToString();
//加载图片资源
LoadTexture();
for (int i = 0; i & m_iMinPicColumnC ++i)
for (int j = 0; j & m_iMinPicRowC ++j)
DePackTexture(i, j);
void Update()
if(Input.GetKeyDown(KeyCode.A))
m_iCurAnimation = 2;
if (Input.GetKeyDown(KeyCode.S))
m_iCurAnimation = 3;
if (Input.GetKeyDown(KeyCode.W))
m_iCurAnimation = 0;
if (Input.GetKeyDown(KeyCode.D))
m_iCurAnimation = 1;
void OnGUI()
DrawAnimation(m_texPlayers, new Rect(100, 100, m_iMinPicWidth, m_iMinPicHeight));
if(GUI.Button(new Rect(200,20,80,50),&开始/暂停&))
m_bStop = m_bStop == false ? true :
m_sFps = GUI.TextField(new Rect(200, 80, 80, 40), m_sFps);
if (GUI.Button(new Rect(200, 150, 50, 40), &应用&))
m_fFps = float.Parse(m_sFps);
//加载图片资源
void LoadTexture()
using (FileStream file = File.Open (Application.dataPath + &/Textures/Player.png&, FileMode.Open))
using (BinaryReader reader = new BinaryReader(file))
m_texPlayer = new Texture2D (192, 256, TextureFormat.ARGB4444, false);
texture.LoadImage (reader.ReadBytes((int)file.Length));
void DePackTexture(int i, int j)
int cur_x = i * m_iMinPicW
int cur_y = j * m_iMinPicH
Texture2D newTexture = new Texture2D(m_iMinPicWidth, m_iMinPicHeight);
for (int m = cur_y; m & cur_y + m_iMinPicH ++m)
for (int n = cur_x; n & cur_x + m_iMinPicW ++n)
newTexture.SetPixel(n - cur_x, m - cur_y, m_texPlayer.GetPixel(n, m));
newTexture.Apply();
m_texPlayers[i, j] = newT
void DrawAnimation(Texture[,] tex, Rect rect)
//绘制当前帧
GUI.DrawTexture(rect, tex[m_iCurFram, m_iCurAnimation], ScaleMode.StretchToFill, true, 0.0f);
//计算限制帧的时间
m_fTime += Time.deltaT
//超过限制帧切换贴图
if (m_fTime &= 1.0 / m_fFps && m_bStop == false)
//帧序列切换
m_iCurFram = ++m_iCurFram % 4;
//限制帧清空
m_fTime = 0;
//超过帧动画总数从第0帧开始
if (m_iCurFram &= tex.Length)
m_iCurFram = 0;
demo地址:http://download.csdn.net/detail/baijiajie
逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。 因为逐帧动画的帧序列内容不一样,不但给制作增加了负担而且最终输出的文件量也很大,但它的优势也很明显:逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似与电影的播放模式,很适合于表演细腻的动画。例如:人物或动物急剧转身、 头发及衣服的飘动、走路、说话以及精致的3D效果等等。
  C#写法:  // 定义一个手势的枚举  public enum Dir:int  {  Left = 0,  Stop,  Right  }  // C#脚本名为Test.cs  public class Test: MonoBehaviour {  public GameObject _// 挂一个用来显示图片的plane对象  public float duration = 0.5f; // 每0.5秒换一张图片  public Texture2D[] _texA
// 挂30张图片  Dir _touchD
// 当前的手势  float curTime = 0;  int _index = 0;  void Update()  {  // 当运行平台为IOS或Android时  if(Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.Android)  {  // 当输入的触点数量大于0,且手指移动时  if(Input.touchCount & 0 && Input.GetTouch(0).phase == TouchPhase.Moved)  {  if(Input.GetTouch(0).deltaPosition.x & 0 - Mathf.Epsilon)  _touchDir = Dir.L  else  _touchDir = Dir.R  }  // 当输入的触点数量大于0,且手指不动时  if(Input.touchCount & 0 && Input.GetTouch(0).phase == TouchPhase.Stationary)  {  _touchDir = Dir.S  }  }  // 根据手势顺序或逆序换图  if(_touchDir != Dir.Stop)  {  if(_touchDir == Dir.Left)  {  curTime += Time.deltaT  if(curTime & duration)  {  curTime = 0;  _index = _index == 0 ? _texAll.Length - 1 : _  _plane.renderer.material.mainTexture = _texAll[_index--];  }  }  else  {  curTime += Time.deltaT  if(curTime & duration)  {  curTime = 0;  _index = _index == _texAll.Length - 1 ? 0 : _  _plane.renderer.material.mainTexture = _texAll[_index++];  }  }  }  }  }...余下全文>>
相关搜索:
相关阅读:
相关频道:
Android教程最近更新

我要回帖

更多关于 unity3d setposition 的文章

 

随机推荐