Skip to Content
ドキュメントQb DocGuides🚀 スクリプトの最適化

🚀 スクリプトの最適化

一般診療

関数と変数をローカライズする

  • Luaはローカル変数や関数にグローバル変数や関数よりも高速にアクセスします。常にlocal明示的にグローバルである必要がない限り、変数または関数を宣言するとき
myVariable = false -- Don't use this local myVariable = false -- Use this function someFunction() -- Don't use this print('Im a global function!') end local function someFunction() -- Use this print('Im a local function!') end

代わりにテーブルインデックスを使用するtable.insert

  • table.insert若干のオーバーヘッドが発生します。値を直接割り当てる方が効率的です。
function someFunction() local table = {} table.insert(table, {}) -- Don't use this table[#table+1] = {} -- Use this end

条件チェックを簡素化する

  • 使用 if something then の代わりに if something ~= nil両方を確認するnil そして false
function someFunction() local bool = nil if bool ~= nil then -- Don't use this print('bool was not nil but also could be false!') end if bool then -- Use this print('bool was neither nil or false!') end end

関数を普遍的に保つ

  • パラメータを渡すことで複数のシナリオに対応できる関数やイベントを記述します。これによりコードの再利用性が向上します。
local function someFunction(param1, param2, param3) print('Im a function that accepts 3 parameters which allows for multiple conditions!') if param1 == 'something' then print('I met condition number one!') elseif param2 == 'somethingelse' then print('I met condition number two!') elseif param3 == 'somethingelsemore' then print('I met condition number three!') end end RegisterNetEvent('someEvent', function(param1, param2, param3) print('Im an event that accepts 3 parameters which allows for multiple conditions!') if param1 == 'something' then print('I met condition number one!') elseif param2 == 'somethingelse' then print('I met condition number two!') elseif param3 == 'somethingelsemore' then print('I met condition number three!') end end)

ショートリターン

  • 使用 ショートリターン条件が満たされない場合に関数を早期に終了する。これによりコードが整理され、不要なネストが回避される。ifブロック
local function someFunction(param1, param2, param3) if not param1 then return end print('I met condition number one!') if not param2 then return end print('I met condition number two!') if not param3 then return end print('I met condition number three!') end

テーブルや変数を繰り返し再作成しないようにする

  • ループや頻繁に呼び出される関数内でテーブルや変数を繰り返し作成するのではなく、一度初期化して再利用します。
local reusableTable = {} local function someFunction() for i = 1, 10 do reusableTable[i] = i -- Reuse the same table instead of creating a new one end end

使用 nilメモリを解放する

  • 未使用の変数を割り当てるnilLuaのガベージコレクターがメモリを解放できるようにする
local largeData = {1, 2, 3, 4} -- Process data... largeData = nil -- Free up memory when done

ハードコーディングを避ける

  • 設定可能な値(座標、アイテム名、支払金額など)を一元管理します。config.lua管理を容易にするファイル

config.lua:

Config = { Zones = { PoliceStation = vector3(441.1, -981.1, 30.7), Hospital = vector3(1151.21, -1529.62, 34.84) }, Payments = { Police = 150, EMS = 120 } }

ログとデバッグ

  • スクリプト内でデバッグモードの切り替えを使用すれば、ログを削除せずに動的にログを有効化または無効化できます。スクリプトにオプションとして追加することもできます。config.lua上から!
local DEBUG = true local function debugLog(message) if DEBUG then print(message) end end debugLog('This is a debug message!')

トラックパフォーマンス

  • パフォーマンスが重要なセクションの実行時間を測定します。os.clock()またはFiveMネイティブ
local start = os.clock() -- Code to measure print("Execution time:", os.clock() - start)
local startTime = GetGameTimer() -- Simulate a delay Wait(1000) local endTime = GetGameTimer() print("Execution time (ms):", endTime - startTime) -- Output: 1000 (approx)

ネットワークイベントの過剰な使用を避ける

  • 共有状態を使用する(例:state bags または entity states)スパムではなく、頻繁なデータ同期が必要な場合TriggerEvent または TriggerServerEvent
-- Set state Entity(playerPed).state:set('exampleData', 123, true) -- Get state local data = Entity(playerPed).state.exampleData print(data) -- Outputs: 123

データ転送の最適化

  • テーブル全体や大きなペイロードではなく、必要なデータのみを送信します
TriggerServerEvent('exampleEvent', { x = 100, y = 200 }) -- Only send necessary fields

コードの読みやすさ

コードにコメントを付ける

  • 特に複雑な部分やわかりにくい部分には、ロジックを説明するコメントを追加します。
