Unity3D学习笔记(6)-- 打飞碟游戏改进版

一.简要说明

这是上一次打飞碟游戏的改进版本,这次和上次的版本有小些差异,在功能上主要添加了一个物理运动的模块,以下来讲讲这些改动。

二.游戏效果图

三.UML图

先上一张UML图


PhysicActionManager有点看不全,不过基本和CCActionManager相同


四.主要代码说明

1.这里用了两个工厂类来管理飞碟和控制飞碟运动的脚本的生成和回收,它们的实现的代码类似,以下是飞碟工厂的代码片段:

 private Dictionary<int, SSAction> used = new Dictionary<int, SSAction>();
 private List<SSAction> free = new List<SSAction>();
 private List<int> wait = new List<int>();
所有正在使用的飞碟都保存在used

未被激活的飞碟保存在free

wait是用来保存等待释放的飞碟

 private void Update()
    {
        foreach (var tmp in used.Values)
        {

            if (!tmp.gameObject.activeSelf)
            {
                wait.Add(tmp.GetInstanceID());
            }
        }


        foreach (int tmp in wait)
        {
            FreeDisk(used[tmp].gameObject); //释放一个飞碟
        }
        wait.Clear();
    }

以上代码用来实现飞碟的自动回收,通过飞碟是否活跃,来判断是否回收

2.这里还实现了两个管理动作的类,一个是管理运动学的动作CCActionManager,另外一个是动力学的动作PhysicActionManager,它们实现的代码也基本相似,下面是

CCActionManager的一些代码片段

    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //保存所以已经注册的动作
    private List<SSAction> waitingAdd = new List<SSAction>();                           //动作的等待队列,在这个对象保存的动作会稍后注册到动作管理器里
    private List<int> waitingDelete = new List<int>();                                  //动作的删除队列,在这个对象保存的动作会稍后删除

protected void Update()
    {
        //把等待队列里所有的动作注册到动作管理器里
        foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
        waitingAdd.Clear();

        //管理所有的动作,如果动作被标志为删除,则把它加入删除队列,被标志为激活,则调用其对应的Update函数
        foreach (KeyValuePair<int, SSAction> kv in actions)
        {
            SSAction ac = kv.Value;
            if (ac.destroy)
            {
                waitingDelete.Add(ac.GetInstanceID());
            }
            else if (ac.enable)
            {
                ac.Update();
            }
        }

        //把删除队列里所有的动作删除
        foreach (int key in waitingDelete)
        {
            SSAction ac = actions[key];
            actions.Remove(key);
            DestroyObject(ac);
        }
        waitingDelete.Clear();
    }

CCActionManager动作管理器通过以下代码把一个动作和一个对象给关联起来

   public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager)
    {
        action.gameobject = gameobject;
        action.transform = gameobject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }

五.全部的源代码

一.飞碟回收工厂类(DiskFactory.cs)

