• Unity 中的 PlayerLoop


    在Unity 2018的PlayerLoop中,禁用Unity调用每一帧的处理或在Update之前添加您自己的处理

     这次,使用从Unity 2018添加的PlayerLoop,您可以添加或自定义您自己的事件,例如Unity事件(Update,FixedUpdate)等

    Unity 2018.1 引入了一个名为PlayerLoop 的功能。这是Unity引擎重新更新过程的顺序,或停止特定的事件,或插入自己的处理似乎是有可能这样。

    获取标准事件列表

    using UnityEngine;
    using UnityEngine.Experimental.LowLevel;
    public class ShowPlayerLoop
    {
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
        static void Init()
        {
            var playerLoop = PlayerLoop.GetDefaultPlayerLoop();
     
            foreach (var header in playerLoop.subSystemList)
            {
                Debug.LogFormat("------{0}------", header.type.Name);
                foreach (var subSystem in header.subSystemList)
                {
                    Debug.LogFormat("{0}.{1}", header.type.Name, subSystem.type.Name);
                }
            }
        }
    }

    首先var playerLoop = PlayerLoop.GetDefaultPlayerLoop();获得所有标准事件。

    重要的是playerLoop.subSystemList,存储在此列表中的方法是递归调用的。如果要自定义调用,则将编辑此subSystemList的各个部分。

    此外,此部分中要获取的方法列表似乎与UnityEngine.Experimental.PlayLoop中可以检查的方法相匹配。

    ------Initialization------
    Initialization.PlayerUpdateTime
    Initialization.AsyncUploadTimeSlicedUpdate
    Initialization.SynchronizeInputs
    Initialization.SynchronizeState
    Initialization.XREarlyUpdate
    ------EarlyUpdate------
    EarlyUpdate.PollPlayerConnection
    EarlyUpdate.ProfilerStartFrame
    EarlyUpdate.GpuTimestamp
    EarlyUpdate.UnityConnectClientUpdate
    EarlyUpdate.CloudWebServicesUpdate
    EarlyUpdate.UnityWebRequestUpdate
    EarlyUpdate.ExecuteMainThreadJobs
    EarlyUpdate.ProcessMouseInWindow
    EarlyUpdate.ClearIntermediateRenderers
    EarlyUpdate.ClearLines
    EarlyUpdate.PresentBeforeUpdate
    EarlyUpdate.ResetFrameStatsAfterPresent
    EarlyUpdate.UpdateAllUnityWebStreams
    EarlyUpdate.UpdateAsyncReadbackManager
    EarlyUpdate.UpdateTextureStreamingManager
    EarlyUpdate.UpdatePreloading
    EarlyUpdate.RendererNotifyInvisible
    EarlyUpdate.PlayerCleanupCachedData
    EarlyUpdate.UpdateMainGameViewRect
    EarlyUpdate.UpdateCanvasRectTransform
    EarlyUpdate.UpdateInputManager
    EarlyUpdate.ProcessRemoteInput
    EarlyUpdate.XRUpdate
    EarlyUpdate.TangoUpdate
    EarlyUpdate.ScriptRunDelayedStartupFrame
    EarlyUpdate.UpdateKinect
    EarlyUpdate.DeliverIosPlatformEvents
    EarlyUpdate.DispatchEventQueueEvents
    EarlyUpdate.DirectorSampleTime
    EarlyUpdate.PhysicsResetInterpolatedTransformPosition
    EarlyUpdate.NewInputBeginFrame
    EarlyUpdate.SpriteAtlasManagerUpdate
    EarlyUpdate.PerformanceAnalyticsUpdate
    ------FixedUpdate------
    FixedUpdate.ClearLines
    FixedUpdate.NewInputEndFixedUpdate
    FixedUpdate.DirectorFixedSampleTime
    FixedUpdate.AudioFixedUpdate
    FixedUpdate.ScriptRunBehaviourFixedUpdate
    FixedUpdate.DirectorFixedUpdate
    FixedUpdate.LegacyFixedAnimationUpdate
    FixedUpdate.XRFixedUpdate
    FixedUpdate.PhysicsFixedUpdate
    FixedUpdate.Physics2DFixedUpdate
    FixedUpdate.DirectorFixedUpdatePostPhysics
    FixedUpdate.ScriptRunDelayedFixedFrameRate
    FixedUpdate.ScriptRunDelayedTasks
    FixedUpdate.NewInputBeginFixedUpdate
    ------PreUpdate------
    PreUpdate.PhysicsUpdate
    PreUpdate.Physics2DUpdate
    PreUpdate.CheckTexFieldInput
    PreUpdate.IMGUISendQueuedEvents
    PreUpdate.NewInputUpdate
    PreUpdate.SendMouseEvents
    PreUpdate.AIUpdate
    PreUpdate.WindUpdate
    PreUpdate.UpdateVideo
    ------Update------
    Update.ScriptRunBehaviourUpdate
    Update.ScriptRunDelayedDynamicFrameRate
    Update.DirectorUpdate
    ------PreLateUpdate------
    PreLateUpdate.AIUpdatePostScript
    PreLateUpdate.DirectorUpdateAnimationBegin
    PreLateUpdate.LegacyAnimationUpdate
    PreLateUpdate.DirectorUpdateAnimationEnd
    PreLateUpdate.DirectorDeferredEvaluate
    PreLateUpdate.UpdateNetworkManager
    PreLateUpdate.UpdateMasterServerInterface
    PreLateUpdate.UNetUpdate
    PreLateUpdate.EndGraphicsJobsLate
    PreLateUpdate.ParticleSystemBeginUpdateAll
    PreLateUpdate.ScriptRunBehaviourLateUpdate
    PreLateUpdate.ConstraintManagerUpdate
    ------PostLateUpdate------
    PostLateUpdate.PlayerSendFrameStarted
    PostLateUpdate.DirectorLateUpdate
    PostLateUpdate.ScriptRunDelayedDynamicFrameRate
    PostLateUpdate.PhysicsSkinnedClothBeginUpdate
    PostLateUpdate.UpdateCanvasRectTransform
    PostLateUpdate.PlayerUpdateCanvases
    PostLateUpdate.UpdateAudio
    PostLateUpdate.ParticlesLegacyUpdateAllParticleSystems
    PostLateUpdate.ParticleSystemEndUpdateAll
    PostLateUpdate.UpdateCustomRenderTextures
    PostLateUpdate.UpdateAllRenderers
    PostLateUpdate.EnlightenRuntimeUpdate
    PostLateUpdate.UpdateAllSkinnedMeshes
    PostLateUpdate.ProcessWebSendMessages
    PostLateUpdate.SortingGroupsUpdate
    PostLateUpdate.UpdateVideoTextures
    PostLateUpdate.UpdateVideo
    PostLateUpdate.DirectorRenderImage
    PostLateUpdate.PlayerEmitCanvasGeometry
    PostLateUpdate.PhysicsSkinnedClothFinishUpdate
    PostLateUpdate.FinishFrameRendering
    PostLateUpdate.BatchModeUpdate
    PostLateUpdate.PlayerSendFrameComplete
    PostLateUpdate.UpdateCaptureScreenshot
    PostLateUpdate.PresentAfterDraw
    PostLateUpdate.ClearImmediateRenderers
    PostLateUpdate.PlayerSendFramePostPresent
    PostLateUpdate.UpdateResolution
    PostLateUpdate.InputEndFrame
    PostLateUpdate.TriggerEndOfFrameCallbacks
    PostLateUpdate.GUIClearEvents
    PostLateUpdate.ShaderHandleErrors
    PostLateUpdate.ResetInputAxis
    PostLateUpdate.ThreadedLoadingDebug
    PostLateUpdate.ProfilerSynchronizeStats
    PostLateUpdate.MemoryFrameMaintenance
    PostLateUpdate.ExecuteGameCenterCallbacks
    PostLateUpdate.ProfilerEndFrame

    覆盖PlayerLoop本身

     我将用我认为最强大的进程取代PlayerLoop 。

    正确地说,一旦你没有调用Unity的基本功能的各种处理,请将处理插入其中。

    这本身很容易实现。但是,如果您不调用进程== Unity循环被完全销毁,Unity使用的大多数函数都将停止。 物理操作,输入和UI 的所有操作都死掉了。

    using UnityEngine;
    using UnityEngine.Experimental.LowLevel;
    public class SpawnSystem
    {
        [RuntimeInitializeOnLoadMethod()]
        static void Init()
        {
            var mySystem = new PlayerLoopSystem()
            {
                type = typeof(MyLoopSystemUpdate),
                updateDelegate = () =>
                {
                    Debug.Log("DO IT!!!");
                }
            };
            var playerLoop = new PlayerLoopSystem();
            playerLoop.subSystemList = new PlayerLoopSystem[] { mySystem };
            PlayerLoop.SetPlayerLoop(playerLoop);
        }
        public struct MyLoopSystemUpdate { }
    }

    这次,我会尝试在更新之前执行类似...的 函数你可以看到每帧都在打印Log, 但是画面都是静止的, 因为之前的正常循环都被覆盖没有了。

    using UnityEngine;
    using UnityEngine.Experimental.LowLevel;
    using System.Collections.Generic;
    public class PreUpdateSystem
    {
        [RuntimeInitializeOnLoadMethod()]
        static void Init()
        {
            var mySystem = new PlayerLoopSystem()
            {
                type = typeof(MyLoopSystemUpdate),
                updateDelegate = () =>
                {
                    Debug.Log("DO IT!!!");
                }
            };
            var playerLoop = PlayerLoop.GetDefaultPlayerLoop();
            var updateSystem = playerLoop.subSystemList[4]; // Update
            var subSystem = new List<PlayerLoopSystem>(updateSystem.subSystemList);
            subSystem.Insert(0, mySystem);
            updateSystem.subSystemList = subSystem.ToArray();
            playerLoop.subSystemList[4] = updateSystem;
            PlayerLoop.SetPlayerLoop(playerLoop);
        }
        public struct MyLoopSystemUpdate { }
    }

    我正在做的就是重写subSystemList的内容并反映它。playerLoop.subSystemList[4];从更新过程中取出,在顶部添加您自己的进程并返回。现在整个显示如果有动画的话, 又动起来了~~~

    下面的列表是Unity调用的事件获取的事件列表。

    结果如下,我在FixedUpdate和Update之间插入了自己的事件。

     

    禁用特定事件

    最后,尝试禁用某些事件。这也很简单,只需准备一个已删除特定事件的PlayerLoop版本,然后执PlayerLoop.SetPlayerLoop。

     这次,我将尝试禁用FixedUpdate.PhysicsFixedUpdate。

    using UnityEngine;
    using UnityEngine.Experimental.LowLevel;
    using UnityEngine.Experimental.PlayerLoop;
    using System.Collections.Generic;
    public class StopPhysicsFixedUpdate
    {
        static PlayerLoopSystem[] originalPlayerLoop, updatedPlayerLoop;
        [RuntimeInitializeOnLoadMethod()]
        static void Init()
        {
            var playerLoop = PlayerLoop.GetDefaultPlayerLoop();
            originalPlayerLoop = playerLoop.subSystemList[2].subSystemList; // Update
            var subSystem = new List<PlayerLoopSystem>(originalPlayerLoop);
            subSystem.RemoveAll(c => c.type == typeof(FixedUpdate.PhysicsFixedUpdate));
            updatedPlayerLoop = subSystem.ToArray();
            PhysicsOFF();
        }
        public static void PhysicsOFF()
        {
            var playerLoop = PlayerLoop.GetDefaultPlayerLoop();
            var sub = playerLoop.subSystemList[2];
            sub.subSystemList = updatedPlayerLoop;
            playerLoop.subSystemList[2] = sub;
            PlayerLoop.SetPlayerLoop(playerLoop);
        }
        public static void PhysicsON()
        {
            var playerLoop = PlayerLoop.GetDefaultPlayerLoop();
            var sub = playerLoop.subSystemList[2];
            sub.subSystemList = originalPlayerLoop;
            playerLoop.subSystemList[2] = sub;
            PlayerLoop.SetPlayerLoop(playerLoop);
        }
    }

    就个人而言,我认识到在Update之前添加初始化处理以及在帧结束时收集信息是一个很好的用法。

  • 相关阅读:
    @import的最优写法
    IE7 下hack的方法
    在Linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file or directory。
    MySQL 依赖另外一个统计出来数据更新表数据的范例
    PHP的bool值
    Ubuntu 下如何配置Jira
    ubuntu 访问Windows的共享
    备份 mysql数据
    ubuntu从中文切换成英文的方法
    css锚点定位偏移原理兼容浏览器
  • 原文地址:https://www.cnblogs.com/Jean90/p/16193938.html
Copyright © 2020-2023  润新知