-- Check if the player is in range of the target zone if #(playerCoords - targetCoords) < 10 then print('Player is in range') end

スクリプトを整理する

  • スクリプトを論理的に構造化し、変数、関数、イベント ハンドラー、コア ロジックを個別のセクションに分離します。
-- Variables local QBCore = exports['qb-core']:GetCoreObject() -- Functions local function calculateDistance(pos1, pos2) return #(pos1 - pos2) end -- Events RegisterNetEvent('exampleEvent', function() print('Event triggered!') end) -- Main Logic CreateThread(function() print('Script started!') end)

フォルダ構造

  • すべてを 1 つのファイルに記述するのではなく、スクリプトをより小さく管理しやすい部分に分割します。
my_script/ ├── client/ │ ├── main.lua │ ├── utils.lua ├── server/ │ ├── main.lua │ ├── events.lua ├── shared/ │ ├── config.lua └── fxmanifest.lua

ネイティブの使用法

  • 常に交換するGetPlayerPed(-1)PlayerPedId()
local function someFunction() local ped = GetPlayerPed(-1) -- Don't use this local ped = PlayerPedId() -- Use this end
  • 常に交換するGetDistanceBetweenCoordslua math 別名#(vector3 - vector3)
local function someFunction() local ped = PlayerPedId() local pCoords = GetEntityCoords(ped) local coords = vector3(-29.53, -1103.67, 26.42) local dist = GetDistanceBetweenCoords(pCoords, coords, true) -- Don't use this local dist = #(pCoords - coords) -- Use this if dist < 5 then print('Im within 5 distance units of the coords!') end end

ループ

  • whileループとその実行タイミングを制御する
local function exampleLoop() CreateThread(function() while listen do print('running while loop only when needed') Wait(0) end end) end local listen = false CreateThread(function() LoopZone = CircleZone:Create(vector3(-851.63, 74.36, 51.86), 5.0, { name = "ExampleLoop", debugPoly = true, }) LoopZone:onPlayerInOut(function(isPointInside) if isPointInside then listen = true exampleLoop() -- Initiate loop else listen = false -- turns off when your outside the zone end end) end)
  • 「while」ループを含むスレッドを作成する必要がある場合は、可能な限り「while true do」の使用を避けてください。どうしても使用する必要がある場合は、次のヒントに従うと、パフォーマンスへの影響はそれほど大きくありません。
  • スレッドの時間を制御するには、待機時間を遡及的に変更する変数を使用します。例えば、スレッドの待機時間を1000ミリ秒に設定し、if文を1秒ごとにチェックします。if文が文中に現れた場合は、変数の値を変更するだけで待機時間を短縮できます。Wait(sleep)
CreateThread(function() while true do local sleep = 2500 -- Default wait time local ped = PlayerPedId() local pos = GetEntityCoords(ped) local inRange = #(pos - vector3(-829.11, 75.03, 52.73)) < 10.0 if inRange then sleep = 0 -- Reduce wait time if condition is met print('I am in range!') else print('I am out of range.') end Wait(sleep) end end)
  • ジョブ固有のループがある場合は、そのジョブのプレイヤーにのみ適用されるようにしてください。警察官ではないプレイヤーが、自分には適用されないループを自分のマシンで実行する理由はありません。
local function exampleJobLoop() local job = QBCore.Functions.GetPlayerData().job.name CreateThread(function() while job == 'police' do print('im a policeman!') Wait(0) end end) end

安全

  • コードに過剰なセキュリティ対策を施すことは悪いことではありません。複数のif文を追加したり、イベントにランダム変数を渡すことをためらわないでください。
  • リソースのクライアント側で、お金やアイテムに関してplayerとのいかなる種類の取引も行わないでください。

Event ハンドラー

  • リソース内で変数を設定する場合、ハンドラーは、常にチェックを実行する必要がないため、特に便利です。
-- These are client-side examples local isLoggedIn = false local PlayerData = {} AddStateBagChangeHandler('isLoggedIn', nil, function(_, _, value) -- FiveM native method if value then isLoggedIn = true PlayerData = QBCore.Functions.GetPlayerData() else isLoggedIn = false PlayerData = {} end end) AddEventHandler('QBCore:Client:OnPlayerLoaded', function() -- Don't use this with the native method isLoggedIn = true PlayerData = QBCore.Functions.GetPlayerData() end) RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() -- Don't use this with the native method isLoggedIn = false PlayerData = {} end) RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo) PlayerData.job = JobInfo end) RegisterNetEvent('QBCore:Player:SetPlayerData', function(val) PlayerData = val end)
Last updated on