/**
 * 这个文件是用来生产飞碟的工厂
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DiskFactory : MonoBehaviour{

    /**
     * diskPrefab是用来生产飞碟的模板,保存着一个飞碟的实例
     */
      
    public GameObject diskPrefab;

    /**
     * used是用来保存正在使用的飞碟
     * free是用来保存未激活的飞碟
     */

    private Dictionary<int, DiskData> used = new Dictionary<int, DiskData>();
    private List<DiskData> free = new List<DiskData>();
    private List<int> wait = new List<int>();

    private void Awake()
    {
        diskPrefab = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/disk"), Vector3.zero, Quaternion.identity);
        diskPrefab.SetActive(false);
    }

    private void Update()
    {

        foreach (var tmp in used.Values)
        {

            if (!tmp.gameObject.activeSelf)
            {
                wait.Add(tmp.GetInstanceID());
            }
        }

        foreach (int tmp in wait)
        {
            FreeDisk(used[tmp].gameObject);
        }
        wait.Clear();
    }

    /**
     * GetDisk这个函数是用来飞碟的,
     * 每次首次判断free那里还有没有未使用的飞碟,
     * 有就从free那里获取,没有就生成一个飞碟
     */

    public GameObject GetDisk(int round, ActionMode mode)
    {
        GameObject newDisk = null;
        if (free.Count > 0)
        {
            newDisk = free[0].gameObject;
            free.Remove(free[0]);
        }
        else
        {
            newDisk = GameObject.Instantiate<GameObject>(diskPrefab, Vector3.zero, Quaternion.identity);
            newDisk.AddComponent<DiskData>();
        }
        
        /**
         * 以下几句代码是用来随机生成飞碟的颜色的,并根据回合数来限制飞碟可用的颜色
         * 第一回合智能生成黄色的飞碟,第二回合飞碟可以有黄色和红色,第三回合黄,红
         * 黑三种颜色的飞碟都可以出现,start变量是用来改变每一回合飞碟出现的概率的
         */
          
        int start = 0;
        if (round == 1) start = 100;
        if (round == 2) start = 250;
        int selectedColor = Random.Range(start, round * 499);

        if (selectedColor > 500)
        {
            round = 2;
        }
        else if (selectedColor > 300)
        {
            round = 1;
        }
        else
        {
            round = 0;
        }

        /**
         * 根据回合数来生成相应的飞碟
         */
        DiskData diskdata = newDisk.GetComponent<DiskData>();
        switch (round)
        {
           
            case 0:
                {
                    diskdata.color = Color.yellow;
                    diskdata.speed = 4.0f;
                    float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;
                    diskdata.direction = new Vector3(RanX, 1, 0);
                    newDisk.GetComponent<Renderer>().material.color = Color.yellow;
                    break;
                }
            case 1:
                {
                    diskdata.color = Color.red;
                    diskdata.speed = 6.0f;
                    float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;
                    diskdata.direction = new Vector3(RanX, 1, 0);
                    newDisk.GetComponent<Renderer>().material.color = Color.red;
                    break;
                }
            case 2:
                {
                    diskdata.color = Color.black;
                    diskdata.speed = 8.0f;
                    float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;
                    diskdata.direction = new Vector3(RanX, 1, 0);
                    newDisk.GetComponent<Renderer>().material.color = Color.black;
                    break;
                }
        }

        if (mode == ActionMode.PHYSIC)
        {
            newDisk.AddComponent<Rigidbody>();
        }

        used.Add(diskdata.GetInstanceID(), diskdata);
        //newDisk.SetActive(true);
        newDisk.name = newDisk.GetInstanceID().ToString();
        return newDisk;
    }

    public void FreeDisk(GameObject disk)
    {
        DiskData tmp = null;
        foreach (DiskData i in used.Values)
        {
            if (disk.GetInstanceID() == i.gameObject.GetInstanceID())
            {
                tmp = i;
            }
        }
        if (tmp != null) {
            tmp.gameObject.SetActive(false);
            free.Add(tmp);
            used.Remove(tmp.GetInstanceID());
        }
    }
}

二.飞碟的数据信息(DiskData.cs)

/*
 * 这个文件是用来保存飞碟的一些信息,
 * DiskData作为组件挂载在飞碟上
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class DiskData : MonoBehaviour {

    public Vector3 size;
    public Color color;
    public float speed;
    public Vector3 direction;
}


三.所有场景控制器要实现的接口(ISceneControl.cs)

/*
 * 场景控制的必须实现的接口
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface ISceneControl  {
    void LoadResources();
}


四.控制场景切换类(Director.cs)

/**
 * 这个文件是用来场景控制的,负责各个场景的切换,
 * 虽然目前只有一个场景
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Director : System.Object {

    /**
     * currentSceneControl标志目前正在使用的场景
     */

    public ISceneControl currentSceneControl { get; set; }

    /**
     * Director这个类是采用单例模式
     */ 

    private static Director director;

    private Director()
    {

    }

	public static Director getInstance()
    {
        if (director == null)
        {
            director = new Director();
        }
        return director;
    }
}


五.控制第一个场景的类(FirstSceneContrlo.cs)

/**
 * 这个文件是用来控制主游戏场景的
 */ 

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

public class FirstSceneControl : MonoBehaviour, ISceneControl, IUserAction {

    public ActionMode mode { get; set; }

    /**
     * actionManager是用来指定当前的动作管理器
     */

    public IActionManager actionManager { get; set; }

    /**
     * scoreRecorder是用来指定当前的记分管理对象的
     */

    public ScoreRecorder scoreRecorder { get; set; }

    /**
     * diskQueue是用来保存一个回合要发射的飞碟
     */

    public Queue<GameObject> diskQueue = new Queue<GameObject>();

