I’m creating a simple enemy AI that uses Humanoid:MoveTo() and RayCasting to determine if the enemy is close enough to attack. The issue I’m encountering is that the enemy’s RayOrigin will sometimes “clip through”, and originate from a few studs behind the HumanoidRootPart of the enemy (when it should just be the HumanoidRootPart). I’ve tried seeing if the RayOrigin actually changes, but it is still the same despite this. I’ve provided a video to show the issue, and the code that handles chasing the Player
function chasePlayer()
if character ~= nil then
local stop = false
local humanoid = character:FindFirstChild("Humanoid")
local torso = character:FindFirstChild("Torso")
local root = character:FindFirstChild("HumanoidRootPart")
if humanoid ~= nil and torso ~= nil and humanoid.Health > 0 then
if light1Anim.IsPlaying then
light1Anim:Stop()
end
local p = Instance.new("Part", workspace)
p.Anchored = true
p.CanCollide = false
p.Name = "RayVisual"
p.Material = Enum.Material.Neon
p.BrickColor = BrickColor.new("Really blue")
while not isAttacking and not hurt and not death do
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Include
local Workspace = game:GetService("Workspace")
local distance = (character.Torso.Position - enemyRoot.Position).Magnitude
local rayOrigin = enemyRoot.CFrame.Position
local rayDirection = enemyRoot.CFrame.LookVector.Unit * 4
local rayResult = Workspace:Raycast(rayOrigin, rayDirection, raycastParams)
p.Size = Vector3.new(0.1, 0.1, distance)
p.CFrame = CFrame.lookAt(rayOrigin, character.Torso.Position)*CFrame.new(0, 0, -distance/2)
if distance < 80 then
if not stop and rayResult == nil then
print("still casting")
enemyHumanoid:MoveTo(root.CFrame.Position)
else
print("cast finished")
enemyHumanoid:MoveTo(enemyRoot.CFrame.Position)
isAttacking = true
attackPlayer()
endAttackEvent.Event:Wait(.5)
--print(isAttacking)
end
end
wait()
end
end
else
--print("Character not found")
end
end
No the same behavior replicates even without the visual. When I boot up the game, the correct behavior is there until… well, it isn’t. I provided a video of the correct behavior.
In terms of why I chose not to use Magnitude, the Magnitude method is less responsive when the Player moves towards the enemy (the Player will collide with the enemy before the enemy realizes the distance closes in), where as RayCast is immediate.
why would magnitude would be less responsive? They both would be immediate, no?
If the player is within 80 studs of the enemy, the enemy would move towards the target until it is within 4 studs of the character, and then attack the player. This would be much simpler than raycasting.
That’s what I thought too. When I tried it, it was not as responsive as the RayCast method. I can show you what I wrote for it.
function chasePlayer()
if character ~= nil then
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Include
local stop = false
local humanoid = character:FindFirstChild("Humanoid")
local torso = character:FindFirstChild("Torso")
local root = character:FindFirstChild("HumanoidRootPart")
if humanoid ~= nil and torso ~= nil and humanoid.Health > 0 then
if light1Anim.IsPlaying then
light1Anim:Stop()
end
--local p = Instance.new("Part", workspace)
--p.Anchored = true
--p.CanCollide = false
--p.Name = "Za Ray Ray"
--p.Material = Enum.Material.Neon
--p.BrickColor = BrickColor.new("Really blue")
while not isAttacking and not hurt and not death do
local distance = (character.Torso.Position - enemyRoot.Position).Magnitude
--local rayOrigin = enemyRoot.CFrame.Position
--local rayDirection = enemyRoot.CFrame.LookVector.Unit * 4
--local rayResult = Workspace:Raycast(rayOrigin, rayDirection, raycastParams)
--p.Size = Vector3.new(0.1, 0.1, distance)
--p.CFrame = CFrame.lookAt(rayOrigin, character.Torso.Position)*CFrame.new(0, 0, -distance/2)
if distance < 80 then
if not stop and distance >= 4 then
print("still casting")
enemyHumanoid:MoveTo(root.CFrame.Position)
else
print("cast finished")
enemyHumanoid:MoveTo(enemyRoot.CFrame.Position)
isAttacking = true
attackPlayer()
endAttackEvent.Event:Wait(.5)
--print(isAttacking)
end
end
wait()
end
end
else
--print("Character not found")
end
end
If it helps, this issue only starts happening after a certain mechanic where the player “rests” at a checkpoint, which resets all NPCs by teleporting them to their spawn point via changing the HumanoidRootPart CFrame