Here’s an example I’ve done on a separated experience so I removed the Humanoid in this project and I found a way to make the NPCs run quite smoothly which doesn’t affect much the FPS feel free to let me know how you would adapt this to my project
local PhysicsService = game:GetService("PhysicsService")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
-- Collision
local COLLISION_GROUP_NAME = "NPC"
if not pcall(function() PhysicsService:RegisterCollisionGroup(COLLISION_GROUP_NAME) end) then end
PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_NAME, COLLISION_GROUP_NAME, false)
-- Dossier pour NPCs
local npcsFolder = Instance.new("Folder", Workspace)
npcsFolder.Name = "NPCs"
-- Constantes
local npcCount = 2000
local SPAWN_RADIUS = 500
local SPEED = 20 -- unités par seconde
local npcs = {}
-- Création d'un NPC minimaliste
local function createNPC(id)
local part = Instance.new("Part")
part.Name = "NPC_" .. id
part.Size = Vector3.new(2, 2, 2)
part.Position = Vector3.new(math.random(-SPAWN_RADIUS, SPAWN_RADIUS), 5, math.random(-SPAWN_RADIUS, SPAWN_RADIUS))
part.Anchored = false
part.CanCollide = true
part.TopSurface = Enum.SurfaceType.Smooth
part.BottomSurface = Enum.SurfaceType.Smooth
part.Parent = npcsFolder
part.CollisionGroup = COLLISION_GROUP_NAME
local attachment = Instance.new("Attachment", part)
local linearVelocity = Instance.new("LinearVelocity")
linearVelocity.Attachment0 = attachment
linearVelocity.MaxForce = math.huge
linearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
linearVelocity.VectorVelocity = Vector3.zero
linearVelocity.Parent = part
local data = {
part = part,
linearVelocity = linearVelocity,
target = nil,
}
table.insert(npcs, data)
return data
end
-- Mouvement aléatoire
local function pickNewTarget(data)
local x = math.random(-SPAWN_RADIUS, SPAWN_RADIUS)
local z = math.random(-SPAWN_RADIUS, SPAWN_RADIUS)
local y = data.part.Position.Y
data.target = Vector3.new(x, y, z)
end
local function updateMovement(data)
if not data.target then
pickNewTarget(data)
end
local direction = (data.target - data.part.Position)
local distance = direction.Magnitude
if distance < 5 then
pickNewTarget(data)
data.linearVelocity.VectorVelocity = Vector3.zero
else
local unit = direction.Unit
data.linearVelocity.VectorVelocity = unit * SPEED
end
end
-- Création des NPCs
for i = 1, npcCount do
createNPC(i)
end
-- Boucle de mise à jour
RunService.Heartbeat:Connect(function()
for _, npc in ipairs(npcs) do
updateMovement(npc)
end
end)
print("✅ 1000 NPCs avec LinearVelocity (sans Humanoid) en déplacement fluide.")
Just took out the deprecated commands and replaced them as needed, nothing wild.
1st few runs your fps said 39-ish… after the switch runs were 59-ish… who knows.