Unity3D游戏开发之跑酷游戏项目讲解

一、游戏策划

游戏采用2D界面,角色从左到右奔跑,在路段中随机生成障碍物和金币,玩家需要使用跳跃功能躲开障碍物,在游戏中玩家收集的金币数目越多,奔跑的距离越长,玩家的得分就越高。我们最终实现的界面效果如图所示,首先我们来讲一下游戏的原理,我们这里这里采用的方法是路段固定,移动摄像机的方法。换句话说,当角色开始移动后,摄像机和场景跟随角色缓缓向右移动。当角色跑完每一个路段距离的2/3时,计算下一路段的位置,并在该位置生成一个新的路段,这样在游戏场景中可以产生无限远的路段,当某一路段离开摄像机视野时,立即将其销毁。于此同时,我们在每一个路段上随机产生障碍物和金币,然后对角色做碰撞检测即可。

 

二、角色控制

角色控制这里,我们只关注角色的状态,即角色是处于奔跑状态还是死亡状态。通过这一状态,我们针对角色采取不同的处理方式。如果角色处于奔跑状态,则更新角色位置、摄像机位置、背景位置,否则角色将在被障碍物撞到以后倒地死亡。我们来一起看下面的脚本:

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Player : MonoBehaviour {
  4.     //定义角色移动速度
  5.     public float mMoveSpeed=2.5F;
  6.     //摄像机
  7.     private Transform mCamera;
  8.     //背景图片
  9.     private Transform mBackground;
  10.     //角色是否在奔跑
  11.     private bool isRuning=true;
  12.     //场景中路段总数目
  13.     private int mCount=1;
  14.     //路段预设
  15.     public GameObject CubeWay;
  16.     //死亡动画播放次数
  17.     private int DeathCount=0;
  18.     //收集的金币数目
  19.     private int mCoinCount=0;
  20.     public int CoinCount {
  21.         get {
  22.             return mCoinCount;
  23.         }
  24.     }
  25.     //当前奔跑距离
  26.     private int mLength=0;
  27.     public int Length {
  28.         get {
  29.             return mLength;
  30.         }
  31.     }
  32.     //当前得分
  33.     private int mGrade=0;
  34.     public int Grade {
  35.         get {
  36.             return mGrade;
  37.         }
  38.     }
  39.     void Start ()
  40.     {
  41.         //获取相机
  42.         mCamera=Camera.main.transform;
  43.         //获取背景
  44.         mBackground=GameObject.Find(“Background”).transform;
  45.     }
  46.     void Update ()
  47.     {
  48.         //如果角色处于奔跑状态则移动角色、相机和场景
  49.         if(isRuning)
  50.         {
  51.             Move();
  52.             CreateCubeWay();
  53.             Jump();
  54.             UpdateData();
  55.         }else
  56.         {
  57.             Death();
  58.         }
  59.     }
  60.     /// <summary>
  61.     /// 更新玩家的游戏数据
  62.     /// </summary>
  63.     private void UpdateData()
  64.     {
  65.         //计算奔跑距离
  66.         mLength=(int)((transform.position.x+25)*25);
  67.         //计算玩家得分
  68.         mGrade=(int)(mLength*0.8+mCoinCount*0.2);
  69.     }
  70.     ///角色死亡
  71.     private void Death()
  72.     {
  73.         //为避免死亡动画在每一帧都更新,使用DeathCount限制其执行
  74.         if(DeathCount<=1)
  75.         {
  76.            //播放死亡动画
  77.            transform.animation.Play(“Lose”);
  78.            //次数+1
  79.            DeathCount+=1;
  80.            //保存当前记录
  81.            //PlayerPrefs.SetInt(“这里填入一个唯一的值”,Grade);
  82.         }
  83.     }
  84.     private void Jump()
  85.     {
  86.         //这里不能使用刚体结构,所以使用手动方法实现跳跃
  87.         if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
  88.         {
  89.             while(transform.position.y<=1)
  90.             {
  91.                 float y=transform.position.y+0.02F;
  92.                 transform.position=new Vector3(transform.position.x,y,transform.position.z);
  93.                 transform.animation.Play(“Jump”);
  94.             }
  95.             StartCoroutine(“Wait”);
  96.         }
  97.     }
  98.     IEnumerator Wait()
  99.     {
  100.         yield return new WaitForSeconds(0.8F);
  101.         //角色落地继续奔跑
  102.         while(transform.position.y>0.125F)
  103.         {
  104.             float y=transform.position.y-0.02F;
  105.             transform.position=new Vector3(transform.position.x,y,transform.position.z);
  106.             transform.animation.Play(“Run”);
  107.         }
  108.     }
  109.     //移动角色、相机和场景
  110.     private void Move()
  111.     {
  112.         //让角色从左到右开始奔跑
  113.         transform.Translate(Vector3.forward * mMoveSpeed * Time.deltaTime);
  114.         //移动摄像机
  115.         mCamera.Translate(Vector3.right * mMoveSpeed * Time.deltaTime);
  116.         //移动背景
  117.         mBackground.Translate(Vector3.left * mMoveSpeed * Time.deltaTime);
  118.     }
  119.     //创建新的路段
  120.     private void CreateCubeWay()
  121.     {
  122.         //当角色跑完一个路段的的2/3时,创建新的路段
  123.         //用角色跑过的总距离计算前面n-1个路段的距离即为在第n个路段上跑过的距离
  124.         if(transform.position.x+30-(mCount-1)*50 >=50*2/3)
  125.         {
  126.             //克隆路段
  127.             //这里从第一个路段的位置开始计算新路段的距离
  128.             GameObject mObject=(GameObject)Instantiate(CubeWay,new Vector3(-5F+mCount * 50F,0F,-2F),Quaternion.identity);
  129.             mObject.transform.localScale=new Vector3(50F,0.25F,1F);
  130.             //路段数加1
  131.             mCount+=1;
  132.         }
  133.     }
  134.     void OnTriggerEnter(Collider mCollider)
  135.     {
  136.         //如果碰到的是金币,则金币消失,金币数目加1;
  137.         if(mCollider.gameObject.tag==”Coin”)
  138.         {
  139.             Destroy(mCollider.gameObject);
  140.             mCoinCount+=1;
  141.         }
  142.         //如果碰到的是障碍物,则游戏结束
  143.         else if(mCollider.gameObject.tag==”Rock”)
  144.         {
  145.             isRuning=false;
  146.         }
  147.     }
  148. }

