Unity3D星际航行游戏完整开发过程

一、准备工作

1、第一步

添加飞船:导入包——新建场景并保存场景——删除Done——Models倒数第二个拖入Main场景并命名为player——Transform(设置reset)——加组件(Add Component—-physics—Rigidbody)不使用重力(Gravity)——加碰撞体Mesh Collider(Conver和inflate mesh都勾选)——碰撞体Material可以更换为材质少的——prefab里面的Engines最后一个拖给player


2、第二步

主相机和飞船方向一致:切换Main Camera——Rotation的X为90,position的Y,Z变大10,5——Clear Flags选择Solid Color,背景色变黑——投影projection设置正交orthographics(因为模型偏二维)Size变大为10
(projection  投影 orthographics  正交)

3、第三步

添加背景图片:设置承载对象(Create-3D-Quad四边形)重命名为background——删掉remove MeshColider——Rotation:X90——Textures第二排第7个拖给background——选择background让游戏进入播放状态(不能全屏播放)——不在播放状态选择Scale改为48.6,30,1,背景扩充了——如果有阴影,Shader-Standard-Unlit-Texture——背景置于模型下方Position的Y值改为-10——星星闪烁效果,Prefab-Starfield然后拖到层次面板——准备工作结束

(U3D第二个视频1:35:40开始总结)

二、飞船和子弹
1、第一步

NewBehaviourScript脚本代码初步,飞船可以上下左右移动

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

public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	public float speed=5.0f;
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		float moveH=Input.GetAxis("Horizontal");//获取水平方向
		float moveV=Input.GetAxis("Vertical");//获取垂直方向
		Vector3 movement= new Vector3(moveH, 0.0f, moveV);
		GetComponent().velocity=movement*speed;//刚体属性有速度,就可以运动

	}
}

 

2、第二步

NewBehaviourScript脚本代码补充,飞船不会跑出边界

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

[System.Serializable]//序列化,使得自己定义的类可以出现在面板
public class Boundary{
	public float xMin,xMax,zMin,zMax;

}
public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	public float speed=5.0f;
	public Boundary boundary;
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		float moveH=Input.GetAxis("Horizontal");//获取水平方向
		float moveV=Input.GetAxis("Vertical");//获取垂直方向
		Vector3 movement= new Vector3(moveH, 0.0f, moveV);
		//GetComponent().velocity=movement*speed;//刚体属性有速度,就可以运动
        Rigidbody rb=GetComponent();
        if(rb!=null){
        	rb.velocity=movement*speed;
        	rb.position=new Vector3(Mathf.Clamp(rb.position.x,boundary.xMin,boundary.xMax),0.0f,Mathf.Clamp(rb.position.z,boundary.zMin,boundary.zMax));//介于最小值和最大值之间,以防越界
        }
	}
}

 

3、第三步

子弹的设置:创建一个空并命名为Bolt——让飞船不显示,为子弹添加刚体组件并去掉重力——承载纹理,加Quad四边形并重命名为VFX——将VFX拖给Bolt,删掉Mesh Collider——将VFX的Rotation90——Materials第一个拖给VFX——给Bolt添加碰撞体capsule collider——Is  Trigger勾选,触发会有后续操作,Driection切换为Z轴——重新勾选player,写代码,新建脚本Mover——挂载给子弹-——将子弹设为预制体,将Bolt拖到下方层次面板

注:Instantiate (prefab, position, rotation)实例化可以自动产生子弹

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

public class Mover : MonoBehaviour {

