|
一、设计意图
在游戏开发过程中,凡是需要设计一些优化策略,以保证游戏的流畅体验。
LOD自动降档策略就是此中之一,当检测到帧率不达标的时候,可以自动触发画质档位的下降(或者其他优化方案),以保证帧率可以恢复达标的状态。
在游戏中,玩家可以按照需求选择是否开启此项优化功能。
二、设计思路
帧率检测方式:检测当前帧之前必然数量(CheckTotalCount)的游戏帧中,deltaTime超过某一阈值的帧数(DeltaTimeThreshold),若此帧数过高,超过设定数量(CheckFrameCount),则记为一次不达标。
例如,设定CheckTotalCount = 40,CheckFrameCount = 30,DeltaTimeThreshold = 0.05。
则按照策略,在某一检测帧之前的40帧内,如果有75%的帧与前一帧的间隔时间(dt)超过0.05秒,则可以把这40帧标识表记标帜为一次不达标的段。
若不达标的次数在监测范围内超过可容忍的次数, 则进行档位自适应调整。
三、实现方式
注意:代码中使用了本身实现的Update模块,可以对指定的Tick函数进行注册和注销,以实现游戏中的更新逻辑。有机会我会对此模块进行介绍,读者可以按照自身的情况实现本身的更新函数。- --[[引入Update模块]]--
- local LuaUpdater = require ”Main/LuaUpdater”
- --[[相关配置]]--
- local DeltaTimeThreshold = 0.05 --检测达成降档的DT阈值
- local CheckTotalCount = 40; -- 当前帧之前,需要统计DT状态的帧数
- local CheckFrameCount = 30; -- 需要统计的帧数中,DT高于阈值的数量
- local FRFailTolerateTimes = 3; -- 帧率检测到不达标的容忍次数
- local TotalCheckTick = 3000; -- 持续检测帧率的最大次数
- --[[定义变量]]--
- local OptimizeController = {}
- local private =
- {
- --bool队列,统计当前帧前CheckTotalCount个帧是否为不达标的帧
- reachQueue = { head = 1, tail = 1, size = 0, capacity = CheckTotalCount, array = {}, },
- --计时队列,统计不达标段的记录时间(帧号)
- frFailTickQueue = { head = 1, tail = 1, size = 0, capacity = FRFailTolerateTimes, array = {}, },
- reachCount = 0, --统计不达标的帧数
- frameCheckTick = 0, --更新函数的计时(帧号)
- }
- --[[外部接口,开启或封锁]]--
- function OptimizeController.EnableAdaptiveLOD(enable)
- if enable then
- private.StartFrameCheck()
- else
- private.StopFrameCheck()
- end
- end
- --[[内部实现]]--
- function private.StartFrameCheck()
- --开启更新
- LuaUpdater.StartRealTimeUpdate(private.Tick)
- --重置变量
- private.ClearQueue(private.reachQueue)
- private.ClearQueue(private.frFailTickQueue)
- private.reachCount = 0
- private.frameCheckTick = 0
- end
- function private.StopFrameCheck()
- --封锁更新
- LuaUpdater.StopRealTimeUpdate(private.Tick)
- end
- function private.Tick(deltaTime)
- private.frameCheckTick = private.frameCheckTick + 1
- --如果队列满了,需要出队
- if private.reachQueue.size == CheckTotalCount then
- if private.Dequeue(private.reachQueue) then
- private.reachCount = private.reachCount - 1
- end
- end
- local reach = deltaTime >= DeltaTimeThreshold
- private.Enqueue(private.reachQueue, reach) --记录是否达标的状态,reach == true 代表不达标
- if not reach then
- --当前帧如果没有呈现未达标的情况,可以跳出
- return
- end
- private.reachCount = private.reachCount + 1
- if private.reachCount < CheckFrameCount then
- --还未达到帧率不达标的情况,可以跳出
- return
- end
-
- --已经触发不达标段的计数,可以从头进行统计了
- private.ClearQueue(private.reachQueue)
- private.reachCount = 0
- --判断此次触发是否咋在统计的时间范围内
- if private.frFailTickQueue.size == FRFailTolerateTimes
- and private.frameCheckTick - private.Dequeue(private.frFailTickQueue) < TotalCheckTick then
- private.ClearQueue(private.frFailTickQueue)
- private.frameCheckTick = 0
- --[[
- 此处调用本身项目内实现的挡位调节方式
- ]]--
- else
- private.Enqueue(private.frFailTickQueue, private.frameCheckTick)
- end
- end
- --[[队列操作]]--
- function private.Enqueue(queue,item)
- if queue.size == queue.capacity then
- return
- end
- queue.array[queue.tail] = item
- queue.tail = queue.tail % queue.capacity + 1
- queue.size = queue.size + 1
- end
- function private.Dequeue(queue)
- if queue.size <= 0 then
- return nil
- end
- local item = queue.array[queue.head]
- queue.array[queue.head] = nil
- queue.head = queue.head % queue.capacity + 1
- queue.size = queue.size - 1
- return item
- end
- function private.ClearQueue(queue)
- table.clearArray(queue.array)
- queue.head = 1
- queue.tail = 1
- queue.size = 0
- end
- return OptimizeController
复制代码 可以直接Require此模块进行使用- local ctrl = require ”OptimizeController”
- ctrl.EnableAdaptiveLOD(true) --开启功能
- ctrl.EnableAdaptiveLOD(false) --封锁功能
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|