Unity实例开发-奔跑的轮胎

我们使用Unity 3D实现一个简单的超车小游戏。

开发环境:Unity5.0.2以上。

运行效果:

Unity实例开发-奔跑的轮胎

Unity实例开发-奔跑的轮胎

玩家必须在有限时间内进入通关大门才能获得胜利,游戏过程中,玩家可以加速,可以左右移动躲避汽车,图中碰到任何一辆车,或者规定的时间进入通关大门。

关键功能及脚本:

控制玩家左右移动:

public class PlayerScript : MonoBehaviour {

	private float speed_L_R = 0.1F; //玩家左右移动的速度;
	private float speed_F = 0.1F;  //玩家向前的速度;
	// Use this for initialization
	void Start () {
	}
	
	// Update is called once per frame
	void Update () {
               if (Input.GetKey (KeyCode.W) )  //按下A键翔左运动
			transform.Translate (-Vector3.forward * speed_F);

		if (Input.GetKey (KeyCode.A) )  //按下A键翔左运动
			transform.Translate (-Vector3.left * speed_L_R);
		if (Input.GetKey (KeyCode.D))  //按下D键向右运动
				transform.Translate (-Vector3.right * speed_L_R);
	}

}

摄像机与玩家匹配:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyCameraScript : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		Transform caTransform;
		//获取玩家的世界坐标值
		caTransform = GameObject.Find ("player").GetComponent<Transform> ();
		//摄像机的x值设为3
		float Camera_X = 3.0f;
		//摄像机的y值设定
		float Camera_Y = caTransform.position.y + 1.5f;
		//摄像机的z值设定
		float Camera_Z = caTransform.position.z - 5.0f;
		//重置摄像机的位置,使摄像机永远跟随玩家运动
		transform.position = new Vector3 (Camera_X, Camera_Y, Camera_Z);
	}
}

当我们一直往左或者一直往右移动玩家时,就会离开摄像机的视角范围。我们编写脚本使之移动到公路边缘时,便

不能继续移动。

if (Input.GetKey (KeyCode.A) && transform.position.x > -0.7)  //按下A键翔左运动
				transform.Translate (-Vector3.left * speed_L_R);
			if (Input.GetKey (KeyCode.D) && transform.position.x < 6.8)  //按下D键向右运动
				transform.Translate (-Vector3.right * speed_L_R);

汽车的随机出现,我们这里有两种汽车,需要让这两种车随机分布并出现在场景中,并且可以向前行驶。需要作为刚体并加上盒子碰撞。:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyPreScript : MonoBehaviour {
	public int car_count;													//汽车的数目
	public Rigidbody car01;													//表示第一辆车
	public Rigidbody car02;													//表示第二辆车
	private Rigidbody[] car;												//用来放置实例化后的汽车
		// Use this for initialization
	void Start () {
		int rand, choose;
		float x, z;
		
		car = new Rigidbody[car_count];
		//汽车的初始位置
		z = -101.0f;
		for (int i = 0; i < car_count; ++i) {
			rand = Random.Range (0, 4);   									//表示汽车的随机位置
			choose = Random.Range (0, 2);									//表示汽车的随机种类
			x = rand * 2;
			if(choose == 0) 												//实例化第一辆车
				car[i] = (Rigidbody)Instantiate(car01, new Vector3(x, 0.1f, z += 5), Quaternion.identity);
			else  															//实例化第二辆车
				car[i] = (Rigidbody)Instantiate(car02, new Vector3(x, 0.1f, z += 5), Quaternion.identity);
		}

	}
}

汽车的随机乱道AI:产生汽车的前进与随机变动。修改MyPreScript:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyPreScript : MonoBehaviour {
	public int car_count;													//汽车的数目
	public Rigidbody car01;													//表示第一辆车
	public Rigidbody car02;													//表示第二辆车
	private Rigidbody[] car;												//用来放置实例化后的汽车
	public int rand_rate;													//汽车随机速率
	private int count_rand; 												//累加器
	private int rand_car; 													//随机数
	// Use this for initialization
	void Start () {
		int rand, choose;
		float x, z;
		count_rand = 0;

		car = new Rigidbody[car_count];
		//汽车的初始位置
		z = -101.0f;
		for (int i = 0; i < car_count; ++i) {
			rand = Random.Range (0, 4);   									//表示汽车的随机位置
			choose = Random.Range (0, 2);									//表示汽车的随机种类
			x = rand * 2;
			if(choose == 0) 												//实例化第一辆车
				car[i] = (Rigidbody)Instantiate(car01, new Vector3(x, 0.1f, z += 5), Quaternion.identity);
			else  															//实例化第二辆车
				car[i] = (Rigidbody)Instantiate(car02, new Vector3(x, 0.1f, z += 5), Quaternion.identity);
		}
	}
	
	// Update is called once per frame
	void Update () {
					//游戏刷新累加器
			++count_rand;
			//游戏每刷新rand_rate次产生一个随机数rand_car,随机数n=3,4,5,6,7,8
			if (count_rand % rand_rate == 1)
				rand_car = Random.Range (3, 9);
			for (int i = 0; i < car_count; ++i) {
				//汽车向正前方行驶
				car [i].transform.Translate (Vector3.forward * 0.1f);
				//跟随随机数构造伪随机方法,实现汽车的三种状态,向左,向右,向前行驶,汽车默认为向前行驶
				if (i * i % rand_car == 0 && car [i].transform.position.x < 6)
					car [i].transform.Translate (Vector3.right * 0.05f);
				if (i * i % rand_car == 1 && car [i].transform.position.x > 0)
					car [i].transform.Translate (Vector3.left * 0.05f);

		}
	}
}