	// Use this for initialization
	public float speed=10.0f;
	void Start () {
		GetComponent().velocity=transform.forward*speed;//向正前方飞
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

4、第四步

添加一个空并命名为shotspawn拖给player——在第一个脚本继续写代码
 

查看发射键:Edit-Project Settings-Input 右方面板即可查看


Shot和ShotSpawn没有赋值,不会自动发射子弹,所以,将Bolt拖给Shot,将ShotSpawn拖给player展开面板右下方的ShotSpawn——按住左Ctrl或鼠标左键即可发射子弹

5、第五步

继续补充NewBehaviourScript代码,使飞船能够发射子弹,并且能够不断产生子弹

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

[System.Serializable]//序列化,使得自己定义的类可以出现在面板
public class Boundary{
	public float xMin,xMax,zMin,zMax;

}
public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	public float speed=5.0f;
	public Boundary boundary;
	public float fireRate=0.5f;//子弹发射间隔时间
	public GameObject shot;//表示子弹预制体
	public GameObject shotSpawn;//表示位置和旋转角度
	private float nextFire=0.0f;//表示子弹下次发射的时间

	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		float moveH=Input.GetAxis("Horizontal");//获取水平方向
		float moveV=Input.GetAxis("Vertical");//获取垂直方向
		Vector3 movement= new Vector3(moveH, 0.0f, moveV);
		//GetComponent().velocity=movement*speed;//刚体属性有速度,就可以运动
        Rigidbody rb=GetComponent();
        if(rb!=null){
        	rb.velocity=movement*speed;
        	rb.position=new Vector3(Mathf.Clamp(rb.position.x,boundary.xMin,boundary.xMax),0.0f,Mathf.Clamp(rb.position.z,boundary.zMin,boundary.zMax));//介于最小值和最大值之间,以防越界
        }
        if(Input.GetButton("Fire1")&&Time.time>nextFire)//从游戏开始到现在的时间大于下次开火时间
        {
        	nextFire=Time.time+fireRate;
        	Instantiate(shot,shotSpawn.GetComponent().position,shotSpawn.GetComponent().rotation);//用来自动发射子弹
        }
	}
}


6、第六步

优化代码——重新拖shotSpawn——
射出边界后自动消失掉:添加一个Cube并命名为Boundary——position的Z设置为5,和主摄相机在一个平面——将scale的X和Z拖至铺满屏幕直至边界——Is trigger勾选——删掉Mesh Rrenderer,以免浪费资源——写代码——新建脚本命名为DestroyByRoundary

优化NewBehaviourScript代码:

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

[System.Serializable]//序列化,使得自己定义的类可以出现在面板
public class Boundary{
	public float xMin,xMax,zMin,zMax;

}
public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	public float speed=5.0f;
	public Boundary boundary;
	public float fireRate=0.5f;//子弹发射间隔时间
	public GameObject shot;//表示子弹预制体
	//public GameObject shotSpawn;//表示位置和旋转角度
	public Transform shotSpawn;
	private float nextFire=0.0f;//表示子弹下次发射的时间

	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		float moveH=Input.GetAxis("Horizontal");//获取水平方向
		float moveV=Input.GetAxis("Vertical");//获取垂直方向
		Vector3 movement= new Vector3(moveH, 0.0f, moveV);
		//GetComponent().velocity=movement*speed;//刚体属性有速度,就可以运动
        Rigidbody rb=GetComponent();
        if(rb!=null){
        	rb.velocity=movement*speed;
        	rb.position=new Vector3(Mathf.Clamp(rb.position.x,boundary.xMin,boundary.xMax),0.0f,Mathf.Clamp(rb.position.z,boundary.zMin,boundary.zMax));//介于最小值和最大值之间,以防越界
        }
        if(Input.GetButton("Fire1")&&Time.time>nextFire)//从游戏开始到现在的时间大于下次开火时间
        {
        	nextFire=Time.time+fireRate;
        	//Instantiate(shot,shotSpawn.GetComponent().position,shotSpawn.GetComponent().rotation);//用来自动发射子弹
        	Instantiate(shot,shotSpawn.position,shotSpawn.rotation);
        }
	}
}


7、第七步

DestroyByBoundary代码挂载在Boundary

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

public class DestroyByBoundary : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerExit(Collider other){
		Destroy(other.gameObject);//溢出触发器的操作,销毁子弹
	}
}


三、小行星

添加小行星,随机产生,射中就爆炸销毁,飞船撞上小行星游戏结束


1、第一步

创建小行星:创建一个空命名为asteroid,用来承载——添加刚体组件,去掉使用重力,添加Capsule collide并勾选Is Triggerr——将Models里第一个拖给asteroid——小行星position的Z给10,direction改为Z轴
 

2、第二步

让小行星动起来:写代码——创建脚本代码RandomRotator——挂载给asteroid

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

