Unity實(shí)現(xiàn)3D射箭小游戲
Unity 小游戲:3D射箭,供大家參考,具體內(nèi)容如下
前兩周因?yàn)閷?shí)訓(xùn)太忙,再加上自己對(duì)老師所講的設(shè)計(jì)模式并不是很理解,所以就沒(méi)有寫博客。這次博客是記錄3D射箭游戲的實(shí)現(xiàn)過(guò)程。
1. 準(zhǔn)備資源
我是在網(wǎng)上找的弓與箭的資源,至于靶子,創(chuàng)建五個(gè)不同大小的同心圓柱體,如圖所示:
需要注意的是,五個(gè)圓柱體并不在同一個(gè)平面上,這樣才能夠看清每一環(huán)的顏色,并且在檢測(cè)碰撞時(shí)不會(huì)出現(xiàn)各種問(wèn)題。
另外,如果靶子放得離相機(jī)太近,就沒(méi)有射箭的感覺(jué)了;離相機(jī)太遠(yuǎn),好像又看不清靶子了,然后我試著把靶子Material的Shader改為 Sprites/Default ,這樣靶子離相機(jī)遠(yuǎn)一點(diǎn)也能看得很清晰。
2. 布置場(chǎng)景
把弓箭作為Main Camera的子物體,這樣我們可以在用鼠標(biāo)控制鏡頭移動(dòng)時(shí),使弓箭一直指向屏幕中心,以達(dá)到第一人稱控制器的效果。
在此項(xiàng)目中,沒(méi)有選擇使用GUI來(lái)做UI界面,而是創(chuàng)建了一個(gè)Canvas,在這里面添加了一個(gè)Image用來(lái)顯示弓箭的準(zhǔn)心,以及四個(gè)Text來(lái)顯示得分、風(fēng)向、風(fēng)力、提示等。
3. 編輯腳本
游戲采用MVC架構(gòu),大部分功能是自己實(shí)現(xiàn)的,也有一小些函數(shù)是借鑒大神的。整體上感覺(jué)有很多缺陷,但是又不知道怎么修改才好,我也很無(wú)奈?。 ?°ˊДˋ°) °
下面是我的UML圖:
以下是完整代碼:
SSDirector.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SSDirector : System.Object { private static SSDirector _instance; public ISceneCotroller currentScenceCotroller { get; set; } public bool running { get; set; } public static SSDirector getInstance() { if (_instance == null) { _instance = new SSDirector (); } return _instance; } }
ISceneCotroller.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public interface ISceneCotroller { void LoadResources (); }
IUserAction.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public interface IUserAction { string getMyScore (); float getWind (); void Openbow (); void Draw (); void Shoot (); }
ActionManager.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ActionManager : MonoBehaviour { private float Force = 0f; private int maxPower = 2500; private float power; public Transform arrowSpawn; public Transform myArrow; public Transform bow; //播放拉弓動(dòng)畫 public void Openbow () { bow.GetComponent<Animation>().Play("Draw"); bow.GetComponent<Animation>()["Draw"].speed = 1; bow.GetComponent<Animation>()["Draw"].wrapMode = WrapMode.Once; arrowSpawn.GetComponent<MeshRenderer>().enabled = true; //重置 power 為 0 power = 0; } //拉弓,從power為0到power為3000 public void Draw () { if(power < maxPower) { power += maxPower * Time.deltaTime; } } //射箭 public void Shoot () { float percent = bow.GetComponent<Animation>()["Draw"].time / bow.GetComponent<Animation>()["Draw"].length; float shootTime = 1 * percent; bow.GetComponent<Animation>().Play("Shoot"); bow.GetComponent<Animation>()["Shoot"].speed = 1; bow.GetComponent<Animation>()["Shoot"].time = shootTime; bow.GetComponent<Animation>()["Shoot"].wrapMode = WrapMode.Once; arrowSpawn.GetComponent<MeshRenderer>().enabled = false; Transform arrow= Instantiate (myArrow, arrowSpawn.transform.position, transform.rotation); arrow.transform.GetComponent<Rigidbody>().AddForce(transform.forward * power); wind (arrow); Force = Random.Range (-100, 100); } //產(chǎn)生風(fēng) private void wind(Transform arrow) { arrow.transform.GetComponent<Rigidbody> ().AddForce (new Vector3 (Force, 0, 0), ForceMode.Force); } //返回風(fēng) public float getWindForce() { return Force; } }
ScoreRecorder.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ScoreRecorder : MonoBehaviour { private string Score = "0"; //判斷得分 public void countScore(string type) { Score = type; } //返回分?jǐn)?shù) public string getScore () { return Score; } }
FirstScene.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FirstScene : MonoBehaviour, ISceneCotroller, IUserAction { private ActionManager actionManager; private ScoreRecorder scoreRecorder; void Awake () { SSDirector director = SSDirector.getInstance (); director.currentScenceCotroller = this; director.currentScenceCotroller.LoadResources (); actionManager = (ActionManager)FindObjectOfType (typeof(ActionManager)); scoreRecorder = (ScoreRecorder)FindObjectOfType (typeof(ScoreRecorder)); } //加載預(yù)制物體靶子 public void LoadResources () { Debug.Log ("loading...\n"); GameObject target = Instantiate<GameObject> ( Resources.Load<GameObject> ("Prefabs/target")); target.name = "target"; } //獲得分?jǐn)?shù) public string getMyScore () { return scoreRecorder.getScore (); } //獲得風(fēng)向和風(fēng)力 public float getWind () { return actionManager.getWindForce (); } //拉弓 public void Openbow () { actionManager.Openbow (); } //蓄力 public void Draw () { actionManager.Draw (); } //射箭 public void Shoot () { actionManager.Shoot (); } }
UserGUI.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UserGUI : MonoBehaviour { private IUserAction userAction; private FirstScene scene; private Quaternion m_CharacterTargetRot; public Text Score; public Text WindDirection; public Text WindForce; // Use this for initialization void Start () { userAction = SSDirector.getInstance ().currentScenceCotroller as IUserAction; } void Awake () { m_CharacterTargetRot = transform.localRotation; } void Update () { //鏡頭跟隨鼠標(biāo) float xRot = Input.GetAxis ("Mouse X") * 3f; float yRot = Input.GetAxis ("Mouse Y") * -3f; m_CharacterTargetRot *= Quaternion.Euler (yRot, xRot, 0f); transform.localRotation = Quaternion.Slerp (transform.localRotation, m_CharacterTargetRot, 5f * Time.deltaTime); //按空格鍵使弓箭瞄準(zhǔn)靶心 if (Input.GetKeyDown (KeyCode.Space)) { m_CharacterTargetRot = Quaternion.Euler (0f, 0f, 0f); transform.localRotation = Quaternion.Slerp (transform.localRotation, m_CharacterTargetRot, 5f * Time.deltaTime); } //鼠標(biāo)左鍵按下,開(kāi)始拉弓 if (Input.GetMouseButtonDown (0)) { userAction.Openbow (); } //鼠標(biāo)左鍵按住不放,蓄力 if (Input.GetMouseButton (0)) { userAction.Draw (); } //鼠標(biāo)左鍵抬起。射箭 if (Input.GetMouseButtonUp (0)) { userAction.Shoot (); } Score.text = "Score : " + userAction.getMyScore (); //顯示上一輪分?jǐn)?shù) float force = userAction.getWind (); if (force < 0) { WindDirection.text = "Wind Direction : <---"; //顯示風(fēng)向 } else if (force > 0) { WindDirection.text = "Wind Direction : --->"; } else { WindDirection.text = "Wind Direction : No"; } WindForce.text = "Wind Force : " + Mathf.Abs (userAction.getWind ()); //顯示風(fēng)力 } }
Arrow.cs
using UnityEngine; using System.Collections; public class Arrow : MonoBehaviour { private RaycastHit hit; void Update (){ //檢測(cè)在移動(dòng)的箭 if(GetComponent<Rigidbody>().velocity.magnitude > 0.5f) { CheckForHit(); } else { enabled = false; } if (transform.position.y < -5) { Destroy (this.gameObject); //將掉出地面以下的箭銷毀 } } //檢測(cè)是否碰撞 void CheckForHit (){ float myVelocity = GetComponent<Rigidbody>().velocity.magnitude; float raycastLength = myVelocity * 0.03f; if(Physics.Raycast(transform.position, transform.forward, out hit, raycastLength)) { GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll; //使箭停留在靶子上 transform.position = hit.point; transform.parent = hit.transform; enabled = false; } else { Quaternion newRot = transform.rotation; newRot.SetLookRotation(GetComponent<Rigidbody>().velocity); transform.rotation = newRot; //箭沒(méi)中靶,則繼續(xù)做拋物線運(yùn)動(dòng) } } }
Target.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Target : MonoBehaviour { private ScoreRecorder scoreRecorder; public string score; //對(duì)應(yīng)靶環(huán)的分?jǐn)?shù) public void Start() { scoreRecorder = (ScoreRecorder)FindObjectOfType (typeof(ScoreRecorder)); } void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "Arrow") { scoreRecorder.countScore (score); //記錄分?jǐn)?shù) } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# wpf使用ListBox實(shí)現(xiàn)尺子控件的示例代碼
本文主要介紹了C# wpf使用ListBox實(shí)現(xiàn)尺子控件的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07C#實(shí)現(xiàn)拷貝文件的9種方法小結(jié)
最近遇一個(gè)問(wèn)題,一個(gè)程序調(diào)用另一個(gè)程序的文件,結(jié)果另一個(gè)程序的文件被占用,使用不了文件,這時(shí)候的解決方案就是把另一個(gè)程序的文件拷貝到當(dāng)前程序就可以了,本文介紹用C#拷貝文件的多種方式,需要的朋友可以參考下2024-04-04深入學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程(下)
這篇文章主要介紹了深入學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程的相關(guān)知識(shí),文中講解的非常詳細(xì),幫助大家更好的學(xué)習(xí)c#網(wǎng)絡(luò)編程,感興趣的朋友可以了解下2020-06-06