    /**
     * diskNumber是用来保存一回合要发射的飞碟总数
     */

    private int diskNumber;

    /**
     * currentRound是用来保存当前是那一回合
     */

    private int currentRound = -1;

    /**
     * round是用来保存总共有多少回合,这里是3,
     * 不过,这个游戏的实现是不断的循环的,即过了
     * 第三回合,又回到第一回合
     */
      
    public int round = 3;

    /**
     * time是用来保存每个飞碟的发射时间间隔
     */
      
    private float time = 0;

    /**
     * gameState是用来保存当前的游戏状态
     */

    private GameState gameState = GameState.START;
    
    void Awake () {
        Director director = Director.getInstance();
        director.currentSceneControl = this;
        diskNumber = 10;
        this.gameObject.AddComponent<ScoreRecorder>();
        this.gameObject.AddComponent<DiskFactory>();
        this.gameObject.AddComponent<CCFlyActionFactory>();
        mode = ActionMode.NOTSET;
        scoreRecorder = Singleton<ScoreRecorder>.Instance;
        director.currentSceneControl.LoadResources();
    }
	
    private void Update()
    {
        /**
         * 以下代码用来管理游戏的状态
         */
        if (mode != ActionMode.NOTSET && actionManager != null)
        {
            if (actionManager.getDiskNumber() == 0 && gameState == GameState.RUNNING)
            {
                gameState = GameState.ROUND_FINISH;

            }

            if (actionManager.getDiskNumber() == 0 && gameState == GameState.ROUND_START)
            {
                currentRound = (currentRound + 1) % round;
                NextRound();
                actionManager.setDiskNumber(10);
                gameState = GameState.RUNNING;
            }

            if (time > 1)
            {
                ThrowDisk();
                time = 0;
            }
            else
            {
                time += Time.deltaTime;
            }
        }  
        
        

    }

    private void NextRound()
    {
        DiskFactory df = Singleton<DiskFactory>.Instance;
        for (int i = 0; i < diskNumber; i++)
        {
            diskQueue.Enqueue(df.GetDisk(currentRound, mode));
        }

        actionManager.StartThrow(diskQueue);
        
    }

    void ThrowDisk()
    {
        if (diskQueue.Count != 0)
        {
            GameObject disk = diskQueue.Dequeue();

            /**
             * 以下几句代码是随机确定飞碟出现的位置
             */
              
            Vector3 position = new Vector3(0, 0, 0);
            float y = UnityEngine.Random.Range(0f, 4f);
            position = new Vector3(-disk.GetComponent<DiskData>().direction.x * 7, y, 0);
            disk.transform.position = position;

            disk.SetActive(true);
        }
        
    }

    public void LoadResources()
    {
        //DiskFactory df = Singleton<DiskFactory>.Instance;
        //df.init(diskNumber);
        GameObject greensward = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/greensward"));
    }


    public void GameOver()
    {
        GUI.color = Color.red;
        GUI.Label(new Rect(700, 300, 400, 400), "GAMEOVER");
        
    }

    public int GetScore()
    {
        return scoreRecorder.score;
    }

    public GameState getGameState()
    {
        return gameState;
    }

    public void setGameState(GameState gs)
    {
        gameState = gs;
    }

    public void hit(Vector3 pos)
    {
        Ray ray = Camera.main.ScreenPointToRay(pos);

        RaycastHit[] hits;
        hits = Physics.RaycastAll(ray);
        for (int i = 0; i < hits.Length; i++)
        {
            RaycastHit hit = hits[i];

            if (hit.collider.gameObject.GetComponent<DiskData>() != null)
            {
                scoreRecorder.Record(hit.collider.gameObject);

                /**
                 * 如果飞碟被击中,那么就移到地面之下,由工厂负责回收
                 */
                  
                hit.collider.gameObject.transform.position = new Vector3(0, -5, 0);
            }

        }
    }

    public ActionMode getMode()
    {
        return mode;
    }

    public void setMode(ActionMode m)
    {
        
        if (m == ActionMode.KINEMATIC)
        {
            this.gameObject.AddComponent<CCActionManager>();
        }
        else
        {
            this.gameObject.AddComponent<PhysicActionManager>();
        }

   	mode = m;
    }
}


六.动作管理器要实现的接口(IActionManager.cs)


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

