Unity3D作业六项目一——优化打飞碟游戏

这次作业,主要使用了单实例的工厂类,从而可以让各个类之间的访问通过Singleton<T>来进行访问。

其次,这次的优化在于将Rule类分开来,把游戏的分数,胜利条件放在Rule类中,从而便于日后管理

而涉及到飞碟的颜色等等属性则放在UFO管理之中,从而实现了分离原则。

UI没有太多的改动,主要是显示内容和控制发射。

这次的场景控制器只有分数,关卡和游戏状态,大大简化了场景控制器所需要知道的东西。

UFO管理是整个游戏的核心之一,因为涉及到UFO的各个状态,所以包括资源的加载,回收和发射飞碟,都是在这个类之中实现的。

动作管理器很简单,写了两个函数用来调用UFO管理的函数。

加载在UFO实例上的两个Compent,一个实现了物理引擎,一个没有实现

这次单数关卡是物理,双数不是。可以继续优化的点在于可以创建一个按钮来实现切换,不过这次就没实现了。

爆炸效果和子弹也都是在UFO管理之中。下面上代码,UML图和效果图


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using UnityEngine.UI;
using rule;

public class UserControl : MonoBehaviour
{

    public Text Main_Text;   // 显示主提示
    public Text Score_Text;  // 显示得分   
    public Text Level_Text;  // 显示回合  
    public Camera cam;
    public bool IsFinish = false;
    SceneController SC;
    GameControl GC;
    Rule RC;
    UFOControl UF;
    private void Awake()
    {
        SC = Singleton<SceneController>.Instance;
        GC = Singleton<GameControl>.Instance;
        RC = Singleton<Rule>.Instance;
        UF = Singleton<UFOControl>.Instance;
    }

    void Start()
    {
        Score_Text.text = "Score:  "+SC.getScore();
        Level_Text.text = "Level:  " + SC.getNowLevel();
        Main_Text.text = "Gaming";
    }

    // Update is called once per frame
    void Update()
    {
        if (IsFinish == true)
        {
            if (RC.CheckStatus() == 1)
                Main_Text.text= "Win";
            else
               Main_Text.text = "False";
        }
        if (Input.GetKeyDown("space") && IsFinish == false)
        {
            GC.Launch_UFO();
        }
        else if (Input.GetMouseButtonDown(0))
        {
            Vector3 mp = Input.mousePosition;
            Ray ray = Camera.main.ScreenPointToRay(mp);    // 摄像机到鼠标射线  
            UF.bullet.GetComponent<Rigidbody>().velocity = Vector3.zero;                       // 子弹刚体速度重置  
            UF.bullet.GetComponent<Transform>().position = transform.position;                  // 子弹从摄像机位置射出  
            UF.bullet.GetComponent<Rigidbody>().AddForce(ray.direction*50, ForceMode.Impulse);

            RaycastHit hit;
            if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "UFO")
            {
                // 播放爆炸粒子特效  
                UF.explosion.transform.position = hit.collider.gameObject.transform.position;
                //UF.explosion.GetComponent<Renderer>().material.color = hit.collider.gameObject.GetComponent<Renderer>().material.color;
                UF.explosion.Play();
                GC.Hit_UFO(hit.collider.gameObject);
            }

        }

        Level_Text.text = "Level: "+ SC.getNowLevel();
        Score_Text.text = "Score: "+SC.getScore();
    }



}



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using rule;

public class GameControl : MonoBehaviour
{

    UFOControl UC;
    private void Awake()
    {
        UC= Singleton<UFOControl>.Instance;
    }

    public void Launch_UFO()
    {
        UC.Launch_UFO();
    }

    public void Hit_UFO(GameObject temp)
    {
        UC.Hit_UFO(temp);
    }

}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using rule;

namespace MyGame
{

    public class UFOControl : MonoBehaviour
    {
        private List<GameObject> UFO_Ready_List = new List<GameObject>();
        private List<GameObject> UFO_Active_List = new List<GameObject>();   
        private List<GameObject> UFO_UnActive_List = new List<GameObject>();
        public GameObject UFO_Pre;  //  UFO预制
        public GameObject bullet; //子弹预制
        public ParticleSystem explosion; //爆炸预制
        private Vector3 UnusedPlace = new Vector3(1000f, 1000f, 1000f);

        private Color UFO_Color;                //颜色
        private int UFO_Number = 10;         // 飞碟一共的数量
        private int UFO_Speed;               //飞碟的速度

