筆記41 遊戲框架

遊戲框架的使用

不使用框架的缺點

在這裏插入圖片描述

映射到程序裏

在這裏插入圖片描述

寫幾個類

在這裏插入圖片描述

遊戲框架的編寫

代碼:信息Message+信息類型MessageType

//消息,用new,它不是一個組件。
public class Message 
{
    //類型。以後可能應用於網絡傳播,所以能用小的就用小的,byte比int小。
    public byte Type;
    //命令(很精準的命令)。例如:打開揹包
    public int Command;
    //參數。可能是任何類型,所以用object任意類型
    public object Content;

    //兩個構造方法
    public Message()
    {

    }
    public Message(byte type,int command,object content)
    {
        Type = type;
        Command = command;
        Content = content;
    }
}

//消息類型(爲了看的清除,沒有新建類)
public class MessageType
{
    //不同的類型,就是不同的數字
    public static byte Type_Audio = 1;
    public static byte Type_UI = 2;

    //每個大的類型下面,細分很多命令。
    //細分音頻。(後期有新功能就繼續添加)
    //有一個問題,比如播放音效,你需要知道播放哪個音效吧。
    //所以,有時還需要發送額外的消息(參數)。
    public static int Audio_PlaySound = 100;
    public static int Audio_PlayMusic = 102;
    public static int Audio_StopMusic = 103;
    public static int Audio_ChangeVolume = 104;
    //細分UI
    //顯示界面
    public static int UI_ShowPanel = 200;
    //添加分數
    public static int UI_AddScore = 201;
    //打開商城
    public static int UI_ShowShop = 202;
}

代碼:紫色(小模塊)層MonoBase : MonoBehaviour

public class MonoBase : MonoBehaviour
{
    //發送消息
    public void SendCustomMessage(Message msg)
    {
        MessageCenter.SendMessage(msg);
    }
    public void SendCustomMessage(byte type,int command, object content)
    {
        MessageCenter.SendMessage(type, command, content);
    }

    
    //一個方法:接收消息。
    //因爲允許重寫,所以使用虛方法。關鍵詞:父virtual,子override
    public virtual void ReceiveMessage(Message message)
    {

    }
}

代碼:消息中心MessageCenter

public class MessageCenter 
{
    //管理類集合。
    //是個靜態集合,這樣下面就可用靜態方法。靜態方法就能調用這個靜態集合了。
    //它保存的全是MonoBase類型。它保存的全是管理類,但是管理類又繼承於它。
    public static List<MonoBase> Managers = new List<MonoBase>();

    //我創建一個集合,這個集合在start方法裏都要註冊到MessageCenter當中。
    
    //功能:發送消息。
    public static void SendMessage(Message msg)
    {
        //快速遍歷管理類
        foreach (MonoBase mb in Managers)
        {
            //發消息(就是調用管理類裏接收消息的方法)
            mb.ReceiveMessage(msg);
        }
    }
    //爲了發消息更方便,往往在外界懶得構造,再給它一個方法。
    //這個方法,先把一個消息所需要的3個參數全填在這裏。
    //這樣發消息有兩種方法,用哪一種都行。
    public static void SendMessage(byte type,int command,object content)
    {
        //實例化消息(調用消息的第二個構造方法)
        Message msg = new Message(type, command, content);
        //然後再調用上面發消息的方法,把msg傳過去
        SendMessage(msg);
    }
}

代碼:管理類ManagerBase : MonoBase where T:MonoBase

//ManagerBase繼承於 MonoBase,所以它作爲管理類,也可以接收消息。
//由於它是個管理類,所以它肯定是個單例。爲了方便,把它寫成泛型,並進行約束。
//where約束 T:MonoBase這個類型必須是MonoBase及其子類類型。
//爲了,當創建ManagerBase子類的時候,都會把它子類的類型放在這當作T傳進來。結合單例,就會使得繼承ManagerBase的類直接就是單例類。就不用再寫單例這些操作了。
//總結:單例,繼承於monoBase,泛型,並約束。
public class ManagerBase<T> : MonoBase where T:MonoBase
{
    //聲明當前單例類型——T類型,不是managerBase<T>
    public static T Instance;
    //管理的消息接收者。
    public List<MonoBase> ReceiveList = new List<MonoBase>();
    //屬性:代表當前管理類接收的消息類型
    protected byte messageType;
  