public interface IActionManager {
    void StartThrow(Queue<GameObject> diskQueue);
    int getDiskNumber();
    void setDiskNumber(int num);
}


七.运动学的动作管理器(CCActionManager.cs)

/**
 * 这个文件是管理动作的具体动作管理器,是用来管理飞碟的飞行动作
 */
  
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CCActionManager : MonoBehaviour, IActionManager, ISSActionCallback {
    
    public FirstSceneControl sceneController;
    public int DiskNumber = 0;


    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //保存所以已经注册的动作
    private List<SSAction> waitingAdd = new List<SSAction>();                           //动作的等待队列,在这个对象保存的动作会稍后注册到动作管理器里
    private List<int> waitingDelete = new List<int>();                                  //动作的删除队列,在这个对象保存的动作会稍后删除

    protected void Start()
    {
        sceneController = (FirstSceneControl)Director.getInstance().currentSceneControl;
        sceneController.actionManager = this;

    }

    // Update is called once per frame
    protected void Update()
    {
        //把等待队列里所有的动作注册到动作管理器里
        foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
        waitingAdd.Clear();

        //管理所有的动作,如果动作被标志为删除,则把它加入删除队列,被标志为激活,则调用其对应的Update函数
        foreach (KeyValuePair<int, SSAction> kv in actions)
        {
            SSAction ac = kv.Value;
            if (ac.destroy)
            {
                waitingDelete.Add(ac.GetInstanceID());
            }
            else if (ac.enable)
            {
                ac.Update();
            }
        }

        //把删除队列里所有的动作删除
        foreach (int key in waitingDelete)
        {
            SSAction ac = actions[key];
            actions.Remove(key);
            DestroyObject(ac);
        }
        waitingDelete.Clear();
    }

    //初始化一个动作
    public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager)
    {
        action.gameobject = gameobject;
        action.transform = gameobject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }


    public void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Competeted,
        int intParam = 0,
        string strParam = null,
        UnityEngine.Object objectParam = null)
    {
        if (source is CCFlyAction)
        {
            DiskNumber--;
            source.gameobject.SetActive(false);
        }
    }

    public void StartThrow(Queue<GameObject> diskQueue)
    {
        CCFlyActionFactory cf = Singleton<CCFlyActionFactory>.Instance;
        foreach (GameObject tmp in diskQueue)
        {
            RunAction(tmp, cf.GetSSAction(), (ISSActionCallback)this);
        }
    }

    public int getDiskNumber()
    {
        return DiskNumber;
    }

    public void setDiskNumber(int num)
    {
        DiskNumber = num;
    }
}



八.动力学的动作管理器(PhysicActionManager.cs)

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

public class PhysicActionManager : MonoBehaviour, IActionManager, ISSActionCallback
{

	/**
 * 这个文件是管理动作的具体动作管理器,是用来管理飞碟的飞行动作
 */
  
    public FirstSceneControl sceneController;
    public int DiskNumber = 0;


    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //保存所以已经注册的动作
    private List<SSAction> waitingAdd = new List<SSAction>();                           //动作的等待队列,在这个对象保存的动作会稍后注册到动作管理器里
    private List<int> waitingDelete = new List<int>();                                  //动作的删除队列,在这个对象保存的动作会稍后删除

    protected void Start()
    {
        sceneController = (FirstSceneControl)Director.getInstance().currentSceneControl;
        sceneController.actionManager = this;

    }

    // Update is called once per frame
    protected void FixedUpdate()
    {
        //把等待队列里所有的动作注册到动作管理器里
        foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
        waitingAdd.Clear();

        //管理所有的动作,如果动作被标志为删除,则把它加入删除队列,被标志为激活,则调用其对应的Update函数
        foreach (KeyValuePair<int, SSAction> kv in actions)
        {
            SSAction ac = kv.Value;
            if (ac.destroy)
            {
                waitingDelete.Add(ac.GetInstanceID());
            }
            else if (ac.enable)
            {
                ac.FixedUpdate();
            }
        }

        //把删除队列里所有的动作删除
        foreach (int key in waitingDelete)
        {
            SSAction ac = actions[key];
            actions.Remove(key);
            DestroyObject(ac);
        }
        waitingDelete.Clear();
    }