        Rule Crule;
        private void Awake()
        {
            Crule = Singleton<Rule>.Instance;
        }

        
        public Color getColor()
        {
            return UFO_Color;
        }
        public int getSpeed()
        {
            return UFO_Speed;
        }
        
        public void Start()
        {
          
            for(int i=0; i<10;i++)
            {
                GameObject Temp = GameObject.Instantiate(UFO_Pre, UnusedPlace, Quaternion.identity) as GameObject;
                UFO_Ready_List.Add(Temp);
            }

        }

        //资源加载
        public void Load_Reources(Level level)
        {
            if (level == Level.Ready)
            {
                UFO_Color = Color.blue;
                UFO_Speed = 1;
                Launch_Ready_UFO();
            }
            else if (level == Level.First)
            {
                UFO_Color = Color.green;
                UFO_Speed = 3;
                Launch_Ready_UFO();
            }
            else if (level == Level.Second)
            {
                UFO_Color = Color.red;
                UFO_Speed = 5;
                Launch_Ready_UFO();
            }
        }
        //发射准备
        public void Launch_Ready_UFO()
        {
            Debug.Log("SSS");
            for (int i = 0; i < 10; i++)
            {
                if (UFO_Active_List.Count != 0)
                {
                    GameObject temp = UFO_Active_List[0];
                    temp.transform.position = UnusedPlace;
                    UFO_Ready_List.Add(temp);
                    UFO_Active_List.Remove(temp);
                }
                else if (UFO_UnActive_List.Count != 0)
                {
                    GameObject temp = UFO_UnActive_List[0];
                    temp.transform.position = UnusedPlace;
                    UFO_Ready_List.Add(temp);
                    UFO_UnActive_List.Remove(temp);
                }
            }
        }


        public void Launch_UFO()
        {
            if (UFO_Ready_List.Count == 0)
            {
                isFlaseStatus();
            }
            else
            {
                GameObject Temp =UFO_Ready_List[0];
                UFO_Ready_List.Remove(Temp);
                Temp.GetComponent<Renderer>().material.color = UFO_Color;

                if(Crule.getNowLevel() == Level.First || Crule.getNowLevel() == Level.Tird)
                {
                    UFOCompent ac = Temp.AddComponent<UFOCompent>();
                    Temp.transform.position = new Vector3(0 + Random.Range(-10, 10), 8 + Random.Range(-4, 5), 0);
                    ac.setting(UFO_Speed);
                }
                else
                {
                    UFOCompentP ac = Temp.AddComponent<UFOCompentP>();
                    Temp.transform.position = new Vector3(0 + Random.Range(-10, 10), 8 + Random.Range(-4, 5), 0);
                    ac.setting(UFO_Speed);
                }
               
                UFO_Active_List.Add(Temp);

            }
            
        }

        public void Hit_UFO(GameObject temp)
        {
            UFO_Active_List.Remove(temp);
            UFO_UnActive_List.Add(temp);
            temp.transform.position = new Vector3(1000f, 1000f, 1000f);
            Crule.HitUFO();
            
        }

        public void Miss_UFO(GameObject temp)
        {
            UFO_Active_List.Remove(temp);
            UFO_UnActive_List.Add(temp);
        }
        //游戏结束判断
        public void isFlaseStatus()
        {
           Crule.IsFalseStatus();
        }


    }
}




using MyGame;
using rule;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UFOCompent : MonoBehaviour
{

    private float time;
    public float UFO_Speed;
    public float UFO_Speed_y;
    public float UFO_Speed_x;
    // Use this for initialization
    Rule Srule;
    UFOControl UC;

    private void Awake()
    {
        Srule = Singleton<Rule>.Instance;
        UC = Singleton<UFOControl>.Instance;
    }
    public void setting(float Speed)
    {
        time = Time.time;
        UFO_Speed = Speed;
    }

    // Update is called once per frame
    void Update()
    {

        UFO_Speed_y = UnityEngine.Random.Range(0, 3) + UFO_Speed;
        UFO_Speed_x = UnityEngine.Random.Range(-10, 10) + UFO_Speed;
        transform.Translate(Vector3.down * Time.deltaTime * UFO_Speed_y, Space.World);
        transform.Translate(Vector3.left * Time.deltaTime * UFO_Speed_x);

        if (this.gameObject.transform.position.y < -3)
        {
            this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
            UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
        }
        if (Time.time - time > 8 || this.gameObject.transform.position.y < -3)
        {
            UC.Miss_UFO(this.gameObject);
            this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
            UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
            Destroy(this);
        }
    }
}

