笔记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()
    {
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章