Unity实例开发-奔跑的轮胎
我们使用Unity 3D实现一个简单的超车小游戏。
开发环境:Unity5.0.2以上。
运行效果:
玩家必须在有限时间内进入通关大门才能获得胜利,游戏过程中,玩家可以加速,可以左右移动躲避汽车,图中碰到任何一辆车,或者规定的时间进入通关大门。
关键功能及脚本:
控制玩家左右移动:
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");
}
到此为止,游戏基本完成,细节部分还要按照自己的要求不断调试,才能更加完善。