在这里我们需要关注下面的内容:

 

1、Update()方法及Move()、Jump()、CreateCubeWay()、Death()方法,因为这是角色在奔跑过程中的核心控制方法。

2、CreateCubeWay()方法的作用是在玩家跑完每一个路段的2/3时,在指定的位置生成新的路段。假设当前场景中共有n个路段,玩家在每一个路段上奔跑的距离=用玩家从起点到当前位置的长度-前面n-1个路段的距离。通过这种方法我们可以判断玩家在每一个路段上的相对位置。在确定了这个位置后,我们将其与路段长度的2/3比较,如果大于或者等于这个距离,则生成新的路段,且第n+1个路段的位置等于第一个路段的位置+n个路段的总长度。由此,我们就实现了在指定的位置生成新的路段,使场景中源源不断的生成新的路段。

3、玩家收集金币和障碍物的碰撞检测都是在OnTrigger方法中实现的,我们使用了一个bool类型的标识变量isRuning来表示角色的状态,此状态直接影响Update()方法的执行,大家可以从代码中自己去寻找。

4、这里角色的跳跃是通过脚本模拟出来的,因为这里使用刚体似乎不能实现博主想实现的那种效果,大家可以参考Jump()方法。
三、场景布设

这里我们2D平面作为游戏的背景,使用NGUI来显示界面文字内容。在Unity3D场景中使用NGUI需要相机和Anchor设置为同一层级,并设置相机的景深,这样两个相机系统都能工作了。路段CubeWay是一个预设体Cube,负责在CubeWay上生成金币和障碍物,该对象关联在Player脚本上。玩家角色是一个3D的人物模型,最终场景布设效果如图所示:

 

