Hi,
I’m trying to make a monster/enemy in Roblox. The basis of how it works is this:
- randomly pathfinds between points on map (already coded; no issues)
- if it sees a player. note conditions include:
- the player must be in a degree range infront of it (for now it’s 135)
- the player must be close enough (for now it’s 64 studs)
- the player must not be hiding (a BoolValue in the character)
- it walks towards the last position it sees the player
- if it goes to the last position and it doesn’t see anyone, it stops chasing and goes back to pathfinding
For some reason, I’m experiencing weird things, like being infront of the NPC and it saying there’s a wall between us, or i’m 152 degrees to the side when im directly infront. Here is an abridged version of my code, cutting out all of the normal pathfinding:
-- init variables
local sightRange = 64
local sightAngle = 135
local targetPlayer = nil
local targetPosition = nil
local chasing = false
-- plus more for pathfinding
local function getVisiblePlayers()
local sightPlayer = nil
local sightPlayerDist = math.huge
local lookVector = script.Parent.HumanoidRootPart.CFrame.LookVector --gets this look direction
for _, plr in pairs(game.Players:GetPlayers()) do
local char = plr.Character
if char == nil then --make sure the player exists
continue
end
-- get the direction of how far the player is around
local charVector = CFrame.lookAt(script.Parent.PrimaryPart.Position, char.PrimaryPart.Position).LookVector
-- find the dot angle
local dot = lookVector:Dot(charVector)
local dotAngle = math.deg(math.acos(dot))
print(dotAngle)
if dotAngle < sightAngle then --if the player's visible, it's time to strike
local filter = {script.Parent}
-- set raycast params
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.CollisionGroup = "Entity"
for i, v in pairs(workspace.map:GetDescendants()) do --makes it able to look through invisible parts.
-- i have lots of invisible parts (i.e. boundaries) for things like map gen, this is to stop it from getting caught on them
if v:IsA("BasePart") and v.Transparency == 1 then
table.insert(filter, v)
end
end
raycastParams.FilterDescendantsInstances = filter
-- find direction
local origin = script.Parent.HumanoidRootPart.Position
local target = char.PrimaryPart.Position
local direction = (target - origin).Unit * sightRange
local ray = workspace:Raycast(origin, direction, raycastParams)
if ray then print(ray.Instance) end
-- if the player's close enough, get ready to chase it!
if ray and ray.Instance:IsDescendantOf(char) then
if sightPlayer == nil then
sightPlayer = plr
sightPlayerDist = (script.Parent.HumanoidRootPart.Position - char.PrimaryPart.Position).Magnitude
elseif (script.Parent.HumanoidRootPart.Position - char.PrimaryPart.Position).Magnitude < sightPlayerDist then
sightPlayer = plr
sightPlayerDist = (script.Parent.HumanoidRootPart.Position - char.PrimaryPart.Position).Magnitude
end
end
end
return sightPlayer
end
end
local function chase()
local visible = getVisiblePlayers()
print(visible)
if visible then
targetPlayer = visible
targetPosition = targetPlayer.Character.PrimaryPart.Position
chasing = true
end
if targetPosition then
local char = targetPlayer.Character
script.Parent.Humanoid:MoveTo(targetPosition)
if (targetPosition - script.Parent.HumanoidRootPart.Position).Magnitude < 6 then
targetPlayer = nil
targetPosition = nil
chasing = false
end
end
task.wait(0.5)
chase()
end
-- pathfinding code
coroutine.wrap(chase)()
-- more pathfinding code
The thing is that whenever I isolate the code, in a baseplate with 1 or 2 walls it works with no issues. However when I bring it into my game, it becomes really bugged. If anyone can help me fix issues and make this work, it would be much appreciated.
Thanks!