unity打靶游戏的制作

您所在的位置:网站首页 打靶子的靶 unity打靶游戏的制作

unity打靶游戏的制作

2024-07-14 19:18| 来源: 网络整理| 查看: 265

 这次第一个作业是一个打靶游戏,要用到老师上课所讲的物理运动,对于这次作业来说,总结一下就是刚体和碰撞的运用,先上一个效果成品图。

如图所示,射出去的箭插在了靶上,左上角显示得分情况和风力大小,正值代表指向x轴正方向的风力,负值代表指向x轴负方向的风力。接下来我来讲一下靶和箭的制作。

首先是靶,靶就是五个不同大小的非常薄的圆柱,将它们拼接在一起即可。一下是靶的参数:

让五个圆柱按照一定的位置叠放好后,一个简单的靶就做成了,老师上课也讲了组合物理物体的制作,对于这个靶来说,就是将这个整体设置成刚体,并且把靶的重力给去掉,每个环不设置刚体,但为每一个环添加一个网格碰撞起。

接下来就是箭的制作,箭也是组成体,分为箭靶和箭头两个部分

接下来是箭的属性

箭因为和靶进行碰撞,所以组合体的属性稍有不同,这里我选择把组合体设置为刚体且为其增加网格碰撞器,而箭靶和箭身不设置刚体,只增加一下各自的碰撞器。调整好摄像机的位置后,接下来就是写脚本了。

这是我这次的uml类图:

sceneController里负责实例化各个类,射箭和设置风力等动作类统一放到GameModel里来进行,因为这次动作比较少,就不设置actionmanger了,统一放到游戏模型里来控制。ArrowFactory负责箭的生产和箭的回收,ScoreRecorder里负责计分,并掌握计分规则。ArrowCollider只负责实现与箭碰撞相关的细节,并将其挂到预置中的箭上。因为这次类的关系比较简单,我这里就不用借口了。接下来我来详细解释一下各类代码。

一:UserInterface类

private sceneController _scene; public Camera cam; public Text scoreText; public Text windText; // Use this for initialization void Start () { _scene = sceneController.getInstance (); } // Update is called once per frame void Update () { scoreText.text = "Score: " + _scene.getPoint().ToString(); windText.text = "Wind: " + _scene.getWind ().ToString (); if (Input.GetMouseButtonDown (0)) { Ray ray = cam.ScreenPointToRay (Input.mousePosition); _scene.shootArrow (ray.direction); } }

核心代码如上,这里要记录一下射线的方向,用来控制角度。

二:SceneController类

namespace Com.mygame{ public class sceneController : System.Object { private static sceneController _instance; private GameModel _gameModel; private ArrowFactory _arrowFactory; private ScoreRecorder _scoreRecorder; public static sceneController getInstance() { if (_instance == null) { _instance = new sceneController (); } return _instance; } public void setGameModel(GameModel obj) { _gameModel = obj; } public GameModel getGameModel() { return _gameModel; } public void shootArrow(Vector3 dir) { _gameModel.shootArrow (dir); } public void setArrowFactory(ArrowFactory obj) { _arrowFactory = obj; } public ArrowFactory getArrowFactory() { return _arrowFactory; } public void setScoreRecorder(ScoreRecorder obj) { _scoreRecorder = obj; } public ScoreRecorder getScoreRecorder() { return _scoreRecorder; } public int getPoint() { return _scoreRecorder.getPoint (); } public float getWind() { return _gameModel.getWind (); } } }

将其定义到命名空间里,并在里面实例化一个场记

三:GameModel类

public class GameModel : MonoBehaviour { private sceneController scene; private float speed = 30f; private GameObject arrow; private float windForce = 0f; void Start() { scene = sceneController.getInstance (); scene.setGameModel (this); } public void shootArrow(Vector3 dir) { arrow = sceneController.getInstance ().getArrowFactory().getArrow(); arrow.transform.position = new Vector3 (0, 0, -10); arrow.transform.up = dir; arrow.GetComponent ().velocity = dir * speed; setWindToArrow (arrow); windForce = Random.Range (-100, 100); } public void setWindToArrow(GameObject arrow) { arrow.GetComponent ().AddForce (new Vector3 (windForce, 0, 0), ForceMode.Force); } public float getWind() { return windForce; } void Update () { } }