实现玩家的加速与超车:

void Update(){
if (Input.GetKey (KeyCode.W))  //按下W键,速度为0.3;
				speed_F = 0.3F;
			else                           //不按W键,速度为0.1;
				speed_F = 0.1F;
			transform.Translate (-Vector3.forward * speed_F);
			if (Input.GetKey (KeyCode.A) && transform.position.x > -0.7)  //按下A键翔左运动
				transform.Translate (-Vector3.left * speed_L_R);
			if (Input.GetKey (KeyCode.D) && transform.position.x < 6.8)  //按下D键向右运动
				transform.Translate (-Vector3.right * speed_L_R);
}

碰撞检测:为玩家加上盒子碰撞器,然后在MyPlayerScript编写一个OnCollisionEnter函数来检测碰撞,如果当前物体发生了一次碰撞,系统就会自动调用该函数。

	void OnCollisionEnter(Collision col)
	{
		//与汽车发生碰撞,游戏结束
		if (col.gameObject.tag == "car")
			GameObject.Find ("GameObject").GetComponent<MyUIScript> ().gameover = true;
	}

然后为所有的车加上car标签。打开MyPreScript脚本添加:

if(choose == 0) 												//实例化第一辆车
				car[i] = (Rigidbody)Instantiate(car01, new Vector3(x, 0.1f, z += 5), Quaternion.identity);
			else  															//实例化第二辆车
				car[i] = (Rigidbody)Instantiate(car02, new Vector3(x, 0.1f, z += 5), Quaternion.identity);

加入计时器:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MyUIScript : MonoBehaviour {
	public Text downtime;								//显示游戏倒计时的文本对象
	public Text countdown; 								//显示游戏中的倒计时
	public bool gameStart;								// Use this for initialization
	void Start () {
		//游戏还不能开始,等待倒计时结束
		gameStart = false;
		//调用迭代函数计时器
		StartCoroutine (startTime (3));
	}

	IEnumerator startTime(int n)
	{
		//将int型变量转换为string型赋值给倒计时文本
		for (int i = n; i >= 0; --i) {
			downtime.text = i.ToString ();
			//等待一秒钟
			yield return new WaitForSeconds (1.0f);
		}
		//倒计时结束,倒计时文本清空
		downtime.text = null;
		//倒计时结束,游戏开始
		gameStart = true;
	}

	}

运行后发现倒计时并没有对游戏的运行产生影响,可以在MyPlayerScript中添加限制。

void Update () {
		//如果游戏开始了,才运行以下内容
		if (GameObject.Find ("GameObject").GetComponent<MyUIScript>().gameStart) {
			//按下W键,速度为0.3
			if (Input.GetKey (KeyCode.W))
				speed_F = 0.3f;
			//不按W键,速度为0.1f
			else
				speed_F = 0.1f;
			//角色前进
			transform.Translate (-Vector3.forward * speed_F);

			if (Input.GetKey (KeyCode.A) && transform.position.x > -0.7) 			//按下A键向左运动
				transform.Translate (-Vector3.left * speed_L_R);
			else if (Input.GetKey (KeyCode.D) && transform.position.x < 6.8)		//按下D键向右运动
				transform.Translate (-Vector3.right * speed_L_R);
					}
	}

在汽车脚本PreScript中也加入这条逻辑:

void Update () {
		//如果游戏开始了,才运行以下内容
		if (GameObject.Find ("GameObject").GetComponent<MyUIScript>().gameStart ) {
			//游戏刷新累加器
			++count_rand;
			//游戏每刷新rand_rate次产生一个随机数rand_car,随机数n=3,4,5,6,7,8
			if (count_rand % rand_rate == 1)
				rand_car = Random.Range (3, 9);
			for (int i = 0; i < car_count; ++i) {
				//汽车向正前方行驶
				car [i].transform.Translate (Vector3.forward * 0.1f);
				//跟随随机数构造伪随机方法,实现汽车的三种状态,向左,向右,向前行驶,汽车默认为向前行驶
				if (i * i % rand_car == 0 && car [i].transform.position.x < 6)
					car [i].transform.Translate (Vector3.right * 0.05f);
				if (i * i % rand_car == 1 && car [i].transform.position.x > 0)
					car [i].transform.Translate (Vector3.left * 0.05f);
			}
		}
	}

