Unity3D学习(7)——简易射箭游戏

来源:互联网 发布:成都办公软件电脑培训 编辑:程序博客网 时间:2024/06/05 00:07

本节中我们继续利用物理学和动力学知识制作一个简易的射箭游戏。附上游戏的一些需求:

这里写图片描述

先展示一下游戏运行效果:

这里写图片描述

下面开始制作。
首先分析靶对象,靶由5个不同大小的cylinder构成,每一个cylinder添加mesh collider,用于后面判断箭的射击。

这里写图片描述

这里写图片描述

再分析箭对象。箭由3个部分(箭头,箭身,箭尾)组成,考虑到在击中箭靶以后箭的不同部分销毁要求不一样,因此分开设计,并且选择了不同的材质和碰撞器:

箭的层次结构:

这里写图片描述

箭的外观:

这里写图片描述

箭头、箭身碰撞器:

这里写图片描述

箭尾碰撞器:

这里写图片描述

此外画布上创建三个Text对象,分别用于显示分数、风力和风向:

这里写图片描述

至此游戏对象的设置已完成,接下来转入编写代码的阶段。游戏仍然采用此前的工厂模式进行设计,UML图如下:

这里写图片描述

下面是各个文件的介绍,如无特殊说明,均挂载在主摄像机上面:

Director.cs: 导演类,负责实例化,无需挂载

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Director : System.Object {    private static Director _instance;    public SceneController Controller { get; set; }    public static Director getinstance() {        if (_instance == null) _instance = new Director();        return _instance;    }    public int getFPS() { return Application.targetFrameRate; }    public void setFPS(int fps) { Application.targetFrameRate = fps; }}

SceneController.cs: 场景控制,调度箭工厂,动作管理以及分数管理

using System.Collections;using System.Collections.Generic;using UnityEngine;public class SceneController : MonoBehaviour {    private ActionManager actionManager;    private ScoreRecorder scoreRecorder;    private ArrowFactory arrowFactory;    void Awake() {        Director director = Director.getinstance();        director.setFPS(60);        director.Controller = this;        actionManager = (ActionManager)FindObjectOfType(typeof(ActionManager));        scoreRecorder = (ScoreRecorder)FindObjectOfType(typeof(ScoreRecorder));        arrowFactory = (ArrowFactory)FindObjectOfType(typeof(ArrowFactory));    }    public ArrowFactory getFactory() { return arrowFactory; }    public ScoreRecorder getRecorder() { return scoreRecorder; }    public ActionManager getActionManager()  { return actionManager; }    // 移动箭到特定位置并射击    public void shootArrow(Vector3 dir) {        GameObject arrow = arrowFactory.getArrow();        arrow.transform.position = new Vector3(0, 2, 0);        actionManager.shoot(arrow, dir);    }}

ArrowFactory.cs: 管理所有箭的使用情况

using System.Collections;using System.Collections.Generic;using UnityEngine;public class ArrowFactory : MonoBehaviour {    private List<GameObject> UsedArrow;    private List<GameObject> FreeArrow;    public GameObject arrow;    void Awake() {        FreeArrow = new List<GameObject>();        UsedArrow = new List<GameObject>();        arrow = Instantiate(Resources.Load("Prefabs/arrow")) as GameObject;        arrow.SetActive(false);    }    // 获取预设对象    public GameObject getArrow() {        GameObject temp;        if (FreeArrow.Count == 0) {            temp = GameObject.Instantiate(arrow) as GameObject;            temp.SetActive(true);        }        else {            temp = FreeArrow[0];            temp.SetActive(true);            if (temp.GetComponent<Rigidbody>() == null) temp.AddComponent<Rigidbody>();            Component[] comp = temp.GetComponentsInChildren<CapsuleCollider>();            foreach (CapsuleCollider i in comp) i.enabled = true;            temp.GetComponent<MeshCollider>().isTrigger = true;            FreeArrow.RemoveAt(0);        }        UsedArrow.Add(temp);        return temp;    }    // 消失的箭从UsedArrow中移除,并且加入FreeArrow    void Update() {        for (int i = 0; i < UsedArrow.Count; i++) {            GameObject temp = UsedArrow[i];            if (!temp.activeInHierarchy) {                UsedArrow.RemoveAt(i);                FreeArrow.Add(temp);            }        }    }}

ActionManager.cs:分离出了射箭动作

using System.Collections;using System.Collections.Generic;using UnityEngine;public class ActionManager : MonoBehaviour {    private float speed = 25f;    private float Force = 0f;    // 定义了射箭时箭的一些物理属性    public void shoot(GameObject arrow, Vector3 dir) {        arrow.transform.up = dir;        arrow.GetComponent<Rigidbody>().velocity = dir * speed;        Force = Random.Range(-100, 100);        addWind(arrow);    }    private void addWind(GameObject arrow) { arrow.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 int Score = 0;    // 计分规则    public void countScore(string str) {        if (str == "Circle1") Score += 5;        else if (str == "Circle2") Score += 4;        else if (str == "Circle3") Score += 3;        else if (str == "Circle4") Score += 2;        else if (str == "Circle5") Score += 1;    }    public int getScore() { return Score; }}

ArrowScript.cs: 挂载在箭对象上

using System.Collections;using System.Collections.Generic;using UnityEngine;public class ArrowScript : MonoBehaviour {    private string s;    private ScoreRecorder recorder;    private float time;    // 箭在射中靶之后在靶上停留的时间    private static float countdown = 5;    void init() {        time = 0;        s = "";    }    void Awake() {        init();        recorder = (ScoreRecorder)FindObjectOfType(typeof(ScoreRecorder));    }    // 箭射中靶触发了碰撞事件    void OnTriggerEnter(Collider other) {        s = other.gameObject.tag;        Destroy(GetComponent<Rigidbody>());        Component[] comp = GetComponentsInChildren<CapsuleCollider>();        foreach (CapsuleCollider i in comp) i.enabled = false;        GetComponent<MeshCollider>().isTrigger = false;        recorder.countScore(s);    }    void Update() {        time += Time.deltaTime;        if (time >= countdown) {            this.gameObject.SetActive(false);            init();        }    }}
0 0
原创粉丝点击