and basically, it works, as expected
but the problem is that the enemies will stack up into one place, which makes melee-fighting extremely difficult or impossible
they’ve got this detection part around them, but since it can’t collide nor query, they ignore it
my question is, how can i make them take that part into consideration so they also avoid that?
Instead of using physical parts to prevent enemies from stacking up, use code to prevent enemies from getting too close and stacking up. Otherwise, you’ll run into physics issues like the one you’re having right now.
Okay so basically, CanQuery property lets you decide if you want the BasePart to be considered in spatial queries such as raycasts and region3 finds. (just wanted you to be clear on that since it doesn’t seem like it matters).
Now, if you’re facing problems in using collision groups, heres how they work:
Its simple, you create a collision group, and either use BasePart.CollisionGroup in script or manually set the collision group through properties.
You would have to create 2 groups, for example “NPCs” and “NPCsDontCollide”. And using a script, you’d have to set every single basepart in the npc to the collision group “NPCs”. And in the collision groups manager, in “NPCs can collide with”, you set “NPCsDontCollide” group checkbox to false.
Now, all you have to do is set the collision group of parts you dont want npcs to collide to “NPCsDontCollide”.
Well, they wouldn’t stack up if you made it so they don’t collide with each other using CollisionGroups. But this might also make it look like they all disappear into 1 npc if they have the same walkto position. Is that what you want?
Yes so basically if you want to make them not collide with each other you set this checkbox to false:
and it would make it so every part that is of the CollisionGroup “Enemies” will not collide with each other, fixing the NPCs stacking up issue after you set every basepart inside the npc character models to the collision group “Enemies”.
I thought what you meant by stacking up was going over one another. Now I know what you mean, well, to fix them all stacking up in one place, you’d have to make sure that every single npc has a unique moveto position, or atleast make sure that not all of them have the same moveto position.
Hmmm yeah, I see, let me think of what could be done, just to make sure, are you using pathfindingservice or just using Humanoid:MoveTo(playerHRPPosition) in a loop?
local pfService = game:GetService("PathfindingService")
local pathfinding = {}
function pathfinding.melee(Humanoid, targetPosition)
if not Humanoid then return end
if not targetPosition then return end
local pathParameters = {
AgentRadius = 2,
AgentHeight = 2,
AgentCanJump = true,
AgentCanClimb = false
}
local path = pfService:CreatePath(pathParameters)
local humanoidRootPart = Humanoid.Parent:FindFirstChild("HumanoidRootPart")
local startPosition = humanoidRootPart.Position
local success, errorMessage = pcall(function()
path:ComputeAsync(startPosition, targetPosition)
end)
if not success then
warn("Pathfinding failed: " .. errorMessage)
return
end
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success and #waypoints > 0 then
for i = 2, #waypoints do
local waypoint = waypoints[i]
if waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid.Jump = true
end
Humanoid:MoveTo(waypoint.Position)
local moveFinished = Humanoid.MoveToFinished:Wait()
end
return path
end
end
return pathfinding
server script
local pathfindingModule = require(game:GetService("ServerScriptService"):WaitForChild("Enemies").PathfindingModule)
local runService = game:GetService("RunService")
local enemiesFolder = workspace:WaitForChild("Enemies")
local heartbeatConnection
heartbeatConnection = runService.Heartbeat:Connect(function()
if #enemiesFolder:GetChildren() > 0 then
local enemies = enemiesFolder:GetChildren()
for _, enemy in ipairs(enemies) do
if enemy.EnemyType.Value == "MELEE" then
local detectionBox = enemy:FindFirstChild("DetectionPart")
local humanoid = enemy:FindFirstChildOfClass("Humanoid")
local closestPlayer = nil
local LOS = workspace:GetPartBoundsInBox(detectionBox.CFrame, detectionBox.Size)
for _, v in pairs(LOS) do
if v.Parent:FindFirstChild("Humanoid") then
local targetPlayer = game.Players:GetPlayerFromCharacter(v.Parent)
if targetPlayer then
if closestPlayer == nil or (enemy.HumanoidRootPart.Position - targetPlayer.Character.HumanoidRootPart.Position).Magnitude < (enemy.HumanoidRootPart.Position - closestPlayer.Character.HumanoidRootPart.Position).Magnitude then
closestPlayer = targetPlayer
end
end
end
end
task.spawn(function()
if closestPlayer then
local targetPosition = closestPlayer.Character.Torso.PathfindPart.Position
pathfindingModule.melee(humanoid, targetPosition)
else
humanoid:MoveTo(enemy.HumanoidRootPart.Position)
end
end)
end
end
end
end)