using MyGame;
using rule;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UFOCompentP : MonoBehaviour
{

    private float time;
    public float UFO_Speed;
    // Use this for initialization
    Rule Srule;
    UFOControl UC;

    private void Awake()
    {
        Srule = Singleton<Rule>.Instance;
        UC = Singleton<UFOControl>.Instance;
    }
    public void setting(float Speed)
    {
        time = Time.time;
        UFO_Speed = Speed;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        this.gameObject.AddComponent<Rigidbody>();
        Rigidbody rigid = this.gameObject.GetComponent<Rigidbody>();
        if (rigid)
        {
            rigid.AddForce(Vector3.down * 3.3f);
            if (Random.Range(-1, 1) < 0)
                rigid.AddForce(Vector3.left * 1.0f);
            else
                rigid.AddForce(Vector3.right * 1.0f);
        }

        if (this.gameObject.transform.position.y < -3)
        {
            this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
            UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
        }
        if (Time.time - time > 8 || this.gameObject.transform.position.y < -3)
        {
            UC.Miss_UFO(this.gameObject);
            this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
            UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
            Destroy(this);
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;

//Rule类负责这个游戏的核心规则
//游戏的胜负,游戏的关卡变化,游戏的分数变化

namespace rule
{
    public enum Level { Ready, First, Second, Tird }; //关卡信息
    public class Rule : MonoBehaviour
    {
       
        private int Score = 0;   //游戏的分数
        private int GoalScore = 5; // 目标分数
        private Level NowLevel = Level.Ready;   //  游戏的关卡
        private bool isWin = false;
        private bool isFalse = false;
        UFOControl RUFOControl;
        public int getScore()
        {
            return Score;
        }

        public Level getNowLevel()
        {
            return NowLevel;
        }

        // 得分  
        public void HitUFO()
        {
            Score++;
            Debug.Log("Good!  Now Score: " + Score);
        }

        //关卡判断
        public void IsNextLevel()
        {
            if (NowLevel == Level.Ready)
            {
                RUFOControl.Load_Reources(NowLevel);
                NowLevel = Level.First;
            }
            else if (NowLevel == Level.First && Score >= GoalScore)
            {
                RUFOControl.Load_Reources(NowLevel);
                Score = 0;
                NowLevel = Level.Second;
            }   
            else if (NowLevel == Level.Second && Score >= GoalScore)
            {
                RUFOControl.Load_Reources(NowLevel);
                Score = 0;
                NowLevel = Level.Tird;
            }
            else if (NowLevel == Level.Tird && Score >= GoalScore)
                isWin = true;
            else
            {
                if (Score < 0)
                    isFalse = true;
            }
        }

        //检查游戏是否结束
        public int  CheckStatus()
        {
            if (isWin == true)
                return 1;
            else if (isFalse == true)
                return -1;
            else
                return 0;
        }

        public void IsFalseStatus()
        {
            if (Score < GoalScore)
            {
                isFalse = true;
            }
        }

        private void Awake()
        {
            RUFOControl = Singleton<UFOControl>.Instance;
        }

        public void Start()
        {
            IsNextLevel();
        }


    }

}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using rule;

namespace MyGame
{

    //场景单实例
    public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
    {

        protected static T instance;

        public static T Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = (T)FindObjectOfType(typeof(T));
                    if (instance == null)
                    {
                        Debug.LogError("An instance of " + typeof(T)
                            + " is needed in the scene, but there is none.");
                    }
                }
                return instance;
            }
        }
    }


    public class SceneController : MonoBehaviour
    {
        
        private int Now_Score;   //当前分数
        private Level Now_Level;//当前关卡
        private int IsStatus = 0;//游戏状态

        Rule Srule;
        UserControl USC;
        private void Awake()
        {
            Srule = Singleton<Rule>.Instance;
            USC = Singleton<UserControl>.Instance;
        }
        

        public int getScore()
        {
            return Now_Score;
        }

        public Level getNowLevel()
        {
            return Now_Level;
        }



        public void Start()
        {
            Now_Score = Srule.getScore();
            Now_Level = Srule.getNowLevel();
        }


        public void Update()
        {
            Srule.IsNextLevel();
            Now_Score = Srule.getScore();
            Now_Level  = Srule.getNowLevel();
            IsStatus =  Srule.CheckStatus();
            if (IsStatus == -1)
                USC.IsFinish = true;
            else if (IsStatus == 1)
                USC.IsFinish = true;

        }

    }
}




版权声明:本文为PalytoxinRK原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。