我是靠谱客的博主 含蓄金针菇,这篇文章主要介绍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脚本代码初步,飞船可以上下左右移动

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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<Rigidbody>().velocity=movement*speed;//刚体属性有速度,就可以运动 } }

 

2、第二步

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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<Rigidbody>().velocity=movement*speed;//刚体属性有速度,就可以运动 Rigidbody rb=GetComponent<Rigidbody>(); 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)实例化可以自动产生子弹

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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<Rigidbody>().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代码,使飞船能够发射子弹,并且能够不断产生子弹

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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<Rigidbody>().velocity=movement*speed;//刚体属性有速度,就可以运动 Rigidbody rb=GetComponent<Rigidbody>(); 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<Transform>().position,shotSpawn.GetComponent<Transform>().rotation);//用来自动发射子弹 } } }


6、第六步

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

优化NewBehaviourScript代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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<Rigidbody>().velocity=movement*speed;//刚体属性有速度,就可以运动 Rigidbody rb=GetComponent<Rigidbody>(); 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<Transform>().position,shotSpawn.GetComponent<Transform>().rotation);//用来自动发射子弹 Instantiate(shot,shotSpawn.position,shotSpawn.rotation); } } }


7、第七步

DestroyByBoundary代码挂载在Boundary

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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<Rigidbody>().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初步代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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、第四步

优化代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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、第六步

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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、第九步

产生多轮小行星:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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

代码如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 补充:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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<Rigidbody>().velocity=movement*speed;//刚体属性有速度,就可以运动 Rigidbody rb=GetComponent<Rigidbody>(); 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<Transform>().position,shotSpawn.GetComponent<Transform>().rotation);//用来自动发射子弹 Instantiate(shot,shotSpawn.position,shotSpawn.rotation); GetComponent<AudioSource>().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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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> ();//拿到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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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脚本:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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<Rigidbody>().velocity=movement*speed;//刚体属性有速度,就可以运动 Rigidbody rb=GetComponent<Rigidbody>(); 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<Transform>().position,shotSpawn.GetComponent<Transform>().rotation);//用来自动发射子弹 Instantiate(shot,shotSpawn.position,shotSpawn.rotation); GetComponent<AudioSource>().Play ();//发射子弹有声音 } } }

DestroyByBoundary 脚本:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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脚本:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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> ();//拿到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脚本:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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<Rigidbody>().angularVelocity = Random.insideUnitSphere*tumble;//单位球体之间取随机值 } // Update is called once per frame void Update () { } }

Mover脚本:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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<Rigidbody>().velocity=transform.forward*speed;//向正前方飞 } // Update is called once per frame void Update () { } }

GameController脚本:

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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 脚本:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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星际航行游戏完整开发过程一、准备工作 三、小行星四、音频添加五、计分器、游戏结束和重新开始文本框六、总结的全部内容,更多相关Unity3D星际航行游戏完整开发过程一、准备工作内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部