    //初始化一个动作
    public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager)
    {
        action.gameobject = gameobject;
        action.transform = gameobject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }


    public void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Competeted,
        int intParam = 0,
        string strParam = null,
        UnityEngine.Object objectParam = null)
    {
        if (source is CCFlyAction)
        {
            DiskNumber--;
            source.gameobject.SetActive(false);
        }
    }

    public void StartThrow(Queue<GameObject> diskQueue)
    {
        CCFlyActionFactory cf = Singleton<CCFlyActionFactory>.Instance;
        foreach (GameObject tmp in diskQueue)
        {
            RunAction(tmp, cf.GetSSAction(), (ISSActionCallback)this);
        }
    }

    public int getDiskNumber()
    {
        return DiskNumber;
    }

    public void setDiskNumber(int num)
    {
        DiskNumber = num;
    }
}

九.动作的基类(SSAction.cs)


/**
 * 所有动作的基类
 */ 

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

public class SSAction : ScriptableObject {

    public bool enable = false;
    public bool destroy = false;

    public GameObject gameobject { get; set; }
    public Transform transform { get; set; }
    public ISSActionCallback callback { get; set; }

    protected SSAction() { }

    public virtual void Start() {
        throw new System.NotImplementedException();
	}
	
	// Update is called once per frame
	public virtual void Update() {
        throw new System.NotImplementedException();
    }

    public virtual void FixedUpdate()
    {
        throw new System.NotImplementedException();
    }

    public void reset()
    {
        enable = false;
        destroy = false;
        gameobject = null;
        transform = null;
        callback = null;
    }
}

十.飞碟飞行的动作(CCFlyAction.cs)


/**
 * 这个文件是实现飞碟的飞行动作
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CCFlyAction : SSAction {

    /**
     * acceleration是重力加速度,为9.8
     */

    float acceleration;

    /**
     * horizontalSpeed是飞碟水平方向的速度
     */

    float horizontalSpeed;

    /**
     * direction是飞碟的初始飞行方向
     */

    Vector3 direction;

    /**
     * time是飞碟已经飞行的时间
     */
      
    float time;

    Rigidbody rigidbody;

    DiskData disk;

    public override void Start () {
        disk = gameobject.GetComponent<DiskData>();
        enable = true;
        acceleration = 9.8f;
        time = 0;
        horizontalSpeed = disk.speed;
        direction = disk.direction;

        rigidbody = this.gameobject.GetComponent<Rigidbody>();
        if (rigidbody)
        {
            rigidbody.velocity = horizontalSpeed * direction;
        }

    }

    // Update is called once per frame
    public override void Update () {
        if (gameobject.activeSelf)
        {
            /**
             * 计算飞碟的累计飞行时间
             */ 
            time += Time.deltaTime;

            /**
             * 飞碟在竖直方向的运动
             */
              
            transform.Translate(Vector3.down * acceleration * time * Time.deltaTime);

            /**
             * 飞碟在水平方向的运动
             */

            transform.Translate(direction * horizontalSpeed * Time.deltaTime);

            /**
             * 当飞碟的y坐标比-4小时,飞碟落地
             */
              
            if (this.transform.position.y < -4)
            {
                this.destroy = true;
                this.enable = false;
                this.callback.SSActionEvent(this);
            }
        }
       
	}

    public override void FixedUpdate()
    {

        if (gameobject.activeSelf)
        {
            if (this.transform.position.y < -4)
            {
                this.destroy = true;
                this.enable = false;
                this.callback.SSActionEvent(this);
            }
        }
    }

    public static CCFlyAction GetCCFlyAction()
    {
        CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction>();
        return action;
    }
}

十一.负责动作与动作管理器间通信的接口(ISSActionCallback.cs)


/**
 * 这个接口负责动作与动作管理器间的通信
 */ 

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

public enum SSActionEventType:int { Started, Competeted }

public interface ISSActionCallback {
    void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Competeted,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null);
	
}



十二.运动脚本回收工厂类(CCFlyActionFactory.cs)

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

public class CCFlyActionFactory : MonoBehaviour
{


    /**
    * used是用来保存正在使用的动作
    * free是用来保存还未被激活的动作
    */

    private Dictionary<int, SSAction> used = new Dictionary<int, SSAction>();
    private List<SSAction> free = new List<SSAction>();
    private List<int> wait = new List<int>();

    public CCFlyAction Fly;

    // Use this for initialization
    void Start()
    {
        Fly = CCFlyAction.GetCCFlyAction();
    }


