example
example

教程 [最佳实践] 优化您的资源性能

Yann

站长
管理成员
GTAOS管理组
认证卖家
认证用户
本 月 名 人 榜 最 佳
原贴:https://forum.cfx.re/t/best-practice-improve-your-resource-performance/105509
最近 FiveM 添加了一项功能,缓慢的资源将会显示给所有玩家作为警告。在本指南中,我们将介绍您可以执行的一些基本步骤,以防止出现警告。该指南主要针对有勇气的开发者或服务器所有者

您的资源运行速度是否缓慢,并且您已尝试了本指南中的所有内容?请在此处发帖,以便我们可以通过最佳实践进一步扩展本指南,并查明您的脚本可能存在的问题。任何其他建议非常感谢!

背景!​

1722183739272.png
在我们解决性能问题之前,对于那些没有看到警告消息的人来说,了解慢速资源警告的内容、时间和方式会非常方便:

该消息由 3 个关键数据点组成,您肯定需要这些数据点来调试遇到的任何问题。该消息的格式如下:
[resource] is taking [time] ms (or -[fps] FPS @ 60 Hz)
[resource] 是速度慢的资源的资源名称,它直接与服务器的资源/目录中的文件夹名称相关。

[time] 是执行整个资源所花费的时间(以毫秒为单位)。需要注意的是,这是一个连续测量,不是一次性的(即加载)。该时间为 64 个刻度的平均值,如果 64 个样本的平均值大于 5 毫秒,则会显示警告消息。

[fps] 是运行该资源所扣除的 FPS 总量。请记住,这是基于 60 FPS 的基础上的。

提高运行效率​

频率
最明显但仍有很多脚本执行此操作的之一是代码运行的频率。我经常看到使用 Citizen.Wait(0) 的脚本,这意味着 while 循环内的任何代码都会在每个时钟周期运行,如果其中碰巧有昂贵的逻辑,这对性能不利。对我来说,这似乎是弹出警告消息的第一大原因。所以这里的经验法则是:
  • 仅运行需要在每个周期运行的代码,例如名称中包含“ThisFrame”的任何本机。 (显然,每次更新都需要运行更多的本地程序)。
  • 考虑一段代码执行的合理间隔,例如您不需要每秒检查 60 次来检查玩家是否死亡,而是考虑使用每秒 1 或 2 次来检查这样的事情。
  • 隔离不需要每帧运行的任何代码。例如,您可以使用全局变量来影响每个周期运行的代码(无需执行昂贵的代码)。

例子​

初始代码 → 运行时间为 119ms
lua:
Citizen.CreateThread(function()
    while(true) do
        if IsPedDeadOrDying(PlayerPedId()) then
            ShowHudComponentThisFrame(9) -- street name
        end

        if IsPedInAnyVehicle(PlayerPedId(), true) then
            ShowHudComponentThisFrame(6) --vehicle name
        end
      Citizen.Wait(0)
    end
end)
改进的代码 → 运行时间为 7 毫秒
lua:
local isDead = false
local inVehicle = false

Citizen.CreateThread(function()
    while(true) do
        if isDead then
            ShowHudComponentThisFrame(9) -- street name
        end

        if inVehicle then
            ShowHudComponentThisFrame(6) --vehicle name
        end
      
        Citizen.Wait(0)
    end
end)

Citizen.CreateThread(function()
    while(true) do
        isDead = IsPedDeadOrDying(PlayerPedId())
        inVehicle = IsPedInAnyVehicle(PlayerPedId(), true)
        Citizen.Wait(500)
    end
end)

原生​

原生是任何脚本的核心,但请记住,原生的调用比纯 LUA 代码更昂贵。特别是当您有一条需要运行大量原生的热路径时,这将增加原生的执行时间并显着增加帧时间。所以这里是经验法则:
  • 在将(多个)原生放入某些热代码路径之前请三思而后行,因为它们会很慢,如果可能,请使用替代方案。
  • 缓存原生的结果,而不是在热代码路径中临时请求它们。是否应该缓存某些内容的一个常见指标是当您在同一范围内使用相同的本机两次或多次时。
例子
初始代码 → 运行时间为 346ms
lua:
Citizen.CreateThread(function()
  while true do
    local armor = GetPedArmour(PlayerPedId())

    armor = armor + 1
    if armor > 100 then
    armor = 0
    end

    SetPedArmour(PlayerPedId(), armor)

    Citizen.Wait(0)
  end
end)
稍微好一点的解决方案 → 运行时间为 255ms
lua:
Citizen.CreateThread(function()
  local armor = GetPedArmour(PlayerPedId())

  while true do

    armor = armor + 1
    if armor > 100 then
        armor = 0
    end
 
    SetPedArmour(PlayerPedId(), armor)
    Citizen.Wait(0)
  end
end)
更好的解决方案 → 运行时间为 216 毫秒
lua:
Citizen.CreateThread(function()
  local player = PlayerPedId()
  local armor = GetPedArmour(player)

  while true do
    armor = armor + 1
    if armor > 100 then
    armor = 0
    end

    SetPedArmour(player, armor)

    Citizen.Wait(0)
  end
end)
但这里的问题是;我们真的想每次都设置护甲吗?更长的延迟可能就足够了!

尽量把它记在心里!

简约​

保持简约!或者换句话说,不要重复自己。这不仅是一种很好的编程实践,而且对于提高性能也确实很方便。我怀疑这是相当常识性的,但那里的资源似乎仍然存在问题。

保持 简约 也适用于性能,因为我们不想计算已经计算过的内容,而是希望从之前的计算中获取结果,而不是再次重新计算,简单的东西!
例子
lua:
local pedindex = {}

function SetWeaponDrops()
    local handle, ped = FindFirstPed()
    local finished = false
    repeat
        if not IsEntityDead(ped) then
                pedindex[ped] = {}
        end
        finished, ped = FindNextPed(handle)
    until not finished
    EndFindPed(handle)

    for peds,_ in pairs(pedindex) do
        if peds ~= nil then
            SetPedDropsWeaponsWhenDead(peds, false)
        end
    end
end

Citizen.CreateThread(function()
    while true do
        Citizen.Wait(0)
        SetWeaponDrops()
    end
end)
更好的解决方法是:
lua:
function SetWeaponDrops()
    local handle, ped = FindFirstPed()
    local finished = false

    repeat
        if not IsEntityDead(ped) then
            SetPedDropsWeaponsWhenDead(ped, false)
        end
        finished, ped = FindNextPed(handle)
    until not finished

    EndFindPed(handle)
end

Citizen.CreateThread(function()
    while true do
        SetWeaponDrops()
        Citizen.Wait(500)
    end
end)

结论​

希望本指南能让您深入了解资源可能存在性能问题的原因。再次强调,如果您仍然遇到性能问题,请告诉我,我将不胜感激!

祝你好运!

只是搬运,有不懂可以楼下提问就行了
 
最后编辑:
顶部