发表时间:2022-03-25来源:网络
游戏简介:一个只能移动枪口的射击游戏,敌人会在前方场景随机生成,需要玩家在20秒的时间内尽可能多地开枪击杀。
先导入网上找到的场景模型、枪支模型(网上找来的免费资源,感谢网友!),如图:

然后对枪编写脚本:

为方便就不事先获得枪支的Transform引用,直接gameObject.GetComponent调用Transform组件下的LookAt方法,该方法可使枪向射线与场景碰撞点处调整方向,因此事先要将为场景模型添加Mesh Collider,也因此在游戏测试时如果将鼠标指向天空等无碰撞体的地方,枪支则不会移动。(可通过在背景处创建一个蓝色的Plane当作天空来解决此问题)

在为场景模型添加碰撞体时,有时候会有多种碰撞体可选,因为这里我们要碰撞体仅仅是为了得到一个碰撞点令枪可以移动,所以可以选择简单一些的碰撞体模型,一般碰撞体的复杂程度可由上图中的verts(顶点)来确定,顶点越少,计算量越小,游戏运行越流畅。
注意:测试时可能会发现枪支随鼠标的旋转很不自然(绕着枪中心处旋转),现实中应该是绕着射手的肩膀旋转,因此应将旋转中心设置在枪的后部,这可以通过创建空物体以及父子关系来调整。因此以上脚本应该挂载到作为父物体的空物体上:

在gun父物体下再创建一个空物体RedPoint,位置设置在枪口(因为红光是从枪口射出的,不是从枪中间射出的),并为其添加Line Renderer组件,设置好其颜色、宽度。(具体步骤上文“线特效”处有提到)
然后补充脚本:
private Ray ray; private RaycastHit hit; private Transform gunTransform; private Transform pointTransform; private LineRenderer rayLineRenderer; void Start() { gunTransform = gameObject.GetComponent(); pointTransform = gunTransform.FindChild("RedPoint"); rayLineRenderer = pointTransform.gameObject.GetComponent(); } void Update() { ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray,out hit)) { gunTransform.LookAt(hit.point); rayLineRenderer.SetPosition(0, pointTransform.position); rayLineRenderer.SetPosition(1, hit.point); } }这里要通过gun下面的子物体RedPoint生成红光,但脚本是挂载在gun上的,因此要通过FindChild方法得到RedPoint及其LineRenderer组件的引用。
最后通过SetPosition绘制红线,这里有两个参数,第一个是射线经过的路程上的拐点的索引,第二个是位置。脚本中设置了两个拐点(其实就是一条线段,如果有三个不在同一直线上的拐点,则红线由两条线段组成),最终效果:
导入僵尸模型,调整其大小,并为其及其所有零部件(子物体)的标签设置为Zombie。
因为模型本身没有自带碰撞体组件,需要手动添加,因为本人使用的模型过于复杂(还有动画效果),因此仅对父物体添加一个胶囊型的碰撞体(覆盖其头部与身体)。考虑到其动画会使其向前稍微移动,因此碰撞体的位置靠前一些。