public class RandomRorator : MonoBehaviour {

	// Use this for initialization
	public float tumble=10.0f;//旋转系数
	void Start () {
		GetComponent().angularVelocity = Random.insideUnitSphere*tumble;//单位球体之间取随机值
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

3、第三步

小行星越转越慢:将Angular Drag设置为0

写代码,小行星和飞船碰撞后销毁:新建脚本代码DestroyByContact——DestroyByContact代码挂载在小行星上

给Boundary加标签——右上方Tag选择Boundary——写代码——Prefabs里Explosions第一个拖给asteroid右下方面板Destroy By Contac脚本的Explosion
 

将Prefabs里Explosions第3个拖给asteroid右下方面板Destroy By Contac脚本的Player Explosion
 

给player加标签——右上方Tag选择Player

DestroyByCotac初步代码:

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

public class DestroyByCotac : MonoBehaviour {

	// Use this for initialization
	//public GameObject explosion;//子弹和小行星碰撞
	//public GameObject playerExplosion;//飞船和小行星碰撞

	//public int scoreValue;
	//private GameController gameController;
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerEnter(Collider other){
		if (other.tag == "Boundary")
			return;//如果是边界直接返回
		Destroy (other.gameObject);//和小行星碰撞的,子弹或飞船
		Destroy (gameObject);//小行星也销毁
		print (other.name);//测试边界是否被销毁,看看other是谁,发现边界和小行星发生碰撞了
	//	Instantiate (explosion,transform.position,transform.rotation);//实例化
	//	if (other.tag == "Player") {
	//		Instantiate (playerExplosion,other.transform.position,other.transform.rotation);//飞船爆炸实例化
		//	gameController.AddScore (scoreValue);
		//	gameController.GameOver ();
	//	}
			
	}
}


4、第四步

优化代码

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

public class DestroyByContact : MonoBehaviour {

	// Use this for initialization

	public GameObject explosion;//子弹和小行星碰撞
	public GameObject playerExplosion;//飞船和小行星碰撞

	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerEnter(Collider other){
		if (other.tag == "Boundary")
			return;//如果是边界直接返回
		Destroy (other.gameObject);//和小行星碰撞的,子弹或飞船
		Destroy (gameObject);//小行星也销毁
		print (other.name);//测试边界是否被销毁,看看other是谁,发现边界和小行星发生碰撞了
			Instantiate (explosion,transform.position,transform.rotation);//实例化
		if (other.tag == "Player") {
			Instantiate (playerExplosion,other.transform.position,other.transform.rotation);//飞船爆炸实例化,和子弹爆炸效果不同

		}
	}
}

 

5、第五步

让小行星能掉下:代码重用,将Mover脚本挂载在小行星asteroid上——speed给一个负值-5
 

小行星随机产生:将其做成预制体,实例化,让位置随机——将asteroid拖到下方prefab层次面板中,然后删掉原来的——create一个空的游戏对象,命名为GameController——Tag勾选GameController——新建脚本文件命名为GameController——写代码

将脚本GameController代码挂载在GameController上——将小行星预制体拖给右上方 hazard;——可以把小行星预制体重新拖到面板上找X和Z的临界值,也就是X最大Z最大值是多少——X是21.65,Z是13.89

GameController 代码:

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

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	//public int hazardCount;
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	void Start () {
		SpawnWaves();//调用函数
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void SpawnWaves(){
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
	}
}


6、第六步

优化代码:产生批量小行星

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

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	void Start () {
		SpawnWaves();//调用函数
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void SpawnWaves(){
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
			}
	}
}


7、第七步

赋给hazardCount一个值,运行

批量产生会彼此碰撞,所以间隔一段时间再产生就可以避免

优化GameController代码:

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

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	IEnumerator SpawnWaves(){
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
	}
}

 

Spawn Wait赋0.5运行,产生小行星,解决问题

8、第八步

让小行星刚开始有一定的延迟,优化GameController代码:

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

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	public float startWait=1.0f;//刚开始有一定的延迟
	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	IEnumerator SpawnWaves(){
		yield return new WaitForSeconds (startWait);//实现协程,打断时间
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
	}
}

9、第九步

