Unity 小游戏:3D射箭,供大家参考,具体内容如下
前两周因为实训太忙,再加上自己对老师所讲的设计模式并不是很理解,所以就没有写博客。这次博客是记录3D射箭游戏的实现过程。
1. 准备资源
我是在网上找的弓与箭的资源,至于靶子,创建五个不同大小的同心圆柱体,如图所示:
需要注意的是,五个圆柱体并不在同一个平面上,这样才能够看清每一环的颜色,并且在检测碰撞时不会出现各种问题。
另外,如果靶子放得离相机太近,就没有射箭的感觉了;离相机太远,好像又看不清靶子了,然后我试着把靶子Material的Shader改为 Sprites/Default ,这样靶子离相机远一点也能看得很清晰。
2. 布置场景
把弓箭作为Main Camera的子物体,这样我们可以在用鼠标控制镜头移动时,使弓箭一直指向屏幕中心,以达到第一人称控制器的效果。
在此项目中,没有选择使用GUI来做UI界面,而是创建了一个Canvas,在这里面添加了一个Image用来显示弓箭的准心,以及四个Text来显示得分、风向、风力、提示等。
3. 编辑脚本
游戏采用MVC架构,大部分功能是自己实现的,也有一小些函数是借鉴大神的。整体上感觉有很多缺陷,但是又不知道怎么修改才好,我也很无奈啊!°(°?Д?°) °
下面是我的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; //播放拉弓动画 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); } //产生风 private void wind(Transform arrow) { arrow.transform.GetComponent<Rigidbody> ().AddForce (new Vector3 (Force, 0, 0), ForceMode.Force); } //返回风 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; } //返回分数 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)); } //加载预制物体靶子 public void LoadResources () { Debug.Log ("loading...\n"); GameObject target = Instantiate<GameObject> ( Resources.Load<GameObject> ("Prefabs/target")); target.name = "target"; } //获得分数 public string getMyScore () { return scoreRecorder.getScore (); } //获得风向和风力 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 () { //镜头跟随鼠标 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); //按空格键使弓箭瞄准靶心 if (Input.GetKeyDown (KeyCode.Space)) { m_CharacterTargetRot = Quaternion.Euler (0f, 0f, 0f); transform.localRotation = Quaternion.Slerp (transform.localRotation, m_CharacterTargetRot, 5f * Time.deltaTime); } //鼠标左键按下,开始拉弓 if (Input.GetMouseButtonDown (0)) { userAction.Openbow (); } //鼠标左键按住不放,蓄力 if (Input.GetMouseButton (0)) { userAction.Draw (); } //鼠标左键抬起。射箭 if (Input.GetMouseButtonUp (0)) { userAction.Shoot (); } Score.text = "Score : " + userAction.getMyScore (); //显示上一轮分数 float force = userAction.getWind (); if (force < 0) { WindDirection.text = "Wind Direction : <---"; //显示风向 } else if (force > 0) { WindDirection.text = "Wind Direction : --->"; } else { WindDirection.text = "Wind Direction : No"; } WindForce.text = "Wind Force : " + Mathf.Abs (userAction.getWind ()); //显示风力 } }
Arrow.cs
using UnityEngine; using System.Collections; public class Arrow : MonoBehaviour { private RaycastHit hit; void Update (){ //检测在移动的箭 if(GetComponent<Rigidbody>().velocity.magnitude > 0.5f) { CheckForHit(); } else { enabled = false; } if (transform.position.y < -5) { Destroy (this.gameObject); //将掉出地面以下的箭销毁 } } //检测是否碰撞 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; //箭没中靶,则继续做抛物线运动 } } }
Target.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Target : MonoBehaviour { private ScoreRecorder scoreRecorder; public string score; //对应靶环的分数 public void Start() { scoreRecorder = (ScoreRecorder)FindObjectOfType (typeof(ScoreRecorder)); } void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "Arrow") { scoreRecorder.countScore (score); //记录分数 } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/210490/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)