Unity框架学习--4 Mono管理器

作用:使不继承MonoBehaviour的类能够开启协程,并且可以使用FixedUpdate、Update、LateUpdate进行每帧更新。

原理:

1、在场景中创建一个继承MonoBehaviour的"执行者"脚本,这个脚本就专门用来开启协程和监听帧更新。

2、Mono管理器访问这个"执行者"脚本,就可以实现所需的效果。

创建一个空物体,挂载一个继承自MonoBehaviour 的脚本(没有任何方法也可以)

没有继承的那个脚本代码这样写:

cs 复制代码
public void Show()
    {
        GameObject go = GameObject.Find("MonoController");
        go.AddComponent<MonoController>().StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
        while (true)
        {
            Debug.Log("协程执行中");
            yield return null;
        }
    }

就可以调用了

Mono管理器开启协程

cs 复制代码
public class MonoController : MonoBehaviour
{
    
}

MonoManager 管理类,自动创建场景物体并挂载继承有Mono的脚本

继承SingletonPatternBase 作为一个 单例存在

cs 复制代码
public class MonoManager : SingletonPatternBase<MonoManager>
{
    private MonoManager() { }

    private MonoController monoController;

    public MonoController MonoController
    {
        get
        {
            if (monoController == null)
            {
                GameObject go = new GameObject(typeof(MonoController).Name);
                monoController = go.AddComponent<MonoController>();
            }
            return monoController;
            
        }
    }

    //一个专门让外部用来开启协程的方法
    public Coroutine StartCoroutine(IEnumerator routine)
    {
        return MonoController.StartCoroutine(routine);
    }

Mono管理器停止协程

cs 复制代码
//停止协程的方法
    public void StopCoroutine(IEnumerator routine)
    {
        MonoController.StopCoroutine(routine);
    }

    //停止协程的方法 重载
    public void StopCoroutine(Coroutine coroutine)
    {
        MonoController.StopCoroutine(coroutine);
    }

    //停止所有协程的方法
    public void StopAllCoroutine()
    {
        MonoController.StopAllCoroutines();
    }
cs 复制代码
public class Player
{
    Coroutine coroutine;

    public void Show()
    {
        coroutine = MonoManager.Instance.StartCoroutine(MyCoroutine());
    }

    public void Hide()
    {
        MonoManager.Instance.StopCoroutine(coroutine);
    }

    public void HideAll()
    {
        MonoManager.Instance.StopAllCoroutine();
    }

在具体的脚本里直接MonoManager.Instance.xxx方法就可以执行

注意停止协程的写法!!!

Mono管理器Update事件监听

利用委托事件,传递方法进去执行

执行者脚本

cs 复制代码
/// <summary>
/// 执行者脚本。其他脚本可以通过它来开启停止协程,也可以通过它来监听Update,FixedUpdate。LateUpdate
/// </summary>
public class MonoController : MonoBehaviour
{
    //在生命周期方法中执行的时间
    event UnityAction updateEvent;

    private void Update()
    {
        updateEvent?.Invoke();
    }

    public void AddUpdateListener(UnityAction call)
    {
        updateEvent += call;
    }

    public void RemoveUpdateListener(UnityAction call)
    {
        updateEvent -= call;
    }

    public void RemoveAllUPdateListeners()
    {
        updateEvent = null;
    }

管理者脚本

cs 复制代码
//添加Update事件
    public void AddUpdateListener(UnityAction call)
    {
        monoController.AddUpdateListener(call);
    }

    //移除Update事件
    public void RemoveUpdateListener(UnityAction call)
    {
        monoController.RemoveUpdateListener(call);
    }

    //移除所有Update事件
    public void RemoveAllUPdateListeners()
    {
        monoController.RemoveAllUPdateListeners();
    }

具体的需要执行的方法的脚本传递委托脚本

cs 复制代码
public void PrintUpdate()
    {   //添加可以添加Lambda 表达式,但是无法从委托列表中删掉这个Lambda表达式  
        //所以一般不是很简单的逻辑不建议使用lambda表达式
        //可以声明为一个专门的方法然后添加进去
        //lambd 表达式
        MonoManager.Instance.AddUpdateListener(() => 
        { 
            Debug.Log("Update"); 
        });
    }

    public void StopPrintUpdate()
    {                               
        //这个方法是无效的,无法成功删除
        //lambd 表达式
        MonoManager.Instance.RemoveUpdateListener(() =>
        {
            Debug.Log("Update");
        });
    }

