扔飞镖游戏
日落西山紅霞飛~戰士打靶把營歸呀巴扎嘿。今天我制作一個簡單的打靶游戲(扔飛鏢)
在制作之前首先要思考這個游戲需要什么對象,很簡單,一只飛鏢、一個靶。
這里我把飛鏢設置成了剛體,什么是剛體?簡而言之,就是給這個物體加上了物理引擎,有了剛體,這個對象可以發生正常的碰撞,可以有質量、有阻力、有重力。這些屬性自然我們可以通過時時改變游戲對象的Position和Rotation來模擬。但是這樣子的話我們要時刻計算這個對象每個點對應的狀態,計算開銷十分之大。然而剛體就幫我們完成了所有的一切。
值得注意的是,剛體中通過改變位置來改變狀態和通過施加力來改變位置這兩種方法不能共存,剛體中Is Kinematic屬性可以勾選是否為運動學,在運動學狀態下,對象不再受力的作用,反之亦然。
剛體往往要配合碰撞器來使用,基礎的碰撞器有盒碰撞器、球碰撞器等等,他們有自己的中心位置、大小等屬性。比如一個球碰撞器:
綠線范圍就是這個碰撞器的感應邊緣
碰撞器可以理解為一個看不見的防御網,一旦有物體進入這個網,都會根據物理引擎模擬出被撞飛的效果(當然誰撞飛既取決于質量,也取決于是否為靜態碰撞器,詳情請查詢具體的碰撞器和剛體的知識)
下面說一下我設計的思路
靶我是通過五個球體通過修改Z值變成圓餅做成的
對象樹和做出來的效果如圖
靶是一個空對象。這里對靶不設置為剛體,因為我把它作為了靜態碰撞器。由于射中不同的環分數不一樣,因此每個子對象都添加了一個碰撞器,這樣子就能根據飛鏢到底是撞到了哪個子對象從而可以計算相應的分數。
理想很豐滿,現實很骨感,想用網格碰撞器,但是面太多不能用,用球碰撞器又不能把檢測范圍做成圓餅
這種范圍就像結界一樣,飛鏢無論多快都無法穿過,隔空就被撞飛了。
那該怎么辦呢?后來我有了新思路,就保持這種球體碰撞器,不同的是把它們都設為觸發器,飛鏢每穿過一個觸發器就把這個觸發器發送給靶,然后當飛鏢頭部剛好和靶重合的時候,把飛鏢的剛體設為運動學,這樣一來可以使得飛鏢無法受到里的作用而產生飛鏢卡在了靶上的效果,同時靶對象保存的最后一個觸發器就是飛鏢扎中的那個圓環。
那么思路明確了我們就可以開始做了。首先要有靶和飛鏢吧,靶在上面已經做好了,那么展示一下我的飛鏢(感覺像一個導彈)
代碼也很簡單,搞了三個類
1.Arrow類
這個就是飛鏢的類
具體有如下幾個功能:
- 在未射出時跟隨鼠標改變位置
- 當扔出后給它施加力
便于重新開始,設置了Init函數用于初始化,IsFly判斷是否被扔出,time記錄飛行時間,為了模擬真實仍飛鏢的情景,0.5秒內我給了飛鏢一個向上的力,之后飛鏢就只有重力和向前的力
代碼如下:
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Arrow : MonoBehaviour {private int IsFly;private float time;private void Start(){Init();}public void Init(){IsFly = 0;transform.position = new Vector3(0, 0, -7);gameObject.GetComponent<Rigidbody>().isKinematic = false;gameObject.GetComponent<Rigidbody>().useGravity = false;}// Update is called once per framevoid Update () {if (IsFly == 0){Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position); // 目的獲取z,在Start方法 Vector3 mousePos = Input.mousePosition;mousePos.z = screenPos.z; // 這個很關鍵 Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos);this.transform.position = worldPos;if (Input.GetButtonDown("Fire1")){IsFly = 1;time = 0;}} else{time += Time.deltaTime;}}private void FixedUpdate(){if (IsFly == 1){Rigidbody rigid = this.gameObject.GetComponent<Rigidbody>();if (rigid){if (time < 0.5){rigid.AddForce(new Vector3(0, 5, 10));}else{rigid.AddForce(new Vector3(0, 0, 15));rigid.useGravity = true;}}}} }2.Target類
這個掛載在靶這個父對象身上,Catch判斷飛鏢是否被觸發器捕捉到(沒被捕捉到表示沒有扎在靶上),Score記錄得分,trigger記錄最后一個被觸發的觸發器,arrow則是飛鏢對象。
由于飛鏢移動較快,檢測可能沒那么迅速,所以用了連續檢測。由于我把靶放在了(0,0,0)位置上,所以只要當飛鏢的位置的Z>0.05(飛鏢頭進入了靶)就可以把飛鏢設為運動學。
代碼:
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Target : MonoBehaviour {public int Catch;public int Score;private static Trigger trigger;public static Arrow arrow;// Use this for initializationprivate void Start(){print("hh");Init(); }public void Init(){if (arrow == null)arrow = Instantiate<Arrow>(Resources.Load<Arrow>("Prefabs/飛鏢"));Catch = 0;Score = -1;trigger = null;arrow.Init();}public void Catched(){Catch = 1;}public static void SetTrigger(Trigger tri){trigger = tri;}private void OnGUI(){if (Score != -1){GUI.Label(new Rect(400, 80, 100, 30), "Your Score is " + Score);GUI.Label(new Rect(400, 100, 150, 30), "push blank to rebegin");}}// Update is called once per framevoid Update () {if (Input.GetAxis("Jump") > 0)Init();if (Catch == 1){if (arrow.transform.position.z > 0.05){arrow.GetComponent<Rigidbody>().isKinematic = true;arrow.GetComponent<Rigidbody>().useGravity = false;print(trigger.gameObject.name);switch(trigger.gameObject.name){case "圈1":Score = 5;break;case "圈2":Score = 4;break;case "圈3":Score = 3;break;case "圈4":Score = 2;break;case "圈5":Score = 1;break;}}return;}if (arrow.transform.position.z > 0.5)Score = 0;} }3.Trigger類
首先我們要把每個碰撞器的 Is Trigger設為true。它關聯到靶對象(Target類),當觸發器檢測到飛鏢,就把觸發器自身發送給Target
代碼:
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Trigger : MonoBehaviour {public Target target;// Use this for initialization// Update is called once per framevoid OnTriggerEnter(Collider collider){print("name : " + gameObject.name);target.Catched();Target.SetTrigger(this);} }好,簡陋版就做出來了
拓展部份
可能這樣子這個游戲很沒有挑戰性,那么我們還可以制造風,東西南北風!簡單來說就是給飛鏢添加別的力—— 一切阻礙它正常移動的力,也可以說,阻力。這個也很簡單,就是時時給飛鏢添加一個向左、向右、向后的阻力,一切都可以靠自己DIY
總結
- 上一篇: Mysqk 多表连接查询的 “打字练习”
- 下一篇: android.view.WindowL