You can write your topic however you want, but you need to answer these questions:
-
What do you want to achieve? Keep it simple and clear!
I want the Monster to turn quicker and increase responsiveness to player changing their position(moving) and also have solutions when it gets stuck -
What is the issue? Include screenshots / videos if possible!
YOUTUBE LINK: https://youtu.be/9DbD8D213uw -
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried reducing the task.wait() in while loops but it didnt help and its already pretty low
I think maybe neatening my code may help identify the problem better but I have no idea on how I should do that while preserving the functionality.
This Model is custom made using blender, it still have all the components as a regular rig but that shouldn’t be the root cause of any problems found here.
Whole script:(Server)
--[[TODO
1.) Grimace can wander around the building with pathfinding like random spots that arent occupied by buildings
2.) He can be alerted by lound sounds like kicking doors
3.) When player gets in line of sight he starts chasing
4.) Whoever he is chasing a sound should be played to them only with a frame so show how close he is
5.) He should have attribute that talks about his state(Wandering, Chasing, Killing)
]]--
local GrimaceModel = script.Parent
local Humanoid = GrimaceModel:WaitForChild("Humanoid")
local G_HumanoidRootPart = GrimaceModel:WaitForChild("HumanoidRootPart")
local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath({
AgentRadius = 6,
AgentHeight = 6,
AgentCanJump = false
})
local PatrolPoints = game.Workspace.HorrorMap.PatrolPoints
local RandoPatrolOrder = {}
local LineOfSightRequired = 0.6 --The perferction of line of sight minimum(1 = Perfect, -1 Perfect Oppose, 0 Perpendicular)
local ChaseCooldown = 1 --To make grimace chill before he chase again after chase time
local isChasing = false --Debounce to ensure functionality
local Range = 175 --There is fog so we gonna make range to make it even more realistic
--//Utility Functions\\--
local function FindVictims()
local victims = {}
for _, player in pairs(game.Players:GetChildren()) do
if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
local HumanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
local distance = (G_HumanoidRootPart.Position - HumanoidRootPart.Position).magnitude
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {GrimaceModel, workspace.HorrorMap.Raycasting}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local origin = G_HumanoidRootPart.Position
local direction = (HumanoidRootPart.Position - G_HumanoidRootPart.Position).unit
local rayLength = distance
local raycastResult = workspace:Raycast(origin, direction * rayLength, raycastParams)
if raycastResult then
local part = Instance.new("Part", workspace.HorrorMap.Raycasting)
part.Size = Vector3.new(0.1, 0.1, rayLength)
part.CFrame = CFrame.new(origin, origin + direction * rayLength) * CFrame.new(0, 0, -rayLength / 2)
part.Anchored = true
part.CanCollide = false
part.BrickColor = BrickColor.new("Bright red")
part.Transparency = 0.5
game.Debris:AddItem(part, 0.5) -- Remove part after 0.5 seconds
if player.Character:FindFirstChild(raycastResult.Instance.Name) then
-- If the ray does not hit anything, the line of sight is clear
if distance <= Range then
local G_LV = G_HumanoidRootPart.CFrame.LookVector
local directionToTarget = (HumanoidRootPart.Position - G_HumanoidRootPart.Position).unit
local dotProduct = G_LV:Dot(directionToTarget)
if dotProduct >= LineOfSightRequired then
table.insert(victims, player.Name) -- Add the character to the victims table
end
end
end
end
end
end
return victims -- Return the table of valid characters
end
local function AttemptSetTarget()
local victims = FindVictims()
if #victims > 0 then
if isChasing == false then
isChasing = true
local targetPlayerName = victims[math.random(1, #victims)]
Humanoid:SetAttribute("TargettingPlayer", targetPlayerName)
return true
end
else
return false
end
end
--//Patrolling Coroutine\\--
coroutine.wrap(function()
while Humanoid:GetAttribute("Patrolling") == true do
if Humanoid:GetAttribute("Status") ~= "Wandering" then
Humanoid:SetAttribute("Status", "Wandering")
end
--Initializing Order if needed
if #RandoPatrolOrder == 0 then
for _, v in pairs(PatrolPoints:GetChildren()) do
table.insert(RandoPatrolOrder, v)
v.Color = Color3.fromRGB(162, 162, 162)
end
end
local randomPoint : Part = RandoPatrolOrder[math.random(1, #RandoPatrolOrder)]
randomPoint.Color = Color3.fromRGB(0, 255, 0)
local succ, err = pcall(function()
path:ComputeAsync(G_HumanoidRootPart.Position, randomPoint.Position)
end)
if succ then
local waypoints = path:GetWaypoints()
for i, waypoint in pairs(waypoints) do
if isChasing == false then --Stops in the middle of computed path is chasing is true
Humanoid:MoveTo(waypoint.Position)
Humanoid.MoveToFinished:Wait()
end
end
table.remove(RandoPatrolOrder, table.find(RandoPatrolOrder, randomPoint))
task.wait(0)
else
warn(err)
end
randomPoint.Color = Color3.fromRGB(255, 0, 0)
end
end)()
--//Targetting Coroutine\\--
local targetting = false
Humanoid:GetAttributeChangedSignal("TargettingPlayer"):Connect(function()
if Humanoid:GetAttribute("TargettingPlayer") ~= "" then
targetting = true
while targetting do
if Humanoid:GetAttribute("Status") ~= "Chasing" then
Humanoid:SetAttribute("Status", "Chasing")
end
local targetsName = Humanoid:GetAttribute("TargettingPlayer")
local targetsPlayer = game.Players:FindFirstChild(targetsName)
local targetsChar = targetsPlayer.Character or targetsPlayer.CharacterAdded:Wait()
local targetsHRP = targetsChar:WaitForChild("HumanoidRootPart")
local succ, err = pcall(function()
path:ComputeAsync(G_HumanoidRootPart.Position, targetsHRP.Position)
end)
if succ then
local waypoints = path:GetWaypoints()
for i, waypoint in ipairs(waypoints) do
if isChasing == true then
Humanoid:MoveTo(waypoint.Position)
Humanoid.MoveToFinished:Wait()
end
end
else
warn(err)
end
task.wait(0)
end
else
targetting = false --Targetting Player field is empty theirfor no one to target
end
end)
--//Main Couroutine\\--
coroutine.wrap(function()
while true do
if AttemptSetTarget() and isChasing == true then
Humanoid:SetAttribute("Patrolling", false)
end
task.wait(0.1)
end
end)()
If you can give me tips of suggestions that may help me in the future It is highly appreciated.