ox_target addBoxZone उदाहरण - FiveM Raycast Targeting Lua
ox_target addBoxZone उदाहरण कॉपी-पेस्ट Lua कोड के साथ FiveM रेकेस्ट टारगेटिंग के लिए। इसमें addSpherezone और qb-target भी शामिल हैं। QBCore, ESX और Standalone।
Agency Scripts
Agency Scripts के संस्थापक और प्रमुख डेवलपर
FiveM में Raycasting क्या है?
रेकैस्टिंग वह तकनीक है जिसमें 3D स्पेस में एक बिंदु से दूसरे बिंदु तक एक अदृश्य रेखा (रे) भेजी जाती है और रास्ते में क्या टकराता है इसकी जांच की जाती है। FiveM में, रेकास्टिंग का उपयोग लक्ष्य प्रणाली, वस्तु इंटरैक्शन, लाइन-ऑफ-साइट जांच, सतह पहचान, और कस्टम लक्ष्य मैकेनिक्स के लिए किया जाता है। गेम इंजन कई रेकास्ट नेटिव प्रदान करता है जो आपको सटीकता से एंटिटीज़, सतहों, और विश्व ज्यामिति का पता लगाने देते हैं। रेकास्टिंग को समझना उन्नत गेमप्ले मैकेनिक्स जैसे कस्टम लक्ष्य निर्धारण, स्मार्ट प्लेसमेंट सिस्टम, लेजर पॉइंटर्स, और संदर्भ-संवेदनशील इंटरैक्शन को अनलॉक करता है जो खिलाड़ी के देखने पर प्रतिक्रिया करते हैं।
स्टार्टशेपटेस्टरे के साथ बेसिक रे-कास्टिंग
रेकैस्टिंग का सबसे सरल रूप उपयोग करता है StartShapeTestRay जो दो निर्देशांकों के बीच एक रे कास्ट करता है और पहले टकराए गए वस्तु की जानकारी लौटाता है। परिणाम में हिट स्थिति, प्रभाव बिंदु के सटीक निर्देशांक, सतह सामान्य वेक्टर, और यदि कोई इकाई टकराई हो तो इकाई हैंडल शामिल होता है। आपको कॉल करना होगा GetShapeTestResult अगले फ्रेम पर परिणाम प्राप्त करने के लिए।
-- client/raycast_basic.lua
local function Raycast(origin, direction, maxDistance, flags, ignoreEntity)
local destination = origin + direction * maxDistance
local shapeTest = StartShapeTestRay(
origin.x, origin.y, origin.z,
destination.x, destination.y, destination.z,
flags or -1, -- flags: -1 = everything
ignoreEntity or 0, -- entity to ignore
0
)
local _, hit, endCoords, surfaceNormal, entityHit = GetShapeTestResult(shapeTest)
return {
hit = hit == 1,
coords = endCoords,
normal = surfaceNormal,
entity = entityHit,
}
end
-- Raycast from camera to world (what the player is looking at)
local function GetPlayerAimTarget(maxDist)
local camCoords = GetGameplayCamCoord()
local camRot = GetGameplayCamRot(2)
-- Convert rotation to direction vector
local radX = math.rad(camRot.x)
local radZ = math.rad(camRot.z)
local direction = vector3(
-math.sin(radZ) * math.abs(math.cos(radX)),
math.cos(radZ) * math.abs(math.cos(radX)),
math.sin(radX)
)
local playerPed = PlayerPedId()
return Raycast(camCoords, direction, maxDist or 50.0, -1, playerPed)
end
रेकैस्ट फ्लैग्स और फ़िल्टरिंग
flags पैरामीटर में StartShapeTestRay रे की किस प्रकार की वस्तुओं को हिट कर सकता है, इसे नियंत्रित करता है। सही फ्लैग्स का उपयोग प्रदर्शन और सटीकता के लिए महत्वपूर्ण है। सब कुछ के खिलाफ जांच करना (-1) महंगा है और अक्सर अवांछित परिणाम लौटाता है जैसे अदृश्य टक्कर सीमाएं। केवल आवश्यक चीज़ों को लक्षित करने के लिए विशिष्ट फ्लैग का उपयोग करें।
-- client/raycast_flags.lua
-- Common flag values for StartShapeTestRay
local RayFlags = {
WORLD = 1, -- Static world geometry (buildings, terrain)
VEHICLES = 2, -- Vehicles
PEDS = 4, -- Pedestrians and players (on foot)
OBJECTS = 16, -- Props and objects
WATER = 32, -- Water surfaces
VEGETATION = 256, -- Trees and bushes
-- Common combinations
WORLD_AND_VEHICLES = 3,
WORLD_AND_OBJECTS = 17,
ENTITIES_ONLY = 22, -- Vehicles + Peds + Objects
ALL = -1, -- Everything
}
-- Example: Only detect vehicles (for a speed camera script)
local function DetectVehicleAhead(origin, direction)
return Raycast(origin, direction, 100.0, RayFlags.VEHICLES, PlayerPedId())
end
-- Example: Detect ground position (for object placement)
local function GetGroundPosition(x, y, z)
local result = Raycast(
vector3(x, y, z + 50.0),
vector3(0.0, 0.0, -1.0),
100.0,
RayFlags.WORLD
)
if result.hit then
return result.coords
end
return nil
end
एक टारगेटिंग सिस्टम बनाना
एक लक्ष्य प्रणाली रे-कास्टिंग को एंटिटी फ़िल्टरिंग के साथ जोड़ती है ताकि खिलाड़ी खेल की दुनिया में विशिष्ट एंटिटीज़ का चयन और इंटरैक्ट कर सकें। यह ox_target और qb-target जैसे इंटरैक्शन सिस्टम के लिए आधार है। सिस्टम प्रत्येक फ्रेम में कैमरा से एक रे कास्ट करता है, जांचता है कि हिट एंटिटी किसी पंजीकृत लक्ष्य से मेल खाती है या नहीं, और इंटरैक्शन प्रॉम्प्ट दिखाता है।
-- client/targeting.lua
local TargetSystem = {
targets = {},
currentTarget = nil,
enabled = true,
}
function TargetSystem.AddTarget(entity, options)
TargetSystem.targets[entity] = {
label = options.label or 'Interact',
icon = options.icon or 'fas fa-hand',
distance = options.distance or 3.0,
canInteract = options.canInteract,
onSelect = options.onSelect,
}
end
function TargetSystem.RemoveTarget(entity)
TargetSystem.targets[entity] = nil
end
-- Main targeting loop
CreateThread(function()
while true do
if TargetSystem.enabled then
local aimResult = GetPlayerAimTarget(10.0)
if aimResult.hit and aimResult.entity ~= 0 then
local entity = aimResult.entity
local target = TargetSystem.targets[entity]
if target then
local playerCoords = GetEntityCoords(PlayerPedId())
local entityCoords = GetEntityCoords(entity)
local dist = #(playerCoords - entityCoords)
if dist <= target.distance then
local canInteract = true
if target.canInteract then
canInteract = target.canInteract(entity)
end
if canInteract then
TargetSystem.currentTarget = entity
-- Draw interaction prompt
DrawText3D(entityCoords.x, entityCoords.y, entityCoords.z + 1.0,
target.label)
-- Handle interaction key press
if IsControlJustPressed(0, 38) then -- E key
target.onSelect(entity)
end
end
end
end
else
TargetSystem.currentTarget = nil
end
end
Wait(0)
end
end)
-- Helper: Draw 3D text at world coordinates
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(true)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
ClearDrawOrigin()
end
सतह पहचान और वस्तु प्लेसमेंट
रेकैस्टिंग वस्तु प्लेसमेंट सिस्टम के लिए आवश्यक है जहां खिलाड़ी किसी सतह की ओर इशारा करता है और एक वस्तु पूर्वावलोकन उनके लक्ष्य का अनुसरण करता है। रेकास्ट द्वारा लौटाया गया सतह सामान्य आपको सतह की अभिविन्यास बताता है, जिससे आप ढलानों, दीवारों, और छतों पर रखी वस्तुओं को सही ढंग से संरेखित कर सकते हैं।
-- client/placement.lua
local Placement = {
active = false,
previewEntity = nil,
modelName = nil,
}
function Placement.Start(modelName)
Placement.modelName = modelName
Placement.active = true
-- Create preview prop
local model = joaat(modelName)
RequestModel(model)
while not HasModelLoaded(model) do Wait(10) end
Placement.previewEntity = CreateObject(model, 0.0, 0.0, 0.0, false, true, false)
SetEntityAlpha(Placement.previewEntity, 150, false)
SetEntityCollision(Placement.previewEntity, false, false)
FreezeEntityPosition(Placement.previewEntity, true)
SetModelAsNoLongerNeeded(model)
CreateThread(function()
while Placement.active do
local result = GetPlayerAimTarget(15.0)
if result.hit then
local coords = result.coords
SetEntityCoords(Placement.previewEntity,
coords.x, coords.y, coords.z, false, false, false, false)
-- Align to surface normal
local normal = result.normal
local pitch = math.deg(math.asin(normal.z)) - 90.0
SetEntityRotation(Placement.previewEntity, pitch, 0.0,
GetEntityHeading(PlayerPedId()), 2, true)
-- Color: green if valid, red if not
local valid = IsPlacementValid(coords)
if valid then
SetEntityDrawOutline(Placement.previewEntity, true)
end
-- Confirm placement
if IsControlJustPressed(0, 38) and valid then
Placement.Confirm(coords)
end
end
-- Cancel placement
if IsControlJustPressed(0, 73) then -- X key
Placement.Cancel()
end
Wait(0)
end
end)
end
function Placement.Confirm(coords)
Placement.active = false
if Placement.previewEntity then
DeleteEntity(Placement.previewEntity)
Placement.previewEntity = nil
end
TriggerServerEvent('myresource:placeObject', Placement.modelName, coords)
end
function Placement.Cancel()
Placement.active = false
if Placement.previewEntity then
DeleteEntity(Placement.previewEntity)
Placement.previewEntity = nil
end
end
function IsPlacementValid(coords)
local playerCoords = GetEntityCoords(PlayerPedId())
local dist = #(playerCoords - coords)
return dist >= 1.0 and dist <= 10.0
end
लाइन ऑफ साइट जांच
रेकैस्टिंग यह मानक तरीका है जिससे जांचा जाता है कि क्या दो बिंदु बिना बाधा के एक-दूसरे को देख सकते हैं। यह स्टील्थ सिस्टम, AI जागरूकता, स्नाइपर मैकेनिक्स, और किसी भी गेमप्ले में उपयोग होता है जो दृश्यता पर निर्भर करता है। एक बिंदु से दूसरे बिंदु तक एक किरण फेंकें और जांचें कि क्या यह लक्ष्य तक पहुंचने से पहले कुछ से टकराता है।
-- shared/los.lua (can run on both client and server)
local function HasLineOfSight(from, to, ignoreEntity)
local direction = to - from
local distance = #direction
direction = direction / distance -- normalize
local result = Raycast(from, direction, distance, RayFlags.WORLD, ignoreEntity)
if not result.hit then
return true -- nothing blocking the path
end
-- Check if the hit point is past the target
local hitDist = #(from - result.coords)
return hitDist >= distance * 0.95
end
-- Usage: Check if NPC can see the player
local function CanNPCSeePlayer(npcPed, playerPed)
local npcCoords = GetEntityCoords(npcPed) + vector3(0, 0, 0.7)
local playerCoords = GetEntityCoords(playerPed) + vector3(0, 0, 0.7)
return HasLineOfSight(npcCoords, playerCoords, npcPed)
end
रेकैस्ट के लिए प्रदर्शन अनुकूलन
- रेकास्ट आवृत्ति को सीमित करें। जब तक बिल्कुल आवश्यक न हो, हर फ्रेम में रे कास्ट न करें। इंटरैक्शन जांच के लिए, हर 100ms आमतौर पर पर्याप्त होता है। केवल सक्रिय निशानेबाजी और प्लेसमेंट सिस्टम के लिए प्रति-फ्रेम रे कास्टिंग का उपयोग करें।
- विशिष्ट फ्लैग्स का उपयोग करें। के खिलाफ कास्टिंग
-1(सब कुछ) विशिष्ट एंटिटी प्रकारों को लक्षित करने की तुलना में काफी धीमा होता है। केवल आवश्यक चीज़ों को फ़िल्टर करें। - परिणाम कैश करें। यदि खिलाड़ी ने स्थानांतरित नहीं किया है या किसी अन्य दिशा में नहीं देखा है, तो रे-कास्ट परिणाम समान होगा। कैमरा स्थिति और घुमाव की तुलना करके अनावश्यक कास्ट को छोड़ दें।
- पहले दूरी जांच का उपयोग करें। इकाई इंटरैक्शन जांचने के लिए रे-कास्टिंग करने से पहले, पुष्टि करें कि खिलाड़ी एक उचित दूरी के भीतर है। दूरी जांचें रे-कास्टिंग की तुलना में कई गुना सस्ती होती हैं।
- LOS के लिए StartShapeTestLosProbe को प्राथमिकता दें। दो ज्ञात बिंदुओं के बीच सरल लाइन-ऑफ-साइट जांच के लिए,
StartShapeTestLosProbeसे हल्का हैStartShapeTestRayक्योंकि यह केवल हिट/नो-हिट बूलियन लौटाता है। - पूरे नक्शे में रे-कास्टिंग से बचें। अधिकतम दूरी को उचित रखें। 50-यूनिट रेकास्ट 1000-यूनिट रेकास्ट की तुलना में बहुत सस्ता होता है।