Alrigth so I have a problem with monsters so basically the monsters rushes on the player but after a certain point the player can decide to outsmart the wave by trying to force them to stay in circle and it’s very annoying.
Here’s the code of the monster
local RunService = game:GetService("RunService")
local chasingPart = script.Parent:WaitForChild("HumanoidRootPart")
local moveSpeed = 10
local player = nil
local spawnRadius = 50
local enemyFolder = workspace:FindFirstChild("Enemies") or workspace
local damageAmount = 10
local damageCooldown = 0.5
local lastHitTime = 0
local separationDistance = 10
local currentVelocity = Vector3.zero
local uniqueOffset = (tonumber(string.sub(tostring(script.Parent.Name), -3)) or math.random()) * 0.2
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.MaxTorque = Vector3.new(100000, 100000, 100000)
bodyGyro.D = 1000
bodyGyro.P = 10000
bodyGyro.CFrame = chasingPart.CFrame
bodyGyro.Parent = chasingPart
function getPlayer()
for _, p in pairs(game.Players:GetPlayers()) do
if p.Character and p.Character:FindFirstChild("HumanoidRootPart") then
return p.Character
end
end
return nil
end
function randomSpawnPosition(playerPosition)
local angle = math.random() * math.pi * 2
local offset = Vector3.new(math.cos(angle), 0, math.sin(angle)) * spawnRadius
local spawnPos = playerPosition + offset
local rayOrigin = spawnPos + Vector3.new(0, 10, 0)
local rayDirection = Vector3.new(0, -20, 0)
local result = workspace:Raycast(rayOrigin, rayDirection, RaycastParams.new())
if result then
spawnPos = result.Position + Vector3.new(0, 2, 0)
end
return spawnPos
end
function moveToPlayer()
if not player then return end
local basePosition = player.HumanoidRootPart.Position
local angle = tick() * 0.2 + uniqueOffset
local radius = 2
local offset = Vector3.new(math.cos(angle), 0, math.sin(angle)) * radius
local targetPosition = basePosition + offset
local desiredDirection = (targetPosition - chasingPart.Position).Unit
local separation = Vector3.zero
for _, otherEnemy in pairs(enemyFolder:GetChildren()) do
if otherEnemy ~= script.Parent and otherEnemy:FindFirstChild("HumanoidRootPart") then
local otherPart = otherEnemy.HumanoidRootPart
local distance = (chasingPart.Position - otherPart.Position).Magnitude
if distance < separationDistance and distance > 0 then
local pushDir = (chasingPart.Position - otherPart.Position).Unit
local strength = (separationDistance - distance) / separationDistance
separation += pushDir * strength
end
end
end
local finalDirection = (desiredDirection + separation).Unit
local deltaTime = RunService.Heartbeat:Wait()
local damping = 0.15
currentVelocity = currentVelocity:Lerp(finalDirection * moveSpeed, damping)
chasingPart.Position += currentVelocity * deltaTime
bodyGyro.CFrame = CFrame.new(chasingPart.Position, chasingPart.Position + finalDirection)
end
function onTouch(otherPart)
local char = otherPart:FindFirstAncestorOfClass("Model")
if char and char:FindFirstChild("Humanoid") and char:FindFirstChild("HumanoidRootPart") then
if char == player then
local currentTime = tick()
if currentTime - lastHitTime >= damageCooldown then
lastHitTime = currentTime
char.Humanoid:TakeDamage(damageAmount)
end
end
end
end
-- Spawn initial
function spawnAtRandomPosition()
local char = getPlayer()
if char then
player = char
chasingPart.Position = randomSpawnPosition(char.HumanoidRootPart.Position)
end
end
spawnAtRandomPosition()
-- Boucle de suivi
RunService.Heartbeat:Connect(function()
local char = getPlayer()
if char then
player = char
moveToPlayer()
end
end)
-- Dégâts
chasingPart.Touched:Connect(onTouch)
Here’s what the effect gives in video