Unity3D游戏开发之仿仙剑奇侠传仙灵岛机关的实现

 今天我们继续来做点和仙剑相关的东西,首先我们来看一副图:

         这幅图呢,是仙剑奇侠传的第一个迷宫场景——仙灵岛的莲花池。男主角李逍遥为替婶婶求药独闯仙灵岛,在经历了前面的小草妖战斗后,李逍遥就来到了 莲花池,这个迷宫的解法很简单,乘坐莲花池中的芦苇垫到不同的地方,然后用破天锤打碎五座阿修罗像,通往仙灵岛的通路就会被打开,就是在仙灵岛李逍遥邂逅了正在沐浴的赵灵儿,仙剑奇侠传的故事从此展开。好了,故事先说到这里,我们来看这里很重要的一个信息:李逍遥踩着芦苇垫到达不同的地方,然后用破天锤打碎石像开启机关。我们把最终要的东西提取出来的话就是我们可以踩着芦苇垫子到不同的地方去。好,我们今天就来实现一个简化的"仙灵岛"吧!那么怎么做呢?在这篇文章中,我们最终实现的效果是这样的:

        现在呢,让我们把莲花池里的构件做一下抽象:每一个 石柱可以看做是一个寻路节点,芦苇垫子可以看做是绑定了寻路组件的一个GameObject。唯一的区别就在于这里的芦苇垫子是需要我们的角色站在上面才能让它运动的,而我们在这篇文章里的游戏体是自己运动的。好,现在我们开始来实现这个功能吧。我们先创建如下图所示的场景:

       我们在水中布置了8个石柱,两个芦苇垫子,当游戏开始时,玩家控制角色走上芦苇垫子时,芦苇垫子将按照事先设定的路线,将角色送达最后一个石柱位置,此时,玩家可以控制角色到达对岸。当玩家再次踏上芦苇垫子时,芦苇垫子会将角色送回起点位置。当芦苇垫子处于移动状态中时,角色可以向四个方向旋转,活动范围仅限于芦苇垫子上。好,交待清楚了场景,我们下面来讲解原理:

      

       基于以上两个原理,我们下面来编写今天的脚本:

