Unity学习——射箭游戏
射箭游戲
游戲視頻<https://www.bilibili.com/video/av71160101/>
游戲工程文件https://github.com/JennySRH/3DGame/tree/master/ShootTarget
上下左右控制箭移動(dòng),空格鍵發(fā)射
靶對(duì)象
靶對(duì)象共有5環(huán),由5個(gè)圓柱體組成,射中最中心的環(huán)得分5,射中最外層環(huán)得分為1。每個(gè)圓柱體都添加了mesh collider,勾選Convex,并且勾選了is Trigger作為觸發(fā)器。
對(duì)于靶對(duì)象而言,它需要完成兩種行為:
Target上將掛載兩個(gè)腳本,一個(gè)是TargetData,掛載到每一個(gè)環(huán)上,用來得到該環(huán)的分?jǐn)?shù);另一個(gè)是TargetTrigger,用來檢測(cè)哪一個(gè)環(huán)被觸發(fā)。
/* TargetData.cs */ public class TargetData : MonoBehaviour {// 掛載到Target上的每一環(huán),用來返回該環(huán)對(duì)應(yīng)的分?jǐn)?shù)。public int GetScore(){string name = this.gameObject.name;int score = 6 - (name[0] - '0');return score;} } /*TargetTrigger.cs*/ using System.Collections; using System.Collections.Generic; using UnityEngine;public class TargetTrigger : MonoBehaviour {// 當(dāng)有箭射中某一環(huán)后觸發(fā)void OnTriggerEnter(Collider arrow_head){//得到箭身Transform arrow = arrow_head.gameObject.transform.parent;if (arrow == null){return;}if (arrow.tag == "Arrow"){arrow_head.gameObject.SetActive(false);//箭身速度為0arrow.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);arrow.GetComponent<Rigidbody>().isKinematic = true;arrow.tag = "Hit";// 分?jǐn)?shù)控制器int score = this.gameObject.gameObject.GetComponent<TargetData>().GetScore();Singleton<ScoreController>.Instance.AddScore(score);//Debug.Log(score);}}}然后將所有的圓柱體放到一個(gè)空物體上,做成預(yù)制。
箭
每一個(gè)箭由head和body組成,head裝有collider。
箭掛載了JoyStick可以通過上下左右來控制方向,如果按下空格鍵將添加剛體Rigidbody,然后交由相應(yīng)的動(dòng)作控制器進(jìn)行控制。
/*JoyStick.cs*/using System.Collections; using System.Collections.Generic; using UnityEngine;public class JoyStick : MonoBehaviour {public float speedX = 1.0F;public float speedY = 1.0F;bool flag = true;// Update is called once per framevoid Update(){// 只有在射出前能移動(dòng)if(flag){float translationY = Input.GetAxis("Vertical") * speedY;float translationX = Input.GetAxis("Horizontal") * speedX;translationY *= Time.deltaTime;translationX *= Time.deltaTime;// 限制移動(dòng)的范圍if (transform.position.x - translationX < 1.5 && transform.position.x - translationX > -1.5&& transform.position.y + translationY > -0.8 && transform.position.y + translationY < 0.8){transform.position = transform.position + new Vector3(-translationX, translationY, 0);}if (Input.GetButton("Jump")){// 如果空格下,則給箭增加剛體,使其能夠進(jìn)行物理學(xué)的運(yùn)動(dòng)this.gameObject.AddComponent<Rigidbody>();this.gameObject.GetComponent<Rigidbody>().useGravity = false;flag = false;}}} }風(fēng)
風(fēng)是由一系列透明的觸發(fā)器組成的。
觸發(fā)器們掛載了WindTrigger用來檢測(cè)是否有箭頭觸發(fā),然后交由相應(yīng)的動(dòng)作控制器控制。
/*WindTrigger*/ using System.Collections; using System.Collections.Generic; using UnityEngine;public class WindTrigger : MonoBehaviour {void OnTriggerEnter(Collider arrow_head){//得到箭身Transform arrow = arrow_head.gameObject.transform.parent;if (arrow == null){return;}if (arrow.tag == "Arrow"){arrow.GetComponent<CCAction>().Move();}} }風(fēng)力大小和風(fēng)向由WindController生成,掛載到全局的空物體上,使用單例模式獲得。
/*WindController.sc*/ using System.Collections; using System.Collections.Generic; using UnityEngine;public class WindController : MonoBehaviour {private float time = 5;private float strength = 0.5f;private Vector3 direction = new Vector3(0.01f,0,0);// Update is called once per framevoid Update(){if(time > 0){time -= Time.deltaTime;}else{time = 5;strength = UnityEngine.Random.Range(0.5f, 0.7f);direction = new Vector3(UnityEngine.Random.Range(-0.02f, 0.02f), UnityEngine.Random.Range(-0.02f, 0.02f), 0);}}public float GetStrength(){return strength;}public Vector3 GetDirection(){return direction;} }場(chǎng)景控制器——FirstSceneController
由于本次作業(yè)依舊沿用了之前的MVC框架,所以只展示重要部分代碼。
FirstSceneController掛載到空物體上,用來加載第一個(gè)場(chǎng)景(一共也只有一個(gè)場(chǎng)景)。
/*FirstSceneController.cs*/ using System.Collections; using System.Collections.Generic; using UnityEngine;public class FirstSceneController : MonoBehaviour, ISceneController {// 靶對(duì)象public GameObject target;// 箭隊(duì)列public Queue<GameObject> arrowQueue = new Queue<GameObject>();// 當(dāng)前正在操控的箭public GameObject arrow;// 風(fēng)public GameObject wind;public void LoadSource(){// 清除記分Singleton<ScoreController>.Instance.ClearScore();// 靶對(duì)象初始化if (target != null){Destroy(target);}target = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Target"));if(arrow != null){Singleton<ArrowFactory>.Instance.FreeArrow(arrow);}// 箭隊(duì)列初始化while (arrowQueue.Count > 0){Singleton<ArrowFactory>.Instance.FreeArrow(arrowQueue.Dequeue());}arrowQueue.Clear();// 初始化一個(gè)箭對(duì)象arrow = Singleton<ArrowFactory>.Instance.GetArrow();arrowQueue.Enqueue(arrow);}// Start is called before the first frame updatevoid Start(){this.gameObject.AddComponent<ArrowFactory>();this.gameObject.AddComponent<ScoreController>();this.gameObject.AddComponent<IGUI>();this.gameObject.AddComponent<WindController>();wind = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Wind"));// 設(shè)置第一個(gè)場(chǎng)景控制器為當(dāng)前場(chǎng)景控制器Director.GetInstance().CurrentSceneController = this;Director.GetInstance().CurrentSceneController.LoadSource();}// Update is called once per framevoid Update(){if(arrow.tag == "WaveEnd"){arrow = Singleton<ArrowFactory>.Instance.GetArrow();arrowQueue.Enqueue(arrow);}} }運(yùn)動(dòng)學(xué)控制器——CCAction (顫抖效果)
CCAction掛載到每個(gè)Arrow上,用來負(fù)責(zé)Arrow射中靶對(duì)象后的抖動(dòng)效果以及遇到風(fēng)之后產(chǎn)生的偏移效果。
/*CCAction.cs*/ using System.Collections; using System.Collections.Generic; using UnityEngine;public class CCAction : MonoBehaviour, IAction {private float time = 1;float radian = 0;float radius = 0.01f; Vector3 initPosition;public void Move(){Move(Singleton<WindController>.Instance.GetDirection(), Singleton<WindController>.Instance.GetStrength());}public void Move(Vector3 direction, float strength){this.transform.position += direction * strength;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){if(time > 0){if (this.gameObject.tag == "Hit"){time -= Time.deltaTime;// 弧度每次增加radian += 0.05f;// 顫抖float dy = Mathf.Cos(radian) * radius;transform.position = initPosition + new Vector3(0, dy, 0);}else{initPosition = transform.position;}}if(time <= 0){this.gameObject.tag = "WaveEnd";transform.position = initPosition;}} }動(dòng)力學(xué)控制器——PhysicalAction
PhysicalAction也掛載到Arrow對(duì)象上,用來控制Arrow發(fā)射的運(yùn)動(dòng)效果。
/*PhysicalAction.cs*/ using System.Collections; using System.Collections.Generic; using UnityEngine;public class PhysicalAction : MonoBehaviour, IAction {float force = 3;public void Move(){}public void Move(float force){this.force = force;}// Update is called once per framevoid Update(){// 如果沒有射中靶對(duì)象if(this.gameObject.transform.position.z < -1){this.gameObject.tag = "WaveEnd";}}void FixedUpdate(){// 如果射中了靶對(duì)象if (this.gameObject.GetComponent<Rigidbody>() != null){this.gameObject.GetComponent<Rigidbody>().AddForce(new Vector3(0, 0, -1) * force);}}}記分器——ScoreController
ScoreController也是使用單例模式,作為全局唯一來記錄分?jǐn)?shù)。
{score = 0;}public void AddScore(int score){this.score += score;}public int GetScore(){return this.score;}}效果展示
改進(jìn)打飛碟游戲
增加一個(gè)運(yùn)動(dòng)的接口類ActionManager,物理運(yùn)動(dòng)PhysicalAction和運(yùn)動(dòng)學(xué)變換CCAction都將實(shí)現(xiàn)該接口。
public interface IActionManager {void Move(Vector3 direction, float speed); }CCAction
public class CCAction : MonoBehaviour, IActionManager {public Vector3 direction;public float speed;public void Move(Vector3 direction,float speed){this.direction = direction;this.speed = speed;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){this.gameObject.transform.position += speed * direction * Time.deltaTime;} }對(duì)于PhysicalManager而言,Move函數(shù)是與其功能不匹配的,但是我們又不想丟棄這個(gè)CCAction和ActionManager,所以我們可以通過adapter模式,進(jìn)行適配。
PhysicalManager
using System.Collections; using System.Collections.Generic; using UnityEngine;public class PhysicalManager : MonoBehaviour, IActionManager {public float speed;public void Move(float speed){this.speed = speed;}public void Move(Vector3 direction, float speed){Move(speed);}void FixedUpdate(){Rigidbody rigid = this.gameObject.GetComponent<Rigidbody>();if(rigid){//Debug.Log(speed);rigid.AddForce(Vector3.down * speed);} }// Start is called before the first frame updatevoid Start(){this.gameObject.GetComponent<Rigidbody>().useGravity = false;}}總結(jié)
以上是生活随笔為你收集整理的Unity学习——射箭游戏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数字图像处理】图像感兴趣区域与图像放大
- 下一篇: 图像放大和缩小