最近在做一个小Demo,用到ITween来完成部分动画的功能,令我苦恼的是ITween的执行过程让我很无奈,源代码片断如下:
//OnMouseUpAsButton()是Unity提供的点击方法
public void OnMouseUpAsButton(){
//点击之后左边的门向右移动,右边的门向左移动,是关门的动画
iTween.MoveTo (leftDoor,new Vector3(-2.26f,0f,-0.1f),1.0f);
iTween.MoveTo (rightDoor,new Vector3(2.26f,0f,-0.1f),1.0f);
//之后,左边的门向左移动,右边的门向右移动,是开门的动画
iTween.MoveTo (leftDoor,new Vector3(-6.0f,0f,-0.1f),1.0f);
iTween.MoveTo (rightDoor,new Vector3(6.0f,0f,-0.1f),1.0f);
}
我原先以为它会按照我想的去移动,至少也是移动有先后顺序,上面的语句执行完了才能执行下面的语句,但是事实上,这四行代码不是四秒运行完的,而是在同一秒中运行完毕,所以没有动画。
就像我现在往一个空篮子中捡鸡蛋,我想把鸡蛋全都捡到篮子里之后,再捡出来,现在却是你在把鸡蛋捡进篮子的同时,旁边还有个熊孩子正在往外捡鸡蛋,所以到头来,篮子里还是没有鸡蛋。
遇到这种情况怎么办呢?那就是你要告诉这个孩子:等我把鸡蛋全捡到篮子里之后,你再往外捡。
那么我们就知道了:要告诉Unity,关门的动画完成之后才能开始开门的动画。
怎么告诉呢?
网上给的答案有些模棱两可,不是很清晰,现在以我的项目为例给出详细的解决方法:
首先大家要了解的一件事就是ITween的MoveTo()等方法里的参数不仅仅是(目标物体,目标位置,事件),更多的动画控制存在一张自定义的哈希表中。哈希表中有一个重要的参数就是回调函数。
ITween为我们提供了三个回调函数:onstart、onupdate和oncomplete。为什么函数后面没有带括号,我们等下说。
它们的意思分别是:在当前动画开始执行的时候执行、在当前动画执行的每一帧中执行、在当前动画执行完成后执行。
那么我们本例中理所当然就用到了最后一种。
接下来看看怎么用:
using UnityEngine;
using System.Collections;
public class StartIntferface : MonoBehaviour {
//下面四个使我们要操作的对象,分别是logo、按钮、左边的门、右边的门
public GameObject logo;
public GameObject Btn;
public GameObject leftDoor;
public GameObject rightDoor;
//为OnComplete()方法制定物体,详情见下方
public GameObject completeObject;
//分别给两个门声明一个哈希表,哈希表中当然存储的就是控制动画的信息了
Hashtable leftDoorClose=new Hashtable();
Hashtable rightDoorOpen=new Hashtable();
// Use this for initialization
void Start () {
//在Start ()中为哈希表添加信息属性
leftDoorClose.Add ("time",1.0f);//门关闭所需的时间
leftDoorClose.Add ("position",new Vector3(-2.26f,0f,-0.1f));//门最终的位置(门要移到什么地方去)
leftDoorClose.Add ("oncomplete","OnComplete");//动画完成后执行什么方法,OnComplete在下面
leftDoorClose.Add ("onCompleteTarget",completeObject);//这个属性看代码下方
//上面是左边的门,下面是右边的门,因为它们要移动的位置不同,所以不能共用一个哈希表
rightDoorOpen.Add ("time",1.0f);
rightDoorOpen.Add ("position",new Vector3(2.26f,0.0f,-0.1f));
rightDoorOpen.Add ("oncomplete","OnComplete");
rightDoorOpen.Add ("onCompleteTarget",completeObject);
//游戏一开始logo平移下来
iTween.MoveTo (logo,new Vector3(0,1.5f,0),1.0f);
iTween.MoveTo (Btn,new Vector3(0,3.2f,-0.9f),0.5f);
}
// Update is called once per frame
void Update () {
}
//OnMouseUpAsButton()这个方法是Unity官方提供的响应交互方法,当前脚本给了谁,鼠标点击那个物体,响应这个方法(前提是物体加了Collider或者GUIElement组件)
public void OnMouseUpAsButton(){
//方法的一开始是对logo和按钮的简单操作
iTween.MoveTo (logo,new Vector3(0,4.463f,0),1.0f);
iTween.MoveTo (Btn,new Vector3(0,0.0f,-0.9f),0.5f);
//这里是ITween根据哈希表中的信息对目标物体进行操作
iTween.MoveTo (leftDoor,leftDoorClose);
iTween.MoveTo (rightDoor,rightDoorOpen);
}
//上面的leftDoorClose.Add ("oncomplete","OnComplete")和rightDoorOpen.Add ("oncomplete","OnComplete")中用到的方法就是这个OnComplete()方法。当然了你也可以定义成别的名称
private void OnComplete(){
//这里就是开门的动画咯
iTween.MoveTo (leftDoor,new Vector3(-6.0f,0f,-0.1f),1.0f);
iTween.MoveTo (rightDoor,new Vector3(6.0f,0.0f,-0.1f),1.0f);
}
}
好了,代码就写完了,但是要回头解释一下:leftDoorClose.Add (“onCompleteTarget”,completeObject)这句是什么意思呢?
字面意思是onComplete的目标物体,那么为什么会有这个东西呢?
用过ITween的同学都知道,把物体S从A移动到B位置,物体S身上会多一个ITween的脚本,有了这个脚本它才会移动,移动完成后就会移除,物体S从A移动到B位置之后,根据需要会选择性执行onComplete方法,所以物体S身上可能还会被ITween加上一个onComplete脚本,但是物体S在执行onComplete脚本的时候会发现:哎,我身上没有onComplete()方法啊,我是被控制的物体,onComplete()方法在控制我移动的那个物体身上啊。
因此,我们就要为onComplete()指定它所在的物体,这也是我们为什么定义了一个completeObject物体的原因。
我们回到unity,把上面这个StartIntferface脚本拖给StartBtn物体,为什么要拖给它?因为OnMouseUpAsButton方法呀,我点击开始按钮的时候响应,那么这个方法只能放在我要点击的物体上:
大家可以对比一下,看看物体的对应关系:
有的朋友会问:这里只是两个动画之间的过渡,那么我有三个甚至更多个怎么办呢?
方法类似嘛:
我们在OnComplete()方法中写了很简单的两个MoveTo,这个MoveTo里面同样可以填上复杂的哈希表,哈希表中的oncomplete指向另一个方法比如OnComplete2(),就好啦,同样的还可以有OnComplete3()、OnComplete4()、OnComplete5()嘛。
好了,完整的小demo就是这样啦,这里值得注意的就是哈希表的使用和onComplete方法以及为onComplete方法指定物体。
文章中有不足之处,恳请大家留言指出批评,谢谢!!