    private void Update()
    {
        foreach (var tmp in used.Values)
        {
            if (tmp.destroy)
            {
                wait.Add(tmp.GetInstanceID());
            }
        }

        foreach (int tmp in wait)
        {
            FreeSSAction(used[tmp]);
        }
        wait.Clear();
    }

 
    /**
     * GetSSAction这个函数是用来获取CCFlyAction这个动作的,
     * 每次首次判断free那里还有没有未使用的CCFlyActon这个动作,
     * 有就从free那里获取,没有就生成一个CCFlyAction
     */

    public SSAction GetSSAction()
    {
        SSAction action = null;
        if (free.Count > 0)
        {
            action = free[0];
            free.Remove(free[0]);
            Debug.Log(free.Count);
        }
        else
        {
            action = ScriptableObject.Instantiate<CCFlyAction>(Fly);
            
        }

        used.Add(action.GetInstanceID(), action);
        return action;
    }

    public void FreeSSAction(SSAction action)
    {
        SSAction tmp = null;
        int key = action.GetInstanceID();
        if (used.ContainsKey(key))
        {
            tmp = used[key];
        }

        if (tmp != null)
        {
            tmp.reset();
            free.Add(tmp);
            used.Remove(key);
        }
    }

    public void clear()
    {
        foreach (var tmp in used.Values)
        {
            tmp.enable = false;
            tmp.destroy = true;

        }
    }
}

十三.负责界面与场景控制器通信的接口(IUserAction.cs)


/**
 * UI界面与场景管理器通信的接口
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum GameState { ROUND_START, ROUND_FINISH, RUNNING, PAUSE, START}
public enum ActionMode { PHYSIC, KINEMATIC, NOTSET }

public interface IUserAction {
    void GameOver();
    GameState getGameState();
    void setGameState(GameState gs);
    int GetScore();
    void hit(Vector3 pos);
    ActionMode getMode();
    void setMode(ActionMode m);
}


十四.负责界面的类(UserGUI.cs)


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

public class UserGUI : MonoBehaviour
{
    private IUserAction action;
    bool isFirst = true;
	// Use this for initialization
	void Start () {
        action = Director.getInstance().currentSceneControl as IUserAction;

	}

    private void OnGUI()
    {
        if (action.getMode() == ActionMode.NOTSET)
        {
            if (GUI.Button(new Rect(700, 100, 90, 90), "KINEMATIC"))
            {
                action.setMode(ActionMode.KINEMATIC);
            }
            if (GUI.Button(new Rect(600, 100, 90, 90), "PHYSIC"))
            {
                action.setMode(ActionMode.PHYSIC);
            }
        }
        else
        {
            if (Input.GetButtonDown("Fire1"))
            {

                Vector3 pos = Input.mousePosition;
                action.hit(pos);

            }

            GUI.Label(new Rect(1000, 0, 400, 400), action.GetScore().ToString());

            if (isFirst && GUI.Button(new Rect(700, 100, 90, 90), "Start"))
            {
                isFirst = false;
                action.setGameState(GameState.ROUND_START);
            }

            if (!isFirst && action.getGameState() == GameState.ROUND_FINISH && GUI.Button(new Rect(700, 100, 90, 90), "Next Round"))
            {
                action.setGameState(GameState.ROUND_START);
            }
        }
    }

   
}


十五.负责得分规则的类(ScoreRecorder.cs)


/**
 * 这个类是用来记录玩家得分的
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScoreRecorder : MonoBehaviour {

    /**
     * score是玩家得到的总分
     */
      
    public int score;

    /**
     * scoreTable是一个得分的规则表,每种飞碟的颜色对应着一个分数
     */

    private Dictionary<Color, int> scoreTable = new Dictionary<Color, int>();

	// Use this for initialization
	void Start () {
        score = 0;
        scoreTable.Add(Color.yellow, 1);
        scoreTable.Add(Color.red, 2);
        scoreTable.Add(Color.black, 4);
	}

    public void Record(GameObject disk)
    {
        score += scoreTable[disk.GetComponent<DiskData>().color];
    }

    public void Reset()
    {
        score = 0;
    }
}


十六.用来实现单实例的模板(Singleton.cs)

/**
 * 这是一个实现单例模式的模板,所有的MonoBehaviour对象都用这个模板来实现单实例
 */
  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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;
        }
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值