这里将箭射出,并为射出去的箭添加风力,射箭时,首先从工厂中获得一支箭,为其设置好transform属性后,为其添加刚体速度和并为其添加风力。

四:ArrowFactory类

sceneController scene; private List usedArrow = new List(); private List unUsedArrow = new List (); private List existTime = new List (); private float timeStart = 0; private GameObject arrow; public static float timeEmit = 4; void Awake () { arrow = Instantiate (Resources.Load ("Prefabs/arrow")) as GameObject; arrow.SetActive (false); scene = sceneController.getInstance (); scene.setArrowFactory (this); } public GameObject getArrow() { GameObject newArrow; if (unUsedArrow.Count == 0) { newArrow = GameObject.Instantiate (arrow) as GameObject; newArrow.SetActive (true); } else { newArrow = unUsedArrow [0]; newArrow.SetActive (true); if (newArrow.GetComponent () == null) { newArrow.AddComponent (); } Component[] comp = newArrow.GetComponentsInChildren (); foreach (CapsuleCollider i in comp) { i.enabled = true; } newArrow.GetComponent ().isTrigger = true; unUsedArrow.RemoveAt (0); } usedArrow.Add (newArrow); existTime.Add (timeStart); return newArrow; } public void freeArrow() { for (int i = 0; i <  usedArrow.Count; i++) { GameObject temp; if (!usedArrow [i].activeInHierarchy) { temp = usedArrow [i]; usedArrow.RemoveAt (i); unUsedArrow.Add (temp); existTime.RemoveAt (i); temp.GetComponent ().setWhichTarget (); } } } void Update () { for (int i = 0; i < existTime.Count; i++) { existTime [i] += Time.deltaTime; if (existTime [i] >= timeEmit) { usedArrow [i].SetActive (false); } } freeArrow (); }

两个List,一个代表未使用的箭,一个代表使用了的箭,还有一个List代表这个箭存在的时间,当这个箭插在箭靶上存在超过一定时间后,将其回收,回收的时候还有将另一个类中的一个变量,也就是setWhichTarget变量,也就是打中哪一个环变量,将这个变量置为空,否则的话这个箭打中哪一个环的属性还在,影响计分。注意这里生产箭的时候,如果这个箭的刚体属性为空的话,要为这个箭同时加上刚体属性,因为在接下来的碰撞器事件中,为了使箭插在靶子上,在一碰撞时去掉了箭的刚体属性。

五:ScoreRecorder类

private sceneController scene; public int point = 0; void Awake () { scene = sceneController.getInstance (); scene.setScoreRecorder (this); } public int getPoint() { return point; } public void countPoint(string s) { if (s == "loop1") { point += 10; } if (s == "loop2") { point += 8; } if (s == "loop3") { point += 6; } if (s == "loop4") { point += 4; } if (s == "loop5") { point += 2; } }

保留分数这个变量和一些简单的计分规则。

六:ArrowCollider类

这个类就是为设置碰撞事件所用,当碰撞所触发的时候,为了使箭插在靶上,立即去掉箭的刚体属性,同时记录箭第一次触碰到的环的名字,因为靶使用圆柱叠加起来的,打到内环时可能会触碰到不止一个环,因此这里只保留第一次触碰到的环的名字。触碰发生后,同时将箭的isTRigger属性置为false,防止多次触发。

private string whichTarget; private sceneController scene; void OnTriggerEnter(Collider other) { if (whichTarget == "") { whichTarget = other.gameObject.name; Debug.Log (whichTarget); } Destroy (GetComponent ()); Component[] comp = GetComponentsInChildren (); foreach (CapsuleCollider i in comp) { i.enabled = false; } GetComponent ().isTrigger = false; scene.getScoreRecorder ().countPoint (whichTarget); } public void setWhichTarget() { whichTarget = ""; } // Use this for initialization void Awake () { whichTarget = ""; scene = sceneController.getInstance (); }

好啦,到这里游戏差不多基本就做完了,这个游戏在掌握了老师课上讲的物理学运动后,还是比较好做的。我的建议是先做预置,然后做UserInterFace和GameModel,先确保箭能够发射,在箭能够发射后,增加工厂和回收机制,最后加上计分规则和风力和碰撞器。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3