[Unity3D]Unity3D官方案例SpaceShooter開發教程
阿新 • • 發佈:2019-02-05
1、先匯入SpaceShooter的環境資源,將Models下的vehicle_playerShip放到Hierachy視窗,改名為Player.Rotation x改為270,為Player新增mesh collider元件,將vehicle_playerShip_collider放到Mesh屬性裡面,為Player新增剛體,去掉重力的勾選,將Prefebs中的engines_player放到Hierarchy,並調好位置。
2、進入3D檢視,將MainCamera中的Projection改為Orthographic,攝像機檢視變為矩形檢視。將Camered的背景改為黑色。將Player的Rotation x 改為零。Camera的Rotation改為90,移動攝像機,調節位置在Game檢視中檢視。通過調節Camera的Size來調節Player的大小,通過調節Camera的Position來調節Player的位置,適當即可。
3、新增一個Directional Light,改名為Main Light,然後reset,改Rotation x為20,y為245.Intensity改為0.75,同理繼續新增一個,改名為Fill Light,將Rotation y改為125,點開color將RGB分別改為128,192,192.在新增一個Rim Light,將Rotation x,y分別改為345,65,Indensity改為0.25,Ctrl+Shift+N建立一個GameObject,改名為Light,將三個Light放進去。
4、新增一個Quad元件,改名為Background,rotation x 90,新增一個紋理tile_nebula_green_dff,將tile_nebula_green_dff中的shader改為Unlity/Texture,將Position y 改為-10,將Scale x, y改為15和30,這是紋理圖片的大小比例決定的,1:2。
5、建立GameObject,改名為GameCotroller,新增指令碼GameCotroller.cs,為Player新增一個新的指令碼,命名為PlayerController,指令碼為:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
} 程式碼心得:限制需要在Game檢視移動來調節。記住了rigidbody的velocity方法,限制Player的飛行範圍可通過rigidbody.position來控制。學習了Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax)的用法。學習了系列化[System.Serializable]在視窗檢視中顯示。
6、建立一個GameObject,改名為Bolt,建立一個GameObject,改名為VFX,放到Bolt下,將fx_lazer_orange_dff拖到VFX Inspector中,將Shader改為Particles/Additive可將背景設定為透明。給Bolt加上RigidBody,去掉use Gravity.新增Mover指令碼:
using UnityEngine;
using System.Collections; public class Mover : MonoBehaviour {
public float speed = 20f;
// Use this for initialization
void Start () {
rigidbody.velocity = transform.forward * speed;
} }
再新增一個Capsule Collider用於碰撞檢測,將Radius和height的值設為0.05,0.55.direction設為Z-Axis,現在報錯,是因為FBX的MeshRenderer和Bolt的Capsule Collider衝突,刪掉FBX的MeshRenderer。注意一點要想把改變的同步到Prefabs中就得點選應用。
開始新增子彈,建立新的GameObject,命名為SpawnPos放到Player下面。繼續編輯PlayerController指令碼。程式碼如下:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
public GameObject bolt;
public Transform spawnPos;
void Update()
{
if(Input.GetButton("Fire1"))
{
Instantiate(bolt, spawnPos.position, spawnPos.rotation);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
}
問題:運行遊戲,發現遊戲的子彈是散的。將Bolt裡面的is Trigger勾選上可防止這種情況的出現。現在發現子彈的發射過於連續,新增程式碼:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
public GameObject bolt;
public Transform spawnPos;
public float fireRate = 0.1f;
private float nextFire;
void Update()
{
if(Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Instantiate(bolt, spawnPos.position, spawnPos.rotation);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
}
Bolt(clone)不會消失,現在開始製作子彈的邊界。
建立一個cube,改名為Boundary,將Box Collider的Size改為15 和 30,位置調節到與Background位置一致。刪除掉mesh collider等元件,新增指令碼DesdroyByBoundary。程式碼如下:
using UnityEngine;
using System.Collections; public class DestroyByBoundary : MonoBehaviour
{ void OnTriggerExit(Collider other)
{
Destroy(other.gameObject);
}
}
現在開始建立隕石,建立新的GameObject,改名為Asteroid,將prop_asteroid_01拖入其中,新增Rigidbody和Capsule Collider,修改引數使Capsule Collider與物體差不多吻合。RigidBody去掉use Gravity.新增一個指令碼,RandomRotation,程式碼如下:
using UnityEngine;
using System.Collections; public class RandomRotation : MonoBehaviour { public float tumble = 5;
// Use this for initialization
void Start () {
rigidbody.angularVelocity = Random.insideUnitSphere * tumble;
}
} Asteroid新增一個Mover,改Speed為-5。現在隕石可以向下旋轉且下落。
同理新增Asteroid2和Asteroid3.
新增一個指令碼,改名為DestroyByCantact,如下:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour { void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
Destroy(other.gameObject);
Destroy(this.gameObject);
}
} 新增到各個Asteroid中。
DestroyByCantact新增程式碼:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour {
public GameObject explossion;
public GameObject playerExplosion;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
if(other.gameObject.tag == "player")
{
Instantiate(playerExplosion, this.transform.position, this.transform.rotation);
}
Destroy(other.gameObject);
Destroy(this.gameObject);
Instantiate(explossion, this.transform.position, this.transform.rotation);
}
} 將各個爆炸效果分別拖到指令碼中,應用到Prefabs當中。
接下來給GameCotroller指令碼加程式碼:
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
// Use this for initialization
void Start()
{ } // Update is called once per frame
void Update()
{
if (Random.value < 0.1)
{
Spawn();
}
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
}
將三個隕石分別新增到Hazards裡面。
繼續修改GameController程式碼:
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
public int numPerWave = 10; public float startWait = 2f; //出現小行星之前的等待時間
public float spanWait = 1f; //一波小行星內的間隔時間
public float waveWait = 4f; //每兩波時間間隔
// Use this for initialization
void Start()
{
StartCoroutine(SpawnWaves());
} // Update is called once per frame
void Update()
{
//if (Random.value < 0.1)
//{
// Spawn();
//}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while(true)
{
for (int i = 0; i < numPerWave; i++)
{
Spawn();
yield return new WaitForSeconds(spanWait);
}
yield return new WaitForSeconds(waveWait);
}
} private void WaitForSeconds(float spanWait)
{
throw new System.NotImplementedException();
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
}
裡面涉及到技巧性。
新增音效,有幾個可以直接新增。對於player發射子彈的聲音可以在程式碼中新增。
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
public GameObject bolt;
public Transform spawnPos;
public float fireRate = 0.1f;
private float nextFire;
public AudioClip fire;
void Update()
{
if(Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Instantiate(bolt, spawnPos.position, spawnPos.rotation);
audio.PlayOneShot(fire);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
}
新增指令碼將爆炸效果去除
建立DestroyByTime,如下:
using UnityEngine;
using System.Collections; public class DestroyByTime : MonoBehaviour { public float lifeTime = 2;
// Use this for initialization
void Start () {
Destroy(this.gameObject, lifeTime);
}
// Update is called once per frame
void Update () {
}
}
新增分數,建立一個GUIText,修改y為1,修改程式碼GameController
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
public int numPerWave = 10; public float startWait = 2f; //出現小行星之前的等待時間
public float spanWait = 1f; //一波小行星內的間隔時間
public float waveWait = 4f; //每兩波時間間隔 public GUIText scoreText;
private int score;
// Use this for initialization
void Start()
{
StartCoroutine(SpawnWaves());
scoreText.text = "Score: " + score;
} // Update is called once per frame
void Update()
{
//if (Random.value < 0.1)
//{
// Spawn();
//}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while(true)
{
for (int i = 0; i < numPerWave; i++)
{
Spawn();
yield return new WaitForSeconds(spanWait);
}
yield return new WaitForSeconds(waveWait);
}
} private void WaitForSeconds(float spanWait)
{
throw new System.NotImplementedException();
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
public void AddScore(int v)
{
score += v;
scoreText.text = "Score: " + score;
}
}
將GameController物體的TAG改為GameController,修改DesdroyByContact指令碼:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour {
public GameObject explossion;
public GameObject playerExplosion; private GameController gameController;
public int score = 10;
void Start()
{
GameObject gameControllerObject = GameObject.FindWithTag("GameController");
if(gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent<GameController>();
}
if(gameControllerObject == null)
{
Debug.Log("TaoCheng");
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
if(other.gameObject.tag == "player")
{
Instantiate(playerExplosion, this.transform.position, this.transform.rotation);
}
if(other.gameObject.tag == "enemy")
{
return;
}
Destroy(other.gameObject);
gameController.AddScore(score);
Destroy(this.gameObject);
Instantiate(explossion, this.transform.position, this.transform.rotation);
}
}
做顯示遊戲結束和遊戲重新開始。
GameCotroller指令碼程式碼如下:
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
public int numPerWave = 10; public float startWait = 2f; //出現小行星之前的等待時間
public float spanWait = 1f; //一波小行星內的間隔時間
public float waveWait = 4f; //每兩波時間間隔 public GUIText scoreText;
private int score;
private bool gameOver;
public GUIText gameOverText;
public GUIText helpText;
// Use this for initialization
void Start()
{
StartCoroutine(SpawnWaves());
scoreText.text = "Score: " + score;
gameOverText.text = "";
helpText.text = "";
} // Update is called once per frame
void Update()
{
if(gameOver && Input.GetKeyDown(KeyCode.R))
{
Application.LoadLevel(Application.loadedLevel);
}
//if (Random.value < 0.1)
//{
// Spawn();
//}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while(true)
{
for (int i = 0; i < numPerWave; i++)
{
Spawn();
yield return new WaitForSeconds(spanWait);
}
yield return new WaitForSeconds(waveWait);
if (gameOver)
break;
}
} private void WaitForSeconds(float spanWait)
{
throw new System.NotImplementedException();
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
public void AddScore(int v)
{
score += v;
scoreText.text = "Score: " + score;
}
public void GameOver()
{
gameOver = true;
gameOverText.text = "Game Over!";
helpText.text = "Press 'R' to Restart!";
}
}
DestroyByContact指令碼程式碼如下:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour {
public GameObject explossion;
public GameObject playerExplosion; private GameController gameController;
public int score = 10;
void Start()
{
GameObject gameControllerObject = GameObject.FindWithTag("GameController");
if(gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent<GameController>();
}
if(gameControllerObject == null)
{
Debug.Log("TaoCheng");
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
if(other.gameObject.tag == "Player")
{
Instantiate(playerExplosion, this.transform.position, this.transform.rotation);
gameController.GameOver();
Debug.Log("Error");
}
if(other.gameObject.tag == "enemy")
{
return;
}
Destroy(other.gameObject);
gameController.AddScore(score);
Destroy(this.gameObject);
Instantiate(explossion, this.transform.position, this.transform.rotation);
}
}
設定一個GUIText組,分別新增到程式碼中。
SpaceShooter基本功能完成。
2、進入3D檢視,將MainCamera中的Projection改為Orthographic,攝像機檢視變為矩形檢視。將Camered的背景改為黑色。將Player的Rotation x 改為零。Camera的Rotation改為90,移動攝像機,調節位置在Game檢視中檢視。通過調節Camera的Size來調節Player的大小,通過調節Camera的Position來調節Player的位置,適當即可。
3、新增一個Directional Light,改名為Main Light,然後reset,改Rotation x為20,y為245.Intensity改為0.75,同理繼續新增一個,改名為Fill Light,將Rotation y改為125,點開color將RGB分別改為128,192,192.在新增一個Rim Light,將Rotation x,y分別改為345,65,Indensity改為0.25,Ctrl+Shift+N建立一個GameObject,改名為Light,將三個Light放進去。
4、新增一個Quad元件,改名為Background,rotation x 90,新增一個紋理tile_nebula_green_dff,將tile_nebula_green_dff中的shader改為Unlity/Texture,將Position y 改為-10,將Scale x, y改為15和30,這是紋理圖片的大小比例決定的,1:2。
5、建立GameObject,改名為GameCotroller,新增指令碼GameCotroller.cs,為Player新增一個新的指令碼,命名為PlayerController,指令碼為:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
} 程式碼心得:限制需要在Game檢視移動來調節。記住了rigidbody的velocity方法,限制Player的飛行範圍可通過rigidbody.position來控制。學習了Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax)的用法。學習了系列化[System.Serializable]在視窗檢視中顯示。
6、建立一個GameObject,改名為Bolt,建立一個GameObject,改名為VFX,放到Bolt下,將fx_lazer_orange_dff拖到VFX Inspector中,將Shader改為Particles/Additive可將背景設定為透明。給Bolt加上RigidBody,去掉use Gravity.新增Mover指令碼:
using UnityEngine;
using System.Collections; public class Mover : MonoBehaviour {
public float speed = 20f;
// Use this for initialization
void Start () {
rigidbody.velocity = transform.forward * speed;
} }
再新增一個Capsule Collider用於碰撞檢測,將Radius和height的值設為0.05,0.55.direction設為Z-Axis,現在報錯,是因為FBX的MeshRenderer和Bolt的Capsule Collider衝突,刪掉FBX的MeshRenderer。注意一點要想把改變的同步到Prefabs中就得點選應用。
開始新增子彈,建立新的GameObject,命名為SpawnPos放到Player下面。繼續編輯PlayerController指令碼。程式碼如下:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
public GameObject bolt;
public Transform spawnPos;
void Update()
{
if(Input.GetButton("Fire1"))
{
Instantiate(bolt, spawnPos.position, spawnPos.rotation);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
}
問題:運行遊戲,發現遊戲的子彈是散的。將Bolt裡面的is Trigger勾選上可防止這種情況的出現。現在發現子彈的發射過於連續,新增程式碼:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
public GameObject bolt;
public Transform spawnPos;
public float fireRate = 0.1f;
private float nextFire;
void Update()
{
if(Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Instantiate(bolt, spawnPos.position, spawnPos.rotation);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
}
Bolt(clone)不會消失,現在開始製作子彈的邊界。
建立一個cube,改名為Boundary,將Box Collider的Size改為15 和 30,位置調節到與Background位置一致。刪除掉mesh collider等元件,新增指令碼DesdroyByBoundary。程式碼如下:
using UnityEngine;
using System.Collections; public class DestroyByBoundary : MonoBehaviour
{ void OnTriggerExit(Collider other)
{
Destroy(other.gameObject);
}
}
現在開始建立隕石,建立新的GameObject,改名為Asteroid,將prop_asteroid_01拖入其中,新增Rigidbody和Capsule Collider,修改引數使Capsule Collider與物體差不多吻合。RigidBody去掉use Gravity.新增一個指令碼,RandomRotation,程式碼如下:
using UnityEngine;
using System.Collections; public class RandomRotation : MonoBehaviour { public float tumble = 5;
// Use this for initialization
void Start () {
rigidbody.angularVelocity = Random.insideUnitSphere * tumble;
}
} Asteroid新增一個Mover,改Speed為-5。現在隕石可以向下旋轉且下落。
同理新增Asteroid2和Asteroid3.
新增一個指令碼,改名為DestroyByCantact,如下:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour { void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
Destroy(other.gameObject);
Destroy(this.gameObject);
}
} 新增到各個Asteroid中。
DestroyByCantact新增程式碼:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour {
public GameObject explossion;
public GameObject playerExplosion;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
if(other.gameObject.tag == "player")
{
Instantiate(playerExplosion, this.transform.position, this.transform.rotation);
}
Destroy(other.gameObject);
Destroy(this.gameObject);
Instantiate(explossion, this.transform.position, this.transform.rotation);
}
} 將各個爆炸效果分別拖到指令碼中,應用到Prefabs當中。
接下來給GameCotroller指令碼加程式碼:
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
// Use this for initialization
void Start()
{ } // Update is called once per frame
void Update()
{
if (Random.value < 0.1)
{
Spawn();
}
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
}
將三個隕石分別新增到Hazards裡面。
繼續修改GameController程式碼:
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
public int numPerWave = 10; public float startWait = 2f; //出現小行星之前的等待時間
public float spanWait = 1f; //一波小行星內的間隔時間
public float waveWait = 4f; //每兩波時間間隔
// Use this for initialization
void Start()
{
StartCoroutine(SpawnWaves());
} // Update is called once per frame
void Update()
{
//if (Random.value < 0.1)
//{
// Spawn();
//}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while(true)
{
for (int i = 0; i < numPerWave; i++)
{
Spawn();
yield return new WaitForSeconds(spanWait);
}
yield return new WaitForSeconds(waveWait);
}
} private void WaitForSeconds(float spanWait)
{
throw new System.NotImplementedException();
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
}
裡面涉及到技巧性。
新增音效,有幾個可以直接新增。對於player發射子彈的聲音可以在程式碼中新增。
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float zMin = -3.3f;
public float zMax = 14f;
public float xMin = -6.5f;
public float xMax = 6.5f;
}
public class PlayerController : MonoBehaviour {
public float speed = 10f;
public Boundary bound;
public GameObject bolt;
public Transform spawnPos;
public float fireRate = 0.1f;
private float nextFire;
public AudioClip fire;
void Update()
{
if(Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Instantiate(bolt, spawnPos.position, spawnPos.rotation);
audio.PlayOneShot(fire);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 move = new Vector3(h, 0, v);
rigidbody.velocity = speed * move;
rigidbody.position = new Vector3(Mathf.Clamp(rigidbody.position.x, bound.xMin, bound.xMax), 0, Mathf.Clamp(rigidbody.position.z, bound.zMin, bound.zMax));
}
}
新增指令碼將爆炸效果去除
建立DestroyByTime,如下:
using UnityEngine;
using System.Collections; public class DestroyByTime : MonoBehaviour { public float lifeTime = 2;
// Use this for initialization
void Start () {
Destroy(this.gameObject, lifeTime);
}
// Update is called once per frame
void Update () {
}
}
新增分數,建立一個GUIText,修改y為1,修改程式碼GameController
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
public int numPerWave = 10; public float startWait = 2f; //出現小行星之前的等待時間
public float spanWait = 1f; //一波小行星內的間隔時間
public float waveWait = 4f; //每兩波時間間隔 public GUIText scoreText;
private int score;
// Use this for initialization
void Start()
{
StartCoroutine(SpawnWaves());
scoreText.text = "Score: " + score;
} // Update is called once per frame
void Update()
{
//if (Random.value < 0.1)
//{
// Spawn();
//}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while(true)
{
for (int i = 0; i < numPerWave; i++)
{
Spawn();
yield return new WaitForSeconds(spanWait);
}
yield return new WaitForSeconds(waveWait);
}
} private void WaitForSeconds(float spanWait)
{
throw new System.NotImplementedException();
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
public void AddScore(int v)
{
score += v;
scoreText.text = "Score: " + score;
}
}
將GameController物體的TAG改為GameController,修改DesdroyByContact指令碼:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour {
public GameObject explossion;
public GameObject playerExplosion; private GameController gameController;
public int score = 10;
void Start()
{
GameObject gameControllerObject = GameObject.FindWithTag("GameController");
if(gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent<GameController>();
}
if(gameControllerObject == null)
{
Debug.Log("TaoCheng");
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
if(other.gameObject.tag == "player")
{
Instantiate(playerExplosion, this.transform.position, this.transform.rotation);
}
if(other.gameObject.tag == "enemy")
{
return;
}
Destroy(other.gameObject);
gameController.AddScore(score);
Destroy(this.gameObject);
Instantiate(explossion, this.transform.position, this.transform.rotation);
}
}
做顯示遊戲結束和遊戲重新開始。
GameCotroller指令碼程式碼如下:
using UnityEngine;
using System.Collections; public class GameController : MonoBehaviour
{ public Vector3 spawnValues;
public GameObject[] hazards;
public int numPerWave = 10; public float startWait = 2f; //出現小行星之前的等待時間
public float spanWait = 1f; //一波小行星內的間隔時間
public float waveWait = 4f; //每兩波時間間隔 public GUIText scoreText;
private int score;
private bool gameOver;
public GUIText gameOverText;
public GUIText helpText;
// Use this for initialization
void Start()
{
StartCoroutine(SpawnWaves());
scoreText.text = "Score: " + score;
gameOverText.text = "";
helpText.text = "";
} // Update is called once per frame
void Update()
{
if(gameOver && Input.GetKeyDown(KeyCode.R))
{
Application.LoadLevel(Application.loadedLevel);
}
//if (Random.value < 0.1)
//{
// Spawn();
//}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while(true)
{
for (int i = 0; i < numPerWave; i++)
{
Spawn();
yield return new WaitForSeconds(spanWait);
}
yield return new WaitForSeconds(waveWait);
if (gameOver)
break;
}
} private void WaitForSeconds(float spanWait)
{
throw new System.NotImplementedException();
}
void Spawn()
{
GameObject o = hazards[Random.Range(0, hazards.Length)];
Vector3 p = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion q = Quaternion.identity;
Instantiate(o, p, q);
}
public void AddScore(int v)
{
score += v;
scoreText.text = "Score: " + score;
}
public void GameOver()
{
gameOver = true;
gameOverText.text = "Game Over!";
helpText.text = "Press 'R' to Restart!";
}
}
DestroyByContact指令碼程式碼如下:
using UnityEngine;
using System.Collections; public class DestroyByCantact : MonoBehaviour {
public GameObject explossion;
public GameObject playerExplosion; private GameController gameController;
public int score = 10;
void Start()
{
GameObject gameControllerObject = GameObject.FindWithTag("GameController");
if(gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent<GameController>();
}
if(gameControllerObject == null)
{
Debug.Log("TaoCheng");
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Boundary")
{
return;
}
if(other.gameObject.tag == "Player")
{
Instantiate(playerExplosion, this.transform.position, this.transform.rotation);
gameController.GameOver();
Debug.Log("Error");
}
if(other.gameObject.tag == "enemy")
{
return;
}
Destroy(other.gameObject);
gameController.AddScore(score);
Destroy(this.gameObject);
Instantiate(explossion, this.transform.position, this.transform.rotation);
}
}
設定一個GUIText組,分別新增到程式碼中。
SpaceShooter基本功能完成。