产生多轮小行星:

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

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	public float startWait=1.0f;//刚开始有一定的延迟
	public float waveWait = 2.0f;//一轮后的等待时间


	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	IEnumerator SpawnWaves(){
		yield return new WaitForSeconds (startWait);//实现协程,打断时间
		while (true){
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
			yield return new WaitForSeconds (waveWait);//产生多轮小行星
		}
	}
}


10、第十步

过一段时间后积累的东西被销毁:新建脚本代码命名为DestroyByTime

代码如下

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

public class DestroyByTime : MonoBehaviour {

	// Use this for initialization
	public float lifetime=2.0f;
	void Start () {
		Destroy (gameObject,lifetime);//过一段时间再销毁
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

11、第十一步

选中预制体Explosions中第一个,在Component——script——DestroyByTime——将代码挂载在爆炸体上了
 

四、音频添加

1、第一步

player直接添加Audio Source组件,将音频最后一个拖给AudioClip——将Play On Awake去掉勾选——写代码

NewBehaviourScript 补充:

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

[System.Serializable]//序列化,使得自己定义的类可以出现在面板
public class Boundary{
	public float xMin,xMax,zMin,zMax;

}
public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	public float speed=5.0f;
	public Boundary boundary;
	public float fireRate=0.5f;//子弹发射间隔时间
	public GameObject shot;//表示子弹预制体
	//public GameObject shotSpawn;//表示位置和旋转角度
	public Transform shotSpawn;
	private float nextFire=0.0f;//表示子弹下次发射的时间

	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		float moveH=Input.GetAxis("Horizontal");//获取水平方向
		float moveV=Input.GetAxis("Vertical");//获取垂直方向
		Vector3 movement= new Vector3(moveH, 0.0f, moveV);
		//GetComponent().velocity=movement*speed;//刚体属性有速度,就可以运动
        Rigidbody rb=GetComponent();
        if(rb!=null){
        	rb.velocity=movement*speed;
        	rb.position=new Vector3(Mathf.Clamp(rb.position.x,boundary.xMin,boundary.xMax),0.0f,Mathf.Clamp(rb.position.z,boundary.zMin,boundary.zMax));//介于最小值和最大值之间,以防越界
        }
        if(Input.GetButton("Fire1")&&Time.time>nextFire)//从游戏开始到现在的时间大于下次开火时间
        {
        	nextFire=Time.time+fireRate;
        	//Instantiate(shot,shotSpawn.GetComponent().position,shotSpawn.GetComponent().rotation);//用来自动发射子弹
        	Instantiate(shot,shotSpawn.position,shotSpawn.rotation);
        	GetComponent().Play ();//发射子弹有声音
        }
	}
}

 

2、第二步

加背景音:选择GameController——直接添加Audio Source组件,将音频4拖给AudioClip——勾选Loop,就可以循环播放了

加打中时的音频:Explosion第一个添加Audio Source——将音频第一个拖给AudioClip

飞船碰上小行星爆炸音:Explosion第三个添加Audio Source——将音频第三个拖给AudioClip——Play On Awake处于勾选状态
 

五、计分器、游戏结束和重新开始文本框

给游戏添加计分器,飞船撞小行星游戏结束,游戏介绍按R键重新开始游戏

1、第一步

添加文本框:create——UI——Text——重命名ScoreText,游戏简单可以删掉EventSystem

调节文字位置:Pos X和Y值慢慢调
 

选择GameController,写好代码后,将ScoreText拖到右方ScoreText上

prefab里asteroid右侧Score Value赋值10

GameController代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//引入UI系统
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	public float startWait=1.0f;//刚开始有一定的延迟
	public float waveWait = 2.0f;//一轮后的等待时间

	public Text scoreText;//文本框绑定
	private int score;//存放得分值

	//public Text gameOverText;
	//private bool gameOver;

