Unity通过PlayerLoopSystem接口实现不通过Monobehavior让函数在FixedUpdate阶段被调用

本文参考了 https://www.cnblogs.com/Jean90/p/16193938.html

简介

PlayerLoop是Unity提供用于修改游戏循环中系统组成的接口。我们可以分别通过PlayerLoop.GetCurrentPlayerLoopPlayerLoop.SetPlayerLoop获取和设置游戏循环。

using System.Collections;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Drawing;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using System;
using WildBoar.Base;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using NPOI.SS.Formula.Functions;
using System.Runtime.Remoting.Messaging;

public class PlayerLoopExample : EditorWindow
{

    [MenuItem("Tools/Example/PlayerLoopWindow")]
    private static void CreateWindow()
    {
        GetWindow<PlayerLoopExample>();
    }


    private void OnGUI()
    {

        if(GUILayout.Button("LogPlayerLoopInfo"))
        {
            LogPlayerLoopInfo();
        }

        if(GUILayout.Button("LogFixedUpdateSystem"))
        {
            GetAndLogFixedUpdateSystem();
        }

        if(GUILayout.Button("RemoveBehaviorFixedUpdate"))
        {
            RemoveBehaviorFixedUpdate();
        }

        if(GUILayout.Button("AddUserFixedUpdate"))
        {
            AddUserFixedUpdate();
        }

    }

    public void LogPlayerLoopInfo()
    {
        var playerLoop = PlayerLoop.GetDefaultPlayerLoop();

        int index = 0;
        foreach (var header in playerLoop.subSystemList)
        {
            Debug.LogFormat($"-----{index}-{header.type.Name}------");
            foreach (var subSystem in header.subSystemList)
            {
                Debug.LogFormat("{0}.{1}", header.type.Name, subSystem.type.Name);
            }

            index++;
        }
    }

    private void GetAndLogFixedUpdateSystem()
    {
        var playerLoopMainSystem = PlayerLoop.GetDefaultPlayerLoop();

        if(playerLoopMainSystem.TryGetSubSystem<FixedUpdate>( out var fixedUpdateSystem))
        {
            foreach (var subSystem in fixedUpdateSystem.subSystemList)
            {
                Debug.LogFormat($"{subSystem.type.Name}");
            }

        }

    }    



    private void RemoveBehaviorFixedUpdate()
    {
        var main = PlayerLoop.GetDefaultPlayerLoop();
        if(main.TryGetSubSystem<FixedUpdate>(out var fixedUpdateSystem))
        {
            var list = new List<PlayerLoopSystem>(fixedUpdateSystem.subSystemList);
            list.RemoveAll(system => system.type == typeof(FixedUpdate.ScriptRunBehaviourFixedUpdate));

            fixedUpdateSystem.subSystemList = list.ToArray();

            main.ReplaceSubSystem(fixedUpdateSystem);

            PlayerLoop.SetPlayerLoop(main);
        }

    }

    private void AddUserFixedUpdate()
    {
        var main = PlayerLoop.GetDefaultPlayerLoop();
        if (main.TryGetSubSystem<FixedUpdate>(out var fixedUpdateSystem))
        {
            var list = new List<PlayerLoopSystem>(fixedUpdateSystem.subSystemList);
            var mySystem = new PlayerLoopSystem()
            {
                type = typeof(MyUserLogFixedUpdate),
                updateDelegate = () =>
                {
                    Debug.Log("User FixedUpdate Log");
                }
            };
            list.Add(mySystem);

            fixedUpdateSystem.subSystemList = list.ToArray();

            main.ReplaceSubSystem(fixedUpdateSystem);

            PlayerLoop.SetPlayerLoop(main);
        }
    }

    struct MyUserLogFixedUpdate
    {

    }


}
    public static class PlayerLoopSystemExtend
    {
        public static bool TryGetSubSystem<T>(this PlayerLoopSystem main, out PlayerLoopSystem subSystem)
            where T: struct
        {
            foreach (var subsystem in main.subSystemList)
            {
                if (subsystem.type == typeof(T))
                {
                    subSystem = subsystem;
                    return true;
                }
            }

            subSystem = default;
            return false;
        }

        public static void ReplaceSubSystem(this PlayerLoopSystem main, PlayerLoopSystem subSystem)
        {
            for(int i = 0; i < main.subSystemList.Count(); i++)
            {
                var sub = main.subSystemList[i];
                if(sub.type == subSystem.type)
                {
                    main.subSystemList[i] = subSystem;
                }
            }

        }
    }
posted @ 2024-06-24 21:27  dewxin  阅读(23)  评论(0编辑  收藏  举报