然后编写脚本:(接在rayLineRenderer.SetPosition后面)
if (hit.collider.tag == "Zombie" && Input.GetMouseButtonDown(0)) { zombieTransform = hit.collider.gameObject.GetComponent(); zombieTransform.Rotate(Vector3.left, 90); GameObject.Destroy(hit.collider.gameObject, 2); }当向鼠标指向处发射的射线碰撞到的是僵尸,且按下鼠标左键(开火),则首先获取到僵尸的Transform组件的引用,然后旋转(击倒效果),并在2秒后销毁该物体。
如果有较好的模型,可对模型的所有零部件(子物体)添加碰撞体,则脚本应该为:(接在rayLineRenderer.SetPosition后面)
if (hit.collider.tag == "Zombie" && Input.GetMouseButtonDown(0)) { Transform zombieParent = hit.collider.gameObject.GetComponent().parent; Transform[] zombie = zombieParent.GetComponentsInChildren(); for (int i = 0; i (); } zombieParent.Rotate(Vector3.left, 90); GameObject.Destroy(zombieParent.gameObject, 2); }因为碰撞到的是模型的子物体,所以通过.parent得到父物体的Transform组件,进而通过GetComponentsInChildren得到所有零部件的Transform组件,最后通过循环对所有子物体添加Rigidbody,这样一来,僵尸会“四分五裂”,一方面因为重力,另一方面是因为各个子物体间的碰撞体有重合,添加Rigidbody后各部分会自发散开。
接下来新建一个实例化僵尸的脚本:
public GameObject prefabZombie; float i = 0; void Update() { if (i>1) { Vector3 position = new Vector3(Random.Range(-35,0),2.6f,Random.Range(-10,-5)); GameObject.Instantiate(prefabZombie, position, .identity); i = 0; } i += Time.deltaTime; }在合适的区域每秒生成一个僵尸,这里用累加Time.deltaTime的方式实现每秒执行,也可以用Invoke函数实现。
为了方便管理生成的僵尸,我们可以将所有生成的僵尸设置为一个空物体的子物体:
public GameObject prefabZombie; public Transform zombieControler; void Start() { zombieControler = gameObject.GetComponent(); InvokeRepeating("Creat", 1, 1); } void Creat() { Vector3 position = new Vector3(Random.Range(-35, 0), 2.6f, Random.Range(-10, -5)); GameObject.Instantiate(prefabZombie, position, .identity); newZombie.GetComponent().SetParent(zombieControler); }用SetParent方法即可实现,最后将该脚本挂载到空物体ZombieControler上即可。
添加开枪音效:
private AudioSource gunSound; void Start() { gunSound = gameObject.GetComponent(); } ... if (Input.GetMouseButtonDown(0)) { gunSound.Play(); if (hit.collider.tag == "Zombie") { ... } }然后为挂载以上脚本的枪支模型添加Audio Source组件,选择合适的开枪音效即可。(注意不要勾选Play On Awake和Loop)
接下来创建UI界面,先将游戏分为三个状态:开始、游戏中以及结束,并编辑对应的UI(创建空物体,添加GUIText组件并调整文字位置、大小、颜色),以下是UI叠加在一起的Game界面:
开始界面要有游戏玩法的基本介绍以及“开始游戏”的按钮,游戏中需要显示分数以及剩余时间,游戏结束需要分数统计、“重新开始”按钮和“退出游戏”按钮。
接下来对父物体UI,创建脚本:
首先编辑一个控制游戏状态的方法(这里采用枚举类型,主要是为了直观,要我写可能就用0、1、2来表示了)。
并将UI在某状态是否显示进行规定:(类似的就省略不写了)
public enum GameState { Start, Gaming, End } private GameObject startUI; ... void Start() { startUI = GameObject.Find("Start"); ... ChangeState(GameState.Start); } public void ChangeState(GameState state) { if (state==GameState.Start) { startUI.SetActive(true); gamingUI.SetActive(false); endUI.SetActive(false); ... } if (state == GameState.Gaming) { ... } if (state == GameState.End) { ... } }这里需要注意的是ChangeState要为public,因为其他脚本的一些操作也会改变游戏状态。(例如点击开始游戏按钮)
接下来编辑“开始游戏”按钮,以下脚本挂载在“StartSign”:
private UIContorl uiContorl; void Start() { uiContorl = GameObject.Find("UI").GetComponent(); } void OnMouseDown() { uiContorl.ChangeState(UIContorl.GameState.Gaming); }首先查找到父物体UI挂载的脚本中的ChangeState方法,只要MouseDown就改变游戏状态。
同理可设置重新开始按钮和退出按钮,其中退出按钮极为简单:
void OnMouseDown() { Application.Quit(); }当在游戏开始和结束状态时,枪支无法移动,因此要对Move脚本进行编辑:
public void ChangeGunMove(bool state) { f = state; } void Update() { if (f) { ... } }然后在ChangeState方法中的对应阶段设置state为true或false即可。
开始和结束阶段僵尸也无法生成,因此Invoke不能写在Start里面,更改CreateZombie脚本:(以下为CreateZombie脚本的完整版)

在ChangeState的Gaming状态下调用CreateZombie即可,另外,在游戏结束时,除了要CancelInvoke,还要把玩家未消灭的僵尸清除。
接下来要在Gaming中显示分数,在UIControl脚本中添加:
public void AddScore() { score++; scoreText.text = "击杀数:"+score; }然后在Move脚本中添加:
if (hit.collider.tag == "Zombie") { uiContorl.AddScore(); ... }每次进入到Gaming状态,要重置分数,在结束状态也要再显示一次分数:
if (state == GameState.Gaming) { score = 0; scoreText.text = "击杀数:" + score; ... } if (state == GameState.End) { finalScore.text = "最终击杀数:" + score; ... }接下来显示剩余时间,在UIControl脚本中添加:
void Update() { if (startTime) { time -= Time.deltaTime; timeText.text = "剩余时间:" + Math.Round(time, 2); if (timestartTime为bool类型,因为Update时刻运行,因此添加该变量确保倒计时只在Gaming状态下运行。
if (state == GameState.Gaming) { startTime = true; time = 20; ... }至此全部脚本编写完毕。
Game界面:

Build后运行结果:(分别是开始界面、游戏界面、结束界面)



原谅我懒得细调开始和结束UI的位置……
最后放出Move脚本:

UIControll脚本:


最后提醒:
做项目前一定要仔细规划(游戏阶段划分、资源模型的管理、脚本,尤其是各种变量名编写一定要注意,我在写的时候差点被自己编的变量名绕晕),此外还有脚本中各个变量的访问修饰符(public还是private一定要搞清楚)。
实际上,如果是个人开发,变量全写public也可以,但这并不是什么好习惯,尤其是在日后团队协作全写public就是坑队友嘛,所以建议现在开始就养成好习惯,细究public和private。
本文部分内容来自擅码网(http://www.mkcode.net)Unity 3D课程,经本人学习、整理得来,若有错漏,欢迎指正!
上一篇:Python编程从入门到实践
皓盘云建最新版下载v9.0 安卓版
53.38MB |商务办公
ris云客移动销售系统最新版下载v1.1.25 安卓手机版
42.71M |商务办公
粤语翻译帮app下载v1.1.1 安卓版
60.01MB |生活服务
人生笔记app官方版下载v1.19.4 安卓版
125.88MB |系统工具
萝卜笔记app下载v1.1.6 安卓版
46.29MB |生活服务
贯联商户端app下载v6.1.8 安卓版
12.54MB |商务办公
jotmo笔记app下载v2.30.0 安卓版
50.06MB |系统工具
鑫钜出行共享汽车app下载v1.5.2
44.7M |生活服务