[csharp] view plaincopyprint?
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class TransportScript : MonoBehaviour {  
  5.       
  6.     //寻路组件节点  
  7.     public Transform[] mPaths;  
  8.     //芦苇垫传送器  
  9.     private Transform mTransportor;  
  10.     //被传送的角色  
  11.     public Transform mTransportPlayer;  
  12.       
  13.     //起点  
  14.     Vector3 StartPoint=new Vector3(0F,0.5F,-13F);  
  15.     //终点  
  16.     Vector3 EndPoint=new Vector3(0F,0.5F,10F);  
  17.       
  18.     //定义移动的方向类型:从起点到终点为0,从终点到起点为1  
  19.     private int MoveType=0;  
  20.     //定义移动状态的标志变量  
  21.     private bool isMoving=false;  
  22.       
  23.     //存储寻路组件设置的哈希表  
  24.     private Hashtable args=new Hashtable();  
  25.       
  26.     void Start ()   
  27.     {  
  28.         //获取传送器  
  29.         mTransportor=this.transform;  
  30.   
  31.         //初始化寻路插件  
  32.         Hashtable args = new Hashtable();  
  33.         //设置路径的点  
  34.         args.Add("path",mPaths);  
  35.         //设置类型为线性,线性效果会好一些。  
  36.         args.Add("easeType", iTween.EaseType.linear);  
  37.         //设置寻路的速度  
  38.         args.Add("speed",2.5f);  
  39.         //移动的整体时间。如果与speed共存那么优先speed  
  40.         args.Add("time",10f);  
  41.         //是否先从原始位置走到路径中第一个点的位置  
  42.         args.Add("movetopath",true);  
  43.         //延迟执行时间  
  44.         args.Add("delay", 0.1f);  
  45.         //移动的过程中面朝一个点  
  46.         args.Add("looktarget",Vector3.up);  
  47.         //三个循环类型 none loop pingPong (一般 循环 来回)    
  48.         args.Add("loopType", "pingPong");  
  49.         //是否让模型始终面朝当面目标的方向  
  50.         //如果你发现你的模型在寻路的时候时钟都是一个方向那么一定要打开这个  
  51.         args.Add("orienttopath",true);  
  52.       
  53.         iTween.MoveTo(gameObject,args);  
  54.         iTween.Pause();  
  55.     }  
  56.       
  57.     void  Update()  
  58.     {  
  59.        //如果当前处于停止状态则暂停动画  
  60.        if(isMoving==false)  
  61.        {  
  62.           iTween.Pause();  
  63.        }  
  64.   
  65.        //从起点到终点的控制  
  66.        if(MoveType==0 && mTransportor.position!=EndPoint && isMoving==true)  
  67.        {  
  68.           //未到达终点则继续运动  
  69.           mTransportPlayer.position=mTransportor.position;  
  70.        }else if(MoveType==0 && mTransportor.position==EndPoint)  
  71.        {  
  72.           //到达终点则暂停运动  
  73.           iTween.Pause();  
  74.           isMoving=false;  
  75.           MoveType=1;  
  76.        }  
  77.           
  78.        //从终点到起点的控制  
  79.        if(MoveType==1 && mTransportor.position!=StartPoint && isMoving==true)  
  80.        {  
  81.           //未到达终点则继续运动  
  82.           mTransportPlayer.position=mTransportor.position;  
  83.        }else if(MoveType==1 && mTransportor.position==StartPoint)  
  84.        {  
  85.           //到达终点则暂停运动  
  86.           iTween.Pause();  
  87.           isMoving=false;  
  88.           MoveType=0;  
  89.        }  
  90.          
  91.     }  
  92.       
  93.     //当角色走上芦苇垫的时候开始移动动画  
  94.     void OnTriggerEnter(Collider mCollider)  
  95.     {  
  96.         if(mCollider.gameObject.name=="Samuzai")  
  97.         {  
  98.              
  99.            if(isMoving==false)  
  100.            {  
  101.               isMoving=true;  
  102.               iTween.Resume();  
  103.            }  
  104.         }  
  105.     }  
  106. }  


        在上面的代码中,我们需要把握以下几点:

        1、在Start()方法中,我们主要完成的是寻路组件的初始化,这里我们将寻路动画设置为来回,然后通过Pause()、Resume()方法两个方法来控制动画的播放,因为iTween没有提供在Update()中实现动画播放的方法,iTween只支持部分方法在Update()方法中使用,具体的大家可以自己去了解iTween的API文档。

        2、我们主要通过isMoving标志来标记当前的状态,使用OnTriggerEnter()方法来判断角色是否走上了芦苇垫子,当角色走上芦苇垫子上时,就开始播放寻路动画。当到达起点/终点时,寻路动画即停止。当角色再次走上芦苇垫子时,再次开始寻路动画。

       3、我们再Update()方法中通过改变角色的位置实现了角色和芦苇垫子的同步移动,当到达起点/终点时,寻路动画即停止,直到下一次被触发。

       4、触发与碰撞的区别在于触发不会产生力的作用,可以通过OnTriggerEnter/OnTriggerStay/OnTriggerExit方法分别监听触发开始、触发中、触发结束。要使用Trigger需要勾选碰撞器的isTrigger选项。具体的区别我会在后面的文章中为大家做讲解。

     

更多精彩请到http://www.gopedu.com/

 

 

       这篇文章中用到的东西就是这么多,主要的难点是寻路动画的控制,由于官方没有提供有关的方法,所以我们只能采用Pause()、Resume()方法来控制角色的动画。最后我们来一起看看实现的效果吧,是不是有仙灵到的感觉呢?呵呵

      

posted on 2014-09-22 14:08  狗刨学习网  阅读(1275)  评论(1编辑  收藏  举报