今天的博客的主题就是《Unity3D游戏开发之跑酷游戏项目讲解》。
从我们自身来考虑这件事情,当你选择做自己热爱的事情的时候,你的内心一定是充满激情和勇气的,你愿意看到自己的努力,你愿意看到自己的付出,我们成长是为了促进自我对认知的不断完善,所以我们应该以一种虔诚、谦恭的态度来对待我们的生命,我们或许无法选择出身,但我们可以选择向自己喜欢的生活去努力。或许我和这些人真的不是一个世界的人吧,很多事情在今天都给出了结局,对于这种人我已经没有再尝试与之交流的想法了,或许大学四年平平淡淡,留给我的只有自己才能体会的孤独吧。好了,不说我的事情了,我们正式开始今天的内容吧!
一、游戏策划
游戏采用2D界面,角色从左到右奔跑,在路段中随机生成障碍物和金币,玩家需要使用跳跃功能躲开障碍物,在游戏中玩家收集的金币数目越多,奔跑的距离越长,玩家的得分就越高。我们最终实现的界面效果如图所示,首先我们来讲一下游戏的原理,我们这里这里采用的方法是路段固定,移动摄像机的方法。换句话说,当角色开始移动后,摄像机和场景跟随角色缓缓向右移动。当角色跑完每一个路段距离的2/3时,计算下一路段的位置,并在该位置生成一个新的路段,这样在游戏场景中可以产生无限远的路段,当某一路段离开摄像机视野时,立即将其销毁。于此同时,我们在每一个路段上随机产生障碍物和金币,然后对角色做碰撞检测即可。
二、角色控制
角色控制这里,我们只关注角色的状态,即角色是处于奔跑状态还是死亡状态。通过这一状态,我们针对角色采取不同的处理方式。如果角色处于奔跑状态,则更新角色位置、摄像机位置、背景位置,否则角色将在被障碍物撞到以后倒地死亡。我们来一起看下面的脚本:
-
using UnityEngine;
-
using System.Collections;
-
-
public class Player : MonoBehaviour {
-
-
-
public float mMoveSpeed=2.5F;
-
-
-
private Transform mCamera;
-
-
private Transform mBackground;
-
-
-
private bool isRuning=true;
-
-
private int mCount=1;
-
-
-
public GameObject CubeWay;
-
-
-
private int DeathCount=0;
-
-
-
private int mCoinCount=0;
-
public int CoinCount {
-
get {
-
return mCoinCount;
-
}
-
}
-
-
-
private int mLength=0;
-
public int Length {
-
get {
-
return mLength;
-
}
-
}
-
-
-
private int mGrade=0;
-
public int Grade {
-
get {
-
return mGrade;
-
}
-
}
-
-
void Start ()
-
{
-
-
mCamera=Camera.main.transform;
-
-
mBackground=GameObject.Find("Background").transform;
-
}
-
-
void Update ()
-
{
-
-
if(isRuning)
-
{
-
Move();
-
CreateCubeWay();
-
Jump();
-
UpdateData();
-
}else
-
{
-
Death();
-
}
-
}
-
-
-
-
-
private void UpdateData()
-
{
-
-
mLength=(int)((transform.position.x+25)*25);
-
-
mGrade=(int)(mLength*0.8+mCoinCount*0.2);
-
}
-
-
-
-
private void Death()
-
{
-
-
if(DeathCount<=1)
-
{
-
-
transform.animation.Play("Lose");
-
-
DeathCount+=1;
-
-
-
}
-
}
-
-
private void Jump()
-
{
-
-
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
-
{
-
while(transform.position.y<=1)
-
{
-
float y=transform.position.y+0.02F;
-
transform.position=new Vector3(transform.position.x,y,transform.position.z);
-
transform.animation.Play("Jump");
-
}
-
StartCoroutine("Wait");
-
}
-
}
-
-
IEnumerator Wait()
-
{
-
yield return new WaitForSeconds(0.8F);
-
-
while(transform.position.y>0.125F)
-
{
-
float y=transform.position.y-0.02F;
-
transform.position=new Vector3(transform.position.x,y,transform.position.z);
-
transform.animation.Play("Run");
-
}
-
}
-
-
-
private void Move()
-
{
-
-
transform.Translate(Vector3.forward * mMoveSpeed * Time.deltaTime);
-
-
mCamera.Translate(Vector3.right * mMoveSpeed * Time.deltaTime);
-
-
mBackground.Translate(Vector3.left * mMoveSpeed * Time.deltaTime);
-
}
-
-
-
private void CreateCubeWay()
-
{
-
-
-
if(transform.position.x+30-(mCount-1)*50 >=50*2/3)
-
{
-
-
-
GameObject mObject=(GameObject)Instantiate(CubeWay,new Vector3(-5F+mCount * 50F,0F,-2F),Quaternion.identity);
-
mObject.transform.localScale=new Vector3(50F,0.25F,1F);
-
-
mCount+=1;
-
}
-
}
-
-
void OnTriggerEnter(Collider mCollider)
-
{
-
-
if(mCollider.gameObject.tag=="Coin")
-
{
-
Destroy(mCollider.gameObject);
-
mCoinCount+=1;
-
}
-
-
else if(mCollider.gameObject.tag=="Rock")
-
{
-
isRuning=false;
-
}
-
}
-
}
在这里我们需要关注下面的内容:
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,我们分别来看他们的脚本:
-
using UnityEngine;
-
using System.Collections;
-
-
public class CubeWay : MonoBehaviour {
-
-
-
public GameObject[] mObjects;
-
-
-
void Start ()
-
{
-
-
-
int mCount=Random.Range(20,50);
-
for(int i=0;i<mCount;i++)
-
{
-
Instantiate(mObjects[0],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),1F,-2F),
-
Quaternion.Euler(new Vector3(90F,180F,0F)));
-
}
-
-
mCount=Random.Range(5,10);
-
for(int i=0;i<mCount;i++)
-
{
-
Instantiate(mObjects[1],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),0.5F,-2F),
-
Quaternion.Euler(new Vector3(90F,180F,0F)));
-
}
-
}
-
-
-
void OnBecameInvisible()
-
{
-
Destroy(this.gameObject);
-
}
-
-
}
-
using UnityEngine;
-
using System.Collections;
-
-
public class Coin : MonoBehaviour {
-
-
-
-
void Update ()
-
{
-
transform.Rotate(Vector3.forward * 50F * Time.deltaTime);
-
}
-
-
-
void OnBecameInvisible()
-
{
-
Destroy(this.gameObject);
-
}
-
}
-
using UnityEngine;
-
using System.Collections;
-
-
public class Rock : MonoBehaviour {
-
-
-
void OnBecameInvisible()
-
{
-
Destroy(this.gameObject);
-
}
-
}
其中CubeWay就是一个Cube、Coin是一个圆柱体,为了让金币看起来好看点,我们让金币在空中旋转起来、Rock就是一个平面贴图。这里Rock、Coin将绑定到CubeWay的mObjects。
五、游戏管理
最后是界面的数据更新啦,脚本定义如下:
-
using UnityEngine;
-
using System.Collections;
-
-
public class GameManager : MonoBehaviour {
-
-
-
private Transform GameUI;
-
-
private Transform mPlayer;
-
-
private Transform mCoins;
-
private Transform mLength;
-
-
void Start ()
-
{
-
GameUI=GameObject.Find("2DUI").transform;
-
mPlayer=GameObject.Find("People").transform;
-
mCoins=GameUI.FindChild("Anchor/Panel/Coins").transform;
-
mLength=GameUI.FindChild("Anchor/Panel/Length").transform;
-
}
-
-
void Update ()
-
{
-
mCoins.GetComponent<UILabel>().text="金币:" + mPlayer.GetComponent<Player>().CoinCount;
-
mLength.GetComponent<UILabel>().text="距离:" + mPlayer.GetComponent<Player>().Length;
-
}
-
}
好了,到现在整个游戏已经讲解完了,相信大家已经迫不及待地想看看最终的效果了,好,我们一起来看看吧:
希望今天的内容大家能够喜欢,希望大家继续支持和关注我的博客,如果我们对今天的例子稍作修改,就可以实现3D版的跑酷,经典的《神庙逃亡》游戏就是基于Unity3D游戏引擎开发的。