四、预设定义

在这个游戏中需要重用的对象有路段CubeWay、金币Coin、障碍物Rock,我们分别来看他们的脚本:

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. using UnityEngine;
  2. using System.Collections;
  3. public class CubeWay : MonoBehaviour {
  4.     //在道路上显示的金币、障碍物
  5.     public GameObject[] mObjects;
  6.     void Start ()
  7.     {
  8.        //在每段路段上随机产生20到50个物品
  9.        int mCount=Random.Range(20,50);
  10.        for(int i=0;i<mCount;i++)
  11.        {
  12.           Instantiate(mObjects[0],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),1F,-2F),
  13.                         Quaternion.Euler(new Vector3(90F,180F,0F)));
  14.        }
  15.        //在每段路段上随机产生5到10个障碍物
  16.        mCount=Random.Range(5,10);
  17.        for(int i=0;i<mCount;i++)
  18.        {
  19.           Instantiate(mObjects[1],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),0.5F,-2F),
  20.                         Quaternion.Euler(new Vector3(90F,180F,0F)));
  21.        }
  22.     }
  23.     //当离开摄像机视野时立即销毁
  24.     void OnBecameInvisible()
  25.     {
  26.         Destroy(this.gameObject);
  27.     }
  28. }

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Coin : MonoBehaviour {
  4.     //这里是一个控制金币旋转的脚本
  5.     void Update ()
  6.     {
  7.         transform.Rotate(Vector3.forward * 50F * Time.deltaTime);
  8.     }
  9.     //当离开摄像机视野时立即销毁
  10.     void OnBecameInvisible()
  11.     {
  12.         Destroy(this.gameObject);
  13.     }
  14. }

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Rock : MonoBehaviour {
  4.     //当离开摄像机视野时立即销毁
  5.     void OnBecameInvisible()
  6.     {
  7.         Destroy(this.gameObject);
  8.     }
  9. }

其中CubeWay就是一个Cube、Coin是一个圆柱体,为了让金币看起来好看点,我们让金币在空中旋转起来、Rock就是一个平面贴图。这里Rock、Coin将绑定到CubeWay的mObjects。

 

五、游戏管理

最后是界面的数据更新啦,脚本定义如下:

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. using UnityEngine;
  2. using System.Collections;
  3. public class GameManager : MonoBehaviour {
  4.     //游戏界面根节点
  5.     private Transform GameUI;
  6.     //玩家
  7.     private Transform mPlayer;
  8.     //界面金币数及距离
  9.     private Transform mCoins;
  10.     private Transform mLength;
  11.     void Start ()
  12.     {
  13.         GameUI=GameObject.Find(“2DUI”).transform;
  14.         mPlayer=GameObject.Find(“People”).transform;
  15.         mCoins=GameUI.FindChild(“Anchor/Panel/Coins”).transform;
  16.         mLength=GameUI.FindChild(“Anchor/Panel/Length”).transform;
  17.     }
  18.     void Update ()
  19.     {
  20.         mCoins.GetComponent<UILabel>().text=”金币:” + mPlayer.GetComponent<Player>().CoinCount;
  21.         mLength.GetComponent<UILabel>().text=”距离:” + mPlayer.GetComponent<Player>().Length;
  22.     }
  23. }

好了,到现在整个游戏已经讲解完了,相信大家已经迫不及待地想看看最终的效果了,好,我们一起来看看吧:

 

 

 

希望今天的内容大家能够喜欢,希望大家继续支持和关注我的博客,如果我们对今天的例子稍作修改,就可以实现3D版的跑酷,经典的《神庙逃亡》游戏就是基于Unity3D游戏引擎开发的。

 

喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei
转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/25510579

源码下载



发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(Spamcheck Enabled)

最新评论