    //protected受保護的,僅父類、子類可用。
    protected virtual void Awake()
    {
        //as T轉成T這個類。
        //這樣以後繼承ManagerBase的類直接就是個單例類。就不用寫單例這些操作了。
        Instance = this as T;
        //設置消息類型(爲了防止別人使用時,沒有給消息類型,老師習慣這樣做)。
        messageType = SetMessageType();
        //將當前的管理類添加到消息中心列表中
        MessageCenter.Managers.Add(this);    
    }

    //返回當前管理類的消息類型(必須實現)。在內部會自動調用S這個方法,如果是子類的話,只需要重新實現這個方法就可以了。
    protected virtual byte SetMessageType()
    {
        //比如,默認UI類型(隨便給)。【注意】MessageType是MessageType類,不要和上面申明的屬性messageType重名!!!否則點不出後面的Type_UI!
        return MessageType.Type_UI;
    }

    //註冊消息監聽。因爲有的小模塊不需要接收消息,它就不用註冊。只有接收消息的小模塊才需要註冊到管理類。
    //開放一個接口,傳進來的是MonoBase(紫色的模塊)。Register註冊Receiver接收者
    public void RegisterReceiver(MonoBase mb)
    {
        //只要這個列表裏不包含
        if (!ReceiveList.Contains(mb))
        {
            //就加到列表裏
            ReceiveList.Add(mb);
        }
    }

    //接收到了消息,並且向下分發消息
    //因爲它是繼承於MonoBase的,所以本身也有ReceiveMessage這個接收消息的方法
    public override void ReceiveMessage(Message message)
    {
        base.ReceiveMessage(message);
        //判斷。如果接收的消息類型不匹配,則不往下分發消息
        if (message.Type != messageType)
        {
            return;
        }
        //匹配,則分發
        foreach(MonoBase mb in ReceiveList)
        {
            mb.ReceiveMessage(message);
        }
    }
}

通知模式的使用

創建物體

在這裏插入圖片描述

代碼:玩家PlayerController

public class PlayerController : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //得到軸
        float vertical = Input.GetAxis("Vertical");
        float horizontal = Input.GetAxis("Horizontal");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        //如果向量不爲零
        if (dir != Vector3.zero)
        {
            //朝向量方向前進,每秒3米
            transform.Translate(dir * 3 * Time.deltaTime);
        }
    }
}

代碼:金幣CoinController : MonoBase

public class CoinController : MonoBase
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    //觸發
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            //加分。組件想調用其它功能,就用SendCustomMessage(消息類型,什麼命令,添加幾分)
            SendCustomMessage(MessageType.Type_UI, MessageType.UI_AddScore, 1);

            //銷燬
            Destroy(gameObject);
        }
    }
}

代碼:UI管理類UIManager : ManagerBase

//修改繼承ManagerBase<填入UIManager>。此時,它就是個單例了。
public class UIManager : ManagerBase<UIManager>
{
    //必須重寫的方法:設定接收的消息類型
    protected override byte SetMessageType()
    {
        //返回UI的
        return MessageType.Type_UI;
    }
}

代碼:分數ScoreController : MonoBase

//因爲使用UI,所以添加名稱空間
using UnityEngine.UI;

//相當於紫色部分,修改繼承,可以接收消息。
public class ScoreController : MonoBase
{
    public Text text;
    private int score = 0;

    void Start()
    {
        //將當前類註冊到UI管理器類中,這樣才能接收消息。把this放在這裏
        UIManager.Instance.RegisterReceiver(this);
    }

    //拿到消息
    public override void ReceiveMessage(Message message)
    {
        base.ReceiveMessage(message);
        //判斷得到的命令是不是“增加分數”
        if (message.Command == MessageType.UI_AddScore)
        {
            //添加分數
            //添加的分數當做Content(參數)傳進來,並強轉成int類型。
            //Content此時表示你添加的分數數值。
            int add = (int)message.Content;
            //增加分數
            score += add;
            //刷新。轉成字符串
            text.text = score + "";
        }
    }
}

代碼:小地圖 MapController : MonoBase

public class MapController : MonoBase
{
    // Start is called before the first frame update
    void Start()
    {
        //將當前類註冊到UI管理器類中,這樣才能接收消息。把this放在這裏
        UIManager.Instance.RegisterReceiver(this);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章