当轮胎被碰撞后,会失去重心,行走不稳。我们需要在MyPlayScript中加上Quaternion.LookRotation()来自我平衡。

//限定角色的自转
			transform.rotation = Quaternion.LookRotation (Vector3.back, Vector3.up);

然后添加第二个倒计时,当3s倒计时结束后,为玩家施加压力的到技术出现了。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MyUIScript : MonoBehaviour {
	public Text downtime;								//显示游戏倒计时的文本对象
	public Text countdown; 								//显示游戏中的倒计时
	public bool gameStart;									public int time_length;								//游戏时间多长
	// Use this for initialization
	void Start () {
		//游戏还不能开始,等待倒计时结束
		gameStart = false;
		//游戏还不能开始,不显示倒计时
		countdown.text = null;
		//调用迭代函数计时器
		StartCoroutine (startTime (3));
	}

	IEnumerator startTime(int n)
	{
		//将int型变量转换为string型赋值给倒计时文本
		for (int i = n; i >= 0; --i) {
			downtime.text = i.ToString ();
			//等待一秒钟
			yield return new WaitForSeconds (1.0f);
		}
		//倒计时结束,倒计时文本清空
		downtime.text = null;
		//倒计时结束,游戏开始
		gameStart = true;
		//开始倒计时结束后,调用游戏倒计时
		StartCoroutine(countTime(time_length));
	}

	IEnumerator countTime(int time)
	{
		for (int i = time; i >= 0; --i) {
			if (gameStart && !gamewin && !gameover) {
				int minutes = i / 60;
				int seconds = i % 60;
				countdown.text = minutes.ToString ("D2") + ":" + seconds.ToString ("D2");
				yield return new WaitForSeconds (1.0f);
			}
		}
	}

}

胜负逻辑:

修改MyPlayerScript,当碰到车的时候,游戏失败告终。

void OnCollisionEnter(Collision col)
	{
		//与汽车发生碰撞,游戏结束
		if (col.gameObject.tag == "car")
			GameObject.Find ("GameObject").GetComponent<MyUIScript> ().gameover = true;
	}

修改UIScript的代码,倒计时结束时,游戏失败告终。

IEnumerator countTime(int time)
	{
		for (int i = time; i >= 0; --i) {
			if (gameStart && !gamewin && !gameover) {
				int minutes = i / 60;
				int seconds = i % 60;
				countdown.text = minutes.ToString ("D2") + ":" + seconds.ToString ("D2");
				yield return new WaitForSeconds (1.0f);
			}
		}
		gameover = true;
	}

修改MyPlayerScript代码,当轮胎进入大门时赢得游戏,并且给游戏的运行设置三个条件。

oid Update () {
		//如果游戏开始了,才运行以下内容
		if (GameObject.Find ("GameObject").GetComponent<MyUIScript> ().gameStart &&
			!GameObject.Find ("GameObject").GetComponent<MyUIScript> ().gamewin &&
			!GameObject.Find ("GameObject").GetComponent<MyUIScript> ().gameover) {
			//按下W键,速度为0.3
			if (Input.GetKey (KeyCode.W))
				speed_F = 0.3f;
			//不按W键,速度为0.1f
			else
				speed_F = 0.1f;
			//角色前进
			transform.Translate (-Vector3.forward * speed_F);

			if (Input.GetKey (KeyCode.A) && transform.position.x > -0.7) 			//按下A键向左运动
				transform.Translate (-Vector3.left * speed_L_R);
			else if (Input.GetKey (KeyCode.D) && transform.position.x < 6.8)		//按下D键向右运动
				transform.Translate (-Vector3.right * speed_L_R);
			//限定角色的自转
			transform.rotation = Quaternion.LookRotation (Vector3.back, Vector3.up);
			//通过大门,游戏胜利
			if (transform.position.z > 260)
				GameObject.Find ("GameObject").GetComponent<MyUIScript> ().gamewin = true;
		}
	}

同理,修改MyPreScript与MyUIScript。

最后在MyUIScript中补充代码:

void OnGUI()
	{
		float screenX = Screen.width / 2 - 50;
		float screenY = Screen.height / 2 - 40;
		//如果游戏失败
		if (gameover)
			//出现重玩此关按钮
			if (GUI.Button (new Rect (screenX, screenY, 100, 40), "重玩此关"))
				Application.LoadLevel ("Game");
		//如果游戏取得胜利
		if (gamewin)
			//出现恭喜胜利按钮
			if (GUI.Button (new Rect (screenX, screenY, 100, 40), "恭喜胜利"))
				Application.LoadLevel ("Game");
	}

到此为止,游戏基本完成,细节部分还要按照自己的要求不断调试,才能更加完善。