    public void StopAllPrintUpdate()
    {
        MonoManager.Instance.RemoveAllUPdateListeners();
    }

Mono管理器优化:嵌套类

很简单,就是把MonoController 声明到 MonoManager 中,没干什么额外的工作

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class MonoManager : SingletonPatternBase<MonoManager>
{
    private MonoManager() { }

    private MonoController monoExecuter;

    public MonoController MonoExecuter
    {
        get
        {
            if (monoExecuter == null)
            {
                GameObject go = new GameObject(typeof(MonoController).Name);
                monoExecuter = go.AddComponent<MonoController>();
            }
            return monoExecuter;
            
        }
    }

    //一个专门让外部用来开启协程的方法
    public Coroutine StartCoroutine(IEnumerator routine)
    {
        return MonoExecuter.StartCoroutine(routine);
    }

    //停止协程的方法
    public void StopCoroutine(IEnumerator routine)
    {
        if (routine != null)
        {
            MonoExecuter.StopCoroutine(routine);
        }
    }

    //停止协程的方法 重载
    public void StopCoroutine(Coroutine coroutine)
    {
        if (coroutine != null)
        {
            MonoExecuter.StopCoroutine(coroutine);
        }
    }

    //停止所有协程的方法
    public void StopAllCoroutine()
    {
        MonoExecuter.StopAllCoroutines();
    }

    //添加Update事件
    public void AddUpdateListener(UnityAction call)
    {
        monoExecuter.AddUpdateListener(call);
    }

    //移除Update事件
    public void RemoveUpdateListener(UnityAction call)
    {
        monoExecuter.RemoveUpdateListener(call);
    }

    //移除所有Update事件
    public void RemoveAllUPdateListeners()
    {
        monoExecuter.RemoveAllUPdateListeners();
    }

    /// <summary>
    /// 执行者脚本。其他脚本可以通过它来开启停止协程,也可以通过它来监听Update,FixedUpdate。LateUpdate
    /// </summary>
    public class MonoController : MonoBehaviour
    {
        //在生命周期方法Update中执行的事件
        event UnityAction updateEvent;

        //在生命周期方法FixUpdate中执行的事件
        event UnityAction fixUpdateEvent;

        private void FixedUpdate()
        {
            fixUpdateEvent?.Invoke();
        }

        private void Update()
        {
            updateEvent?.Invoke();
        }

        public void AddUpdateListener(UnityAction call)
        {
            updateEvent += call;
        }

        public void RemoveUpdateListener(UnityAction call)
        {
            if (updateEvent != null)
            {
                updateEvent -= call;
            }
        }

        public void RemoveAllUPdateListeners()
        {
            updateEvent = null;
        }

        public void AddFixUpdateListener(UnityAction call)
        {
            fixUpdateEvent += call;
        }

        public void RemoveFixUpdateListener(UnityAction call)
        {
            if (fixUpdateEvent != null)
            {
                fixUpdateEvent -= call;

            }
        }

        public void RemoveAllFixUpdateListeners()
        {
            fixUpdateEvent = null;
        }
    }

}
相关推荐
7 小时前
Unity开发中常用的洗牌算法
java·算法·unity·游戏引擎·游戏开发
马特说11 小时前
Unity VR手术模拟系统架构分析与数据流设计
unity·系统架构·vr
心前阳光1 天前
Unity WebGL文本输入
unity·游戏引擎·webgl
天涯过客TYGK1 天前
unity A星寻路
unity·游戏引擎
KhalilRuan1 天前
Unity Demo——3D平台跳跃游戏笔记
笔记·游戏·unity·游戏引擎
ttod_qzstudio2 天前
Unity中使用EzySlice实现模型切割与UV控制完全指南
unity
南無忘码至尊2 天前
Unity 实现与 Ollama API 交互的实时流式响应处理
unity·游戏引擎·交互
平行云2 天前
如何实现UE程序大并发多集群的像素流部署
unity·ue5·图形渲染
向宇it3 天前
【unity小技巧】在 Unity 中将 2D 精灵添加到 3D 游戏中,并实现阴影投射效果,实现类《八分旅人》《饥荒》等等的2.5D游戏效果
游戏·3d·unity·编辑器·游戏引擎·材质
向宇it3 天前
Unity Universal Render Pipeline/Lit光照材质介绍
游戏·unity·c#·游戏引擎·材质