//	public Text restartText;
//	private bool restart;


	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
		score = 0;//开始为0
		UpdataScore ();//开始先更新一下分数
	//	gameOverText.text =" ";
	//	gameOver = false;
	//	restartText.text = "";
	//	restart = false;
	}
	
	// Update is called once per frame
	void Update () {

		//if (restart) {
		//	if (Input.GetKeyDown (KeyCode.R))
		//		SceneManager.LoadScene ("Main");
				
		//}
	}
	IEnumerator SpawnWaves(){
		yield return new WaitForSeconds (startWait);//实现协程,打断时间
		while (true){
		//	if (gameOver) {
			//	restartText.text = "按住【R】键重新开始";
			//	restart = true;
			//	break;
			//}
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
			yield return new WaitForSeconds (waveWait);
		}
	}
	public void AddScore(int newScoreValue){
		score += newScoreValue;//更新分数
		UpdataScore ();
	}
	void UpdataScore(){
		scoreText.text = "Score" + score;//屏幕上Score增加
	}
//	public void GameOver(){
	//	gameOver = true;
	//	gameOverText.text = "游戏结束";
	//}
}

修改DestroyByContact代码:

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

public class DestroyByContact : MonoBehaviour {

	// Use this for initialization

	public GameObject explosion;//子弹和小行星碰撞
	public GameObject playerExplosion;//飞船和小行星碰撞

	public int scoreValue;//实参
	private GameController gameController;//实例化,可以调用GameController的方法
	void Start () {
		GameObject go=GameObject.FindWithTag ("GameController");
		if (go != null)
			gameController = go.GetComponent ();//拿到GameController脚本代码的控制权
		else
			Debug.Log ("找不到tag名为GameController的对象");
		if(gameController==null)
			Debug.Log ("找不到脚本GameController");
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerEnter(Collider other){
		if (other.tag == "Boundary")
			return;//如果是边界直接返回
		Destroy (other.gameObject);//和小行星碰撞的,子弹或飞船
		Destroy (gameObject);//小行星也销毁
		print (other.name);//测试边界是否被销毁,看看other是谁,发现边界和小行星发生碰撞了
			Instantiate (explosion,transform.position,transform.rotation);//实例化
			gameController.AddScore (scoreValue);//应该在这里
		if (other.tag == "Player") {
			Instantiate (playerExplosion,other.transform.position,other.transform.rotation);//飞船爆炸实例化
			//gameController.AddScore (scoreValue);
			//gameController.GameOver ();
		}
	}
}

 

2、第二步

GAME OVER设置

选中ScoreText然后Ctrl+D键即可复制,重命名为GameOverText——文本内容改为GAME OVER——调整位置——写好代码将GameOverText拖给GameController右侧Game OverText

GameController代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//引入UI系统
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	public float startWait=1.0f;//刚开始有一定的延迟
	public float waveWait = 2.0f;//一轮后的等待时间

	public Text scoreText;//文本框绑定
	private int score;//存放得分值

	public Text gameOverText;//更新内容
	private bool gameOver;//判断是否结束

	//public Text restartText;
	//private bool restart;


	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
		score = 0;//开始为0
		UpdataScore ();//开始先更新一下分数
		gameOverText.text =" ";//赋值为空
		gameOver = false;//刚开始游戏不会结束
	//	restartText.text = "";
	//	restart = false;
	}
	
	// Update is called once per frame
	void Update () {

		//if (restart) {
		//	if (Input.GetKeyDown (KeyCode.R))
		//		SceneManager.LoadScene ("Main");
				
		//}
	}
	IEnumerator SpawnWaves(){
		yield return new WaitForSeconds (startWait);//实现协程,打断时间
		while (true){
			if (gameOver) {
			//	restartText.text = "按住【R】键重新开始";
			//	restart = true;
				break;//游戏结束不再产生小行星
			}
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
			yield return new WaitForSeconds (waveWait);
		}
	}
	public void AddScore(int newScoreValue){
		score += newScoreValue;//更新分数
		UpdataScore ();
	}
	void UpdataScore(){
		scoreText.text = "Score:" + score;//屏幕上Score增加
	}
	public void GameOver(){
		gameOver = true;
		gameOverText.text = "GAME OVER";
	}
}

 

3、第三步

RESTART设置

重新复制一个文本框,重命名为RestartText——文本内容改为Restart——调整位置——写好代码将RestartText拖给GameController右侧RestartText

GameController代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//引入UI系统
using UnityEngine.SceneManagement;//和场景管理相关的操作都在里面

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	public float startWait=1.0f;//刚开始有一定的延迟
	public float waveWait = 2.0f;//一轮后的等待时间

	public Text scoreText;//文本框绑定
	private int score;//存放得分值

	public Text gameOverText;//更新内容
	private bool gameOver;//判断是否结束

	public Text restartText;
	private bool restart;//判断是否重新开始


	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
		score = 0;//开始为0
		UpdataScore ();//开始先更新一下分数
		gameOverText.text =" ";//赋值为空
		gameOver = false;//刚开始游戏不会结束
		restartText.text = "";
		restart = false;
	}
	
	// Update is called once per frame
	void Update () {

		if (restart) {
			if (Input.GetKeyDown (KeyCode.R))
				SceneManager.LoadScene ("Main");//执行重新开始操作
				
		}
	}
	IEnumerator SpawnWaves(){
		yield return new WaitForSeconds (startWait);//实现协程,打断时间
		while (true){
			if (gameOver) {
				restartText.text = "按住【R】键重新开始";
				restart = true;
				break;//游戏结束不再产生小行星
			}
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
			yield return new WaitForSeconds (waveWait);//一轮之后隔一段时间再产生
		}
	}
	public void AddScore(int newScoreValue){
		score += newScoreValue;//更新分数
		UpdataScore ();
	}
	void UpdataScore(){
		scoreText.text = "Score:" + score;//屏幕上Score增加
	}
	public void GameOver(){
		gameOver = true;
		gameOverText.text = "GAME OVER";
	}
}

六、总结

游戏已做好,完整代码如下:

 NewBehaviourScript脚本:

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

[System.Serializable]//序列化,使得自己定义的类可以出现在面板
public class Boundary{
	public float xMin,xMax,zMin,zMax;

}
public class NewBehaviourScript : MonoBehaviour {

	// Use this for initialization
	public float speed=5.0f;
	public Boundary boundary;
	public float fireRate=0.5f;//子弹发射间隔时间
	public GameObject shot;//表示子弹预制体
	//public GameObject shotSpawn;//表示位置和旋转角度
	public Transform shotSpawn;
	private float nextFire=0.0f;//表示子弹下次发射的时间

	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		float moveH=Input.GetAxis("Horizontal");//获取水平方向
		float moveV=Input.GetAxis("Vertical");//获取垂直方向
		Vector3 movement= new Vector3(moveH, 0.0f, moveV);
		//GetComponent().velocity=movement*speed;//刚体属性有速度,就可以运动
        Rigidbody rb=GetComponent();
        if(rb!=null){
        	rb.velocity=movement*speed;
        	rb.position=new Vector3(Mathf.Clamp(rb.position.x,boundary.xMin,boundary.xMax),0.0f,Mathf.Clamp(rb.position.z,boundary.zMin,boundary.zMax));//介于最小值和最大值之间,以防越界
        }
        if(Input.GetButton("Fire1")&&Time.time>nextFire)//从游戏开始到现在的时间大于下次开火时间
        {
        	nextFire=Time.time+fireRate;
        	//Instantiate(shot,shotSpawn.GetComponent().position,shotSpawn.GetComponent().rotation);//用来自动发射子弹
        	Instantiate(shot,shotSpawn.position,shotSpawn.rotation);
        	GetComponent().Play ();//发射子弹有声音
        }
	}
}

DestroyByBoundary 脚本:

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

public class DestroyByBoundary : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerExit(Collider other){
		Destroy(other.gameObject);//溢出触发器的操作,销毁子弹
		print (other.name);
	}
}


DestroyByContact脚本:

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

public class DestroyByContact : MonoBehaviour {

	// Use this for initialization

	public GameObject explosion;//子弹和小行星碰撞
	public GameObject playerExplosion;//飞船和小行星碰撞

	public int scoreValue;//实参
	private GameController gameController;//实例化,可以调用GameController的方法
	void Start () {
		GameObject go=GameObject.FindWithTag ("GameController");
		if (go != null)
			gameController = go.GetComponent ();//拿到GameController脚本代码的控制权
		else
			Debug.Log ("找不到tag名为GameController的对象");
		if(gameController==null)
			Debug.Log ("找不到脚本GameController");
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerEnter(Collider other){
		if (other.tag == "Boundary")
			return;//如果是边界直接返回
		Destroy (other.gameObject);//和小行星碰撞的,子弹或飞船
		Destroy (gameObject);//小行星也销毁
		print (other.name);//测试边界是否被销毁,看看other是谁,发现边界和小行星发生碰撞了
			Instantiate (explosion,transform.position,transform.rotation);//实例化
			gameController.AddScore (scoreValue);//应该在这里,射中子弹分数加加
		if (other.tag == "Player") {
			Instantiate (playerExplosion,other.transform.position,other.transform.rotation);//飞船爆炸实例化
			//gameController.AddScore (scoreValue);
			gameController.GameOver ();//飞船爆炸游戏结束
		}
	}
}

RandomRorator脚本:

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

public class RandomRorator : MonoBehaviour {

	// Use this for initialization
	public float tumble=10.0f;//旋转系数
	void Start () {
		GetComponent().angularVelocity = Random.insideUnitSphere*tumble;//单位球体之间取随机值
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

Mover脚本:

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

public class Mover : MonoBehaviour {

	// Use this for initialization
	public float speed=10.0f;
	void Start () {
		GetComponent().velocity=transform.forward*speed;//向正前方飞
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

GameController脚本:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//引入UI系统
using UnityEngine.SceneManagement;//和场景管理相关的操作都在里面

public class GameController : MonoBehaviour {

	// Use this for initialization
	public GameObject hazard;//障碍物,表示预制对象
	public int hazardCount;//产生小行星的数量
	private Vector3 spawnPosition = Vector3.zero;//位置,初始位置0,0,0
	public Vector3 spawnValues;//位置控制,给spawnPosition提供炮弹
	private Quaternion spawnRotation;//四元素,旋转控制,更方便
	public float spawnWait;//等待时间
	public float startWait=1.0f;//刚开始有一定的延迟
	public float waveWait = 2.0f;//一轮后的等待时间

	public Text scoreText;//文本框绑定
	private int score;//存放得分值

	public Text gameOverText;//更新内容
	private bool gameOver;//判断是否结束

	public Text restartText;
	private bool restart;//判断是否重新开始


	void Start () {
		StartCoroutine(SpawnWaves ());//开启协程
		score = 0;//开始为0
		UpdataScore ();//开始先更新一下分数
		gameOverText.text =" ";//赋值为空
		gameOver = false;//刚开始游戏不会结束
		restartText.text = "";
		restart = false;
	}
	
	// Update is called once per frame
	void Update () {

		if (restart) {
			if (Input.GetKeyDown (KeyCode.R))
				SceneManager.LoadScene ("Main");//执行重新开始操作
				
		}
	}
	IEnumerator SpawnWaves(){
		yield return new WaitForSeconds (startWait);//实现协程,打断时间
		while (true){
			if (gameOver) {
				restartText.text = "按住【R】键重新开始";
				restart = true;
				break;//游戏结束不再产生小行星
			}
		for (int i = 0; i < hazardCount; i++) {
		        spawnPosition.x = Random.Range (-spawnValues.x,spawnValues.x);//取区间的随机值
				spawnPosition.z = spawnValues.z;//Z方向值
				spawnRotation = Quaternion.identity;//不发生旋转?
				Instantiate (hazard,spawnPosition,spawnRotation);//实例化
				yield return new WaitForSeconds (spawnWait);//产生一个后中断一段时间再产生
			}
			yield return new WaitForSeconds (waveWait);//一轮之后隔一段时间再产生
		}
	}
	public void AddScore(int newScoreValue){
		score += newScoreValue;//更新分数
		UpdataScore ();
	}
	void UpdataScore(){
		scoreText.text = "Score:" + score;//屏幕上Score增加
	}
	public void GameOver(){
		gameOver = true;
		gameOverText.text = "GAME OVER";
	}
}

 

 DestroyByTime 脚本:

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

public class DestroyByTime : MonoBehaviour {

	// Use this for initialization
	public float lifetime=2.0f;
	void Start () {
		Destroy (gameObject,lifetime);//过一段时间再销毁
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

 

你可能感兴趣的:(Unity3D星际航行游戏完整开发过程)