Unityunity倒入动画的问题bool问题

程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之在项目中使用Unity4新Mecanim动画(五十三)
Unity3D研究院之在项目中使用Unity4新Mecanim动画(五十三)
围观43353次
编辑日期: 字体:
Unity4的Mecanim动画很早以前就有体验过,迟迟没有加到项目中有两个原因,今天写这篇博客来记录我在做的过程中遇到的一些问题。
1.以前的代码代码量比较多,修改起来动的地方太多了。
2.使用Mecanim动画,还得需要美术的动画做配合才行。
在3.x中播放动画的时候使用Play()或CrossFade(),直接播放动画 或淡入淡出播放动画。
animation.Play("name"); animation.CrossFade("name");
也可以使用队列播放,让动画形成一个队列。
animation.PlayQueued("name"); animation.CrossFade("name1");
我举一个我现在项目的例子。主角攻击敌人是一套连招,连招一共分为4套动画。也就是当玩家连续按下4次攻击键时这四套动画是连续播放的,假如玩家只连续按下2次攻击,可能只会播放前两套动画。代码中你需要判断其中某个动画是否播放完毕,只有播放完毕才能继续播放下一个动画。
if(animation.isPlaying)
if(animation.IsPlaying("attack1"))
大家在仔细想想这个命题,我们可以把动画分成4中可能的队列,也只可能分为这几种队列。
站立动画- 》攻击动画0 -》站立动画
站立动画- 》攻击动画0 -》攻击动画1 -》站立动画
站立动画- 》攻击动画0 -》攻击动画1 -》攻击动画2-》站立动画
站立动画- 》攻击动画0 -》攻击动画1 -》攻击动画2-》攻击动画3-》站立动画
此时如果用unity3以前的动画方式,无非就是上面这几种方法加上一些逻辑判断完成。现在Unity4加入了Mecanim动画,可以很好的帮我们解决这个问题。详细的动画使用教程我就不多说了,网上已经有很多人写过了。
如下图所示,以前我们在使用模型的时候。一个原始模型,原始模型中没有动画。然后是动画模型,每一个动画都会依赖原始模型。动画的名称末尾用 名称 + @name来表示。 这样的做法使用起来非常方便,但是由于每一个动画都会依赖原始模型所以文件会非常大。
Unity4已经将默认模型与动态导入的类型做了修改,你会发现你的模型拖拽入Hierarchy视图中没有Animation组件而是Animator组件。如果你还是想在Unity4中使用以前的动画系统。你需要把每个模型和动画的类型改成 Rig-& Animation Type -& Legacy,如下图所示。
手动的改起来会非常的累。建议你将下面这条脚本放在项目Editor文件夹下(没有创建一个)。这样当你将模型或动画拖入Project视图中,程序会自动帮你修改它的类型,显然Unity已经不建议大家继续使用以前的动画系统了。
12345678910
using UnityEditor;&public class MyEditor : AssetPostprocessor{&&&&public void OnPreprocessModel()&&&&{&&&&&&&&ModelImporter modelImporter = (ModelImporter) assetImporter;&&&&&&&&
modelImporter.animationType = ModelImporterAnimationType.Legacy;&&&&}&& }
下面开始说说新的动画。在Animations选项卡中先勾掉Import Animation 点击Apply。如下图所示,在Rig选项卡中修改Animation Type的类型为Humanoid。 如果你希望现在选择的这个模型做为标准模型的话,在Avatar Definition中选择Create From This Model。点击下方的Configure可以预览你的骨骼。
让美术修改一下以前的动画,将动画中的原始模型去掉,这样还可以减少文件的大小。然后在Porject视图中找一个原始模型拖拽入右侧Preview中,可以看到这个模型已经播放奔跑动画。
此时换一个模型拖入同样可以预览奔跑效果。
如下图所示,在动画的.fbx中 因为动画需要用刚刚生成的骨骼。所以这里Avatar Definition中你需要选择Copy From Other Avatar 。在Source中选择刚刚生成的Avatar 以后所有动画都需要这样来设置。。
下面我们来让这个女模型和男模型共用男模型的那一套动画,在游戏视图中播放。在Project视图中选择Crate-&AnimatorController。然后把Project中男模型和女模型都拖拽入Hierarchy视图中。 将刚刚创建的AnimatorController放置在Controller处。
此时在Unity导航菜单栏中选择Window -》 Animator。 将动画文件拖入Animator窗口中,你会发现两个模型都开始发生运动。如下图所示,黄颜色表示它为原始动画,也就是根动画。用箭头将它们一一前后相连,箭头实际上就是动画播放的条件。请注意看图中两个蓝色的箭头,A播放完后将会播放B动画,可是B却对应了两个箭头,也就是说B播放完后可以播放C也可以回过头来播放A。
那么B播放完到底是播放C还是播放A呢?用鼠标点击一下箭头,看看这这两个箭头的条件吧。分别点开BA 和BC的两个箭头,在右侧监测面板视图中你都会发现Conditions下有一个Exit Time的条件。根据动画的不同对应数值也会不同,我的数值是0.94。也就是当B动画播放0.94s后将播放下一个动画。默认BA和BC的动画时间是一样的,Unity会有限选择下一个动画,也就是A -》 B-》-》C-》D-》A这样循环播放下去。假设我现在需要动画是 A-》B-》A这样循环播放,只需要修改一下BA箭头的条件,将Exit Time改小一点只要比BC箭头上的小就可以。。 其它的播放虚列原理类似。。
接着还有问题了,用时间来做动画切换的条件是不是有点太限制了。Animator还支持自定义条件,在Animator窗口的左下角处,点击“+”按钮就可以添加变量。这里我添加三组变量, float 、int、bool。
变量添加完毕后,继续点击箭头的条件,箭头上可以有一个条件 或者多个条件。如果是多个条件需要多个条件同时满足才可以。 Conditons左键是变量名称,中间是变量条件,右边是变量值。
Greater 表示左边变量大于右边时触发
Less 表示左边变量小于右边时触发
Equals 表示左边变量等于右边时触发
NotEquals表示左边变量不等于右边时触发。
int 变量上述四种都有,float变量只有Greater 和Less, bool变量只有true和false。
此时我们在加深一下理解。选择AB的箭头,也就设置A动画切换B动画的条件。
5 表示 当ft的值大于5的时候触发。
3 表示 当 it的值小于3的时候触发。
表示 当ib的值等于true的时候触发。
只有上述三种条件全部达成时将A动画将切换播放B动画。否则将一直停留在播放A动画处。
那么ft it ib的这三个变量到底在那里设置呢?如下图所示,才记得前面我们创建的三个变量吗? 这三个变量对应的值就是右边的 0.0 0 false 。在编辑器中你可以通过修改这三个数值来满足播放动画的条件。可是在代码中怎么办呢?
在代码中你可以这样来设置或变更它们的条件。 如果说你需要在程序中判断当前动画的一些信息,可以使用 GetCurrentAnimatorStateInfo(0),我查了一下Animator不能直接拿到当前播放动画的名称, 只能拿到它对应的Has值,也就是说你需要将原始的动画名称转换成Hash来判断。
1234567891011121314151617181920212223242526272829303132333435363738
using UnityEngine;using System.Collections;&public class NewBehaviourScript : MonoBehaviour {& private Animator animator ; void&&Start() {
//得到Animator对象
animator = GetComponent&Animator&(); }& void OnGUI() {
if(GUILayout.Button("play",GUILayout.Width(50)))
&&&&//在这里设置变量的条件
animator.SetFloat("ft",6f);
animator.SetInteger("it",2);
&&&&animator.SetBool("ib",true);&
} }& void Update() {
AnimatorStateInfo animatorState = animator.GetCurrentAnimatorStateInfo(0);&
if(animatorState.IsName("Base Layer.Run_FastStop_Idle"))
Debug.Log("动画相等");
Debug.Log("动画不等");
另外Mecanim还支持多个动画的混合。目前Mecanim还有一个最大的难题,也是文章最上面我说的需要美术配合的那部分。之前我们看到的动画都是应用于人型模型,也就是说它支持人形的骨骼, 举个例子我们的项目人和武器是两个骨骼,这样在用Mecanim就悲剧了。因为不同模型武器的骨骼不一样所以公用模型的话会出现武器位置不对的情况。最后我想到的办法就是美术将以前做的武器骨骼重新导出,每个人对应一套自己武器骨骼(或者一些特殊的骨骼)最后生成武器的动画 ,比如 站立动画、攻击动画、死亡动画等。当Mecanim播放动画的时候,同时在播放该模型对应的武器动画,我想这样就可以解决这个问题吧。。
最后欢迎大家一起讨论。。
今天有朋友QQ上问了我已下,是不是非人形动画还得使用老的动画系统?如下图所示,当你把模型导入Unity的时候,这里可以选择它的类型。
legacy:是老的动画系统,这里就多说了。
Generic:是新的动画系统,它就是支持非人形的动画,建议使用它。但是它不能向Humanoid重定向动画。
Humanoid:就是新的人形重定向动画系统。
本文固定链接:
转载请注明:
MOMO与MO嫂提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!Unity3D研究院之代码使用IK动画(五十五) - 推酷
Unity3D研究院之代码使用IK动画(五十五)
& & & & &IK动画全名是Inverse Kinematics 意思是反向动力学,就是子骨骼节点带动父骨骼节点运动。比如跳街舞的少年用手撑着身体在地上转圈,手就是子骨骼,胳膊身体就是它的父骨骼,这时运动手就需要带动胳膊身体来移动。
&IK动画可以在3DMAX 或者Maya中制作(不在本篇的讨论范围内),本篇我么说说在程序中如何动态调用IK动画。IK动画需要使用Unity4新版的动画系统,如果对新版的动画系统不是很了解的朋友建议看看上一篇。
& & & & & 如下图所示,设置模型的骨骼并且给模型添加AnimatorController控制器。如果不会添加详细请看上一篇文章。
在Unity导航菜单栏中打开Window-&Animator打开动画控制器窗口,在这里勾选IK Pass。
代码方面直接使用API中的,我懒得写了,我给大家详细的解释一下。
using UnityE
using System.C
[RequireComponent(typeof(Animator))]
public class IKCtrl : MonoBehaviour {
//动画控制
protected A
//是否开始IK动画
public bool ikActive =
//右手子节点参考的目标
public Transform rightHandObj =
void Start ()
//得到动画控制对象
animator = GetComponent&Animator&();
//a callback for calculating IK
//它是回调访法。
//前提是在Unity导航菜单栏中打开Window-&Animator打开动画控制器窗口,在这里必须勾选IK Pass!!!
void OnAnimatorIK()
if(animator)
//if the IK is active, set the position and rotation directly to the goal.
//即或IK动画后开始让右手节点寻找参考目标。
if(ikActive)
//weight = 1.0 for the right hand means position and rotation will be at the IK goal (the place the character wants to grab)
//设置骨骼的权重,1表示完整的骨骼,如果是0.5哪么骨骼权重就是一半呢,可移动或旋转的就是一半,大家可以修改一下参数试试。
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1f);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1f);
//set the position and the rotation of the right hand where the external object is
if(rightHandObj != null)
//设置右手根据目标点而旋转移动父骨骼节点
animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
//if the IK is not active, set the position and rotation of the hand back to the original position
//如果取消IK动画,哪么重置骨骼的坐标。
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);
& & & & &如下图所示,图中哪个小球就是子节点参考的目标。,在Scene视图中移动哪个小球,你会发现主角的右手开始IK动画。
上面代码中我们IK的是主角的右手,实际上IK动画支持两个手和两个脚。
// AvatarIKGoal.RightHand 右手
// AvatarIKGoal.LeftHand
// AvatarIKGoal.LeftFoot
// AvatarIKGoal.RightFoot 右脚
animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
OK!快快用代码来动态的制作你的IK动画吧,欢迎一起讨论技术,如有疑问请留言给我哇咔咔~
已发表评论数()
&&登&&&录&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之Time.timeScale、游戏暂停(七十四)
Unity3D研究院之Time.timeScale、游戏暂停(七十四)
围观16437次
编辑日期: 字体:
项目里面一直在用Time.timeScale来做游戏的 1倍 2倍整体加速,今天我仔细看了一下Time.timeScale才发现之前我理解错了一些东西。
Time.timeScale可以控制Update 和LateUpdate 的执行速度,举个例子说明一下。
Time.timeScale=1时,Update、LateUpdate、FixedUpdate 都按正常的时间来执行。
Time.timeScale=2时,Update和 LateUpdate的执行速度是之前的2倍,而FixedUpdate还是按正常时间来执行。
Sorry上面红色这部分确实是写错了,感谢网友在留言处给我的指正,谢谢。
正确的应该是timeScale不会影响Update和LateUpdate的执行速度。因为FixedUpdate是根据时间来的,所以timeScale只会影响FixedUpdate的速度。 再次抱歉。。 谢谢热心网友给我的指正。。 因为我的项目里在处理战斗部分的时候 大量使用 iTween 所以
3 倍加速 或者暂停 的功能直接修改timeScale 。
Time.timeScale也误导了我很久,为什么这么说呢?我原先一直以为Time.timeScale = 0 的话所有的Update都不执行了。今天测试了一下发现原来不是这样的,无论Time.timeScale 等于多说Update和LateUpdate都会去执行,不信你可以自己做个实验看看。
Time.timeScale还会影响Time.time的时间,比如Time.timeScale = 2的话,那么Time.time的增长速度也会变成2倍速度。如果你想取到游戏的实际时间,那么使用Time.timeSinceLevelLoad就可以,前提是必须在Awake()方法以后再取,如果在Awake()方法里面取Time.realtimeSinceStartup会取出一个错误的值,在Start方法里面取的话就正常了。
总之一句话Time.timeScale影响的是Unity的游戏时间缩放比例。Unity里面所有跟时间有关系的东西都是根据timeScale来演算的。仔细想想现在的手游就是个 动画 和 粒子技能特效 还有UI位移特效,所以改他们的速度直接用Time.timeScale就可以完成。还有一个重要的东西就是人物移动 或者 技能移动的速度了, 根据时间的公式,时间 = 路程\速度 ,比如角色从起点跑到中间的一个预期时间, 或者一个技能的火球从攻击到打中目标的预期时间。 凡是处理时间的东东全用Time.time 这样就可以完美让Time.timeScale控制你的游戏了。
下面说说两个大家伙比较关心的话题。
1.游戏暂停
设置 Time.timeScale = 0;即可让游戏暂停。 其实我们暂停的主要是 人物动画,还有技能特效,比如一个火球打了一半。UI方面往往我们不希望暂停,比如暂停界面 有一些UI位移动画或者帧动画, 或者最起码要有个“取消暂停的按钮” 吧。 总不能游戏暂停了我点击按钮 按钮的点击动画 或者特效也暂停了吧。
所有的动画都是基于时间来的,因为Time.timeScale = 0了,所以Time.time也就不会在变化了。换句话来说如果游戏暂停以后想在暂停界面上继续播放一些不受Time.timeScale 影响的动画,那么我们就需要用到Time.realtimeSinceStartup
如果你的项目NGUI的版本还算比较新的话,你会发现在UITweener.cs处理UI动画的基类里面已经增加了一个属性叫public bool ignoreTimeScale = 它就是控制控制NGUI 的UI动画是否受到ignoreTimeScale影响。如下图所示,你可以看看NGUI在Update里面的实现,它也是根据时间来判断的。忽略timescale的话就用真实时间,不忽略的话就用Time.time 和Time.deltaTime。
2.如何让游戏中某个游戏对象不受Time.timeScale影响。
动画不受timeScale影响:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
static IEnumerator Play( Animation animation, string clipName, bool useTimeScale,System.Action onComplete ) {
if(!useTimeScale)
AnimationState _currState = animation[clipName];
bool isPlaying = true;
float _startTime = 0F;
float _progressTime = 0F;
float _timeAtLastFrame = 0F;
float _timeAtCurrentFrame = 0F;
float deltaTime = 0F;
animation.Play(clipName);
_timeAtLastFrame = Time.realtimeSinceStartup;
while (isPlaying)
_timeAtCurrentFrame = Time.realtimeSinceStartup;
deltaTime = _timeAtCurrentFrame - _timeAtLastFrame;
_timeAtLastFrame = _timeAtCurrentFrame;
_progressTime += deltaTime;
_currState.normalizedTime = _progressTime / _currState.length;
animation.Sample ();
if (_progressTime &= _currState.length)
if(_currState.wrapMode != WrapMode.Loop)
isPlaying = false;
_progressTime = 0.0f;
yield return new WaitForEndOfFrame();
yield return null;
if(onComplete != null)
onComplete();
animation.Play(clipName);
粒子特效不受timescale影响
12345678910111213141516171819202122232425262728293031
using UnityEngine;using System.Collections; public class ParticaleAnimator : MonoBehaviour {&& private void Awake() {
particle = GetComponent&ParticleSystem&(); }
// Use this for initialization void Start () {
lastTime = Time.realtimeSinceStartup; }
// Update is called once per frame void Update ()
float deltaTime = Time.realtimeSinceStartup - (float)lastTime; &&&&&&&& particle.Simulate(deltaTime, true, false); //last must be false!! &&&&&&&& lastTime = Time.realtimeSinceStartup; }
private double lastTime; private ParticleSystem particle; }
经过我的测试发现timeScale = 0 时, 播放放粒子特效,效率上有很大问题非常的卡。
举个例子啊,刀塔传奇大家都玩过吧?某个角色放技能的时候,其他所有人物动作全部暂停,并且打出去的技能也暂停。等着角色的技能全部放完,别人才恢复正常。 我觉得向做这类游戏,最好就不要 利用timeScale了,不然写起来太蛋疼了。 不过刀塔传奇也没有 1 倍 2倍
3倍速 的功能吧,呵呵。
3.timeScale变化时的声音。
当声音播放的同时去修改timescale的数值你会发现声音播放的很奇怪。如下代码所示,你可以封装一个方法,把IgnoreTimeScale作为参数传进去, 如果忽略timescale的话那么速度就应该是1否则就应该是Time.timeScale。
//添加一个声音组件AudioSource source = gameObject.AddComponent&AudioSource&();//设置播放声音的速度。 默认速度是1 ,那如果我们加速了,那就应该是 Time.timeScalesource.pitch =IgnoreTimeScale?1:Time.timeScale;//播放声音source.Play();
此时如果修改了Time.timeScale的数值的话,那么正在播放中的声音会非常奇怪。所以当每次播放音频的时候我们需要记录一下这个音频的状态,它是否需要忽略timeScale当前的数值。
//创建一个音频的字典private static Dictionary&AudioSource,bool&soundList = new Dictionary&AudioSource, bool&();&//播放声音source.Play();&//把音频对象加入字典中,value 就是是否忽略timescalesoundList.Add(source,IgnoreTimeScale);
每当timeScale变化的时候调用一下下面这个方法。就是遍历一下当前保存的所有音频对象,从新设置一下他们的播放频率。
12345678910
&&&&public static void TimeScaleChanged()&&&&{
foreach (AudioSource source in soundList.Keys)&&
if(source != null)
source.pitch = soundList[source]?1:Time.timeScale;
如果你有更好的建议,欢迎在下面给我留言,谢谢。
本文固定链接:
转载请注明:
MOMO与MO嫂提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!请问各位UNITY里BOOL与EBOOL的区别等几个问题.
>> 请问各位UNITY里BOOL与EBOOL的区别等几个问题.
请问各位UNITY里BOOL与EBOOL的区别等几个问题.
kantion, 16:29:05
&& 大家好,在下是用UNITY的新手,因为从入行开始就一直用的是西门子STEP7,所以觉得STEP7无比亲切.现在有个新工程要用UNITY了,感觉有很多不习惯的地方.有几个不懂的地方望大家指教.
1.UNITY里的布尔变量有BOOL和EBOOL,其中它们的区别在手册上说的是EBOOL&另外还包含关于对上升沿或下降沿以及强制进行管理的信息&,但是在模拟器上试的时候发现用BOOL格式的布尔变量照样可以做强制啊.那么是否可以认为就用EBOOL就够了吧,BOOL就没必要用了?
2.另外论坛里有位朋友发过一个四台泵轮换的程序,模拟量块里面对模拟量做了这么个处理:CE_LIANG_ZHI:=REAL_TO_INT(INT_TO_REAL(LIANG_CHENG)/10000.0*INT_TO_REAL(CGQ_SHU_RU))+JIAO_LING;也就是测量值=量程/10000*输入值+校零值.我不懂的是从模块那边上来的就是INT了,为什么要转成REAL来算,算完了又转成INT呢?INT应该是保存不了小数位的吧,这有意义吗?在数据编辑器里不是可以把从模拟量通道过来的量直接定义格式为REAL吗?另外模块通道那里不是可以配置转换比例0%~100%对应0~10000吗,如果我的仪表量程比如变频器频率最高是50HZ,那么我在采频率时可以直接设置成0%~100%对应0~50就可以了吧.
暂时只有以上两个小问题,请大家帮忙指教一下.谢谢!gaoxiao, 16:58:36
BOOL只占用一个位,而EBOOL实际是占用了一个字节
BOOL不能取上升沿下降沿,EBOOL可以取上升沿下降沿
如果你用EBOOL很多,并且程序量很大的话,会耗费大量系统资源gaoxiao, 17:01:17
量程转换的时候是可以转成实数使用的,例子中为什么又转成整数,估计是因为他的SCADA与PLC通讯不支持实数,这样他就只能再转换成整数了PTNJ0, 09:34:57
[QUOTE][B]下面引用由[U]gaoxiao[/U]发表的内容:[/B]
量程转换的时候是可以转成实数使用的,例子中为什么又转成整数,估计是因为他的SCADA与PLC通讯不支持实数,这样他就只能再转换成整数了[/QUOTE]
也可以保证精度wmq-12 14:29:56
这样啊,学习啦hejibing, 14:37:37
终于明白BOOL与EBOOL的区别了,谢谢2楼的。请问各位UNITY里BOOL与EBOOL的区别等几个问题.
hsbeyond, 17:08:33
明白了一点,非常感谢!&97
8: 此主题共有6帖 此页7帖 每页12帖&

我要回帖

更多关于 unity动画教程 的文章

 

随机推荐