Hello !
The problem is described in the title. Now I’ll get to the point and elaborate a little.
I need objects (in my case, NPCs) not to be pushed when moving (collision is turned off), but at the same time not to be compressed into a heap due to the lack of collision between them.
What I tried: I took each object and compared it with others, if the distance between them was small, then I pushed the object out. This method leaves much to be desired for me, in particular because I don’t quite understand how exactly this can be implemented.
I also tried to detect which objects are currently inside using Workspace:GetPartsInPart(), but this, unfortunately, was also unsuccessful.
Minecraft immediately came to my mind, because that’s what seems to be done there.
I wouldn’t mind considering alternative options!
You want to keep the collision for every npcs without them colliding each others? Else i would suggest to use GroupCollision, setting a group for npcs where npcs will go throught each others but still in collision with the Default group (if it helps or maybe this is not really what you are looking for?)
yeah and it will be a blended Npc, i understand. Why not using Raycasting in front of the npc? if the npc encounter another npc then he doesnt walk anymore until there is no more npc. Or else, you could use pathfinding
Are you trying to achieve a “pushing” effect? You mentioned Minecraft, so I can only assume that you mean that when mobs “collide” with each other, instead of looking like they run into brick walls they lightly push each other apart.
The only way I’d see this as a possibility is having a “hitbox” part surrounding the entity and, when colliding with others, applying opposite LinearVelocities/BodyVelocities that push the entities apart.
Just check with workspace:Raycast() and if the result.Instance is a child of the npc model then apply npc.Humanoid:MoveTo(the pushing npc CFrame * CFrame.new(0, 0, -4))
If anyone needs/is interested in how I did it, here it is:
local Workspace = game:GetService("Workspace")
local ipairs = ipairs
local task = task
local Vector3 = Vector3
local CFrame = CFrame
local tick = tick
local print = print
local parts = {...}
local function handleCollisions(part: Part, partsInPart: {BasePart})
for _, somePart in ipairs(partsInPart) do
if somePart.Anchored then
continue
end
local partPosition = part.Position
local somePartPosition = somePart.Position
local lookVector = CFrame.lookAt(
partPosition,
somePartPosition - (Vector3.yAxis * somePartPosition.Y) + Vector3.yAxis * partPosition.Y
).LookVector
local velocityModule = somePart.AssemblyLinearVelocity.Magnitude
if velocityModule > 12 or velocityModule < 12 then
velocityModule = 12
end
local velocity = lookVector * velocityModule
somePart.AssemblyLinearVelocity += (lookVector * velocityModule)
end
end
local function iterate()
for _, part in ipairs(parts) do
local partsInPart = Workspace:GetPartsInPart(part)
if not partsInPart or #partsInPart <= 0 then
continue
end
task.spawn(handleCollisions, part, partsInPart)
end
end
while task.wait() do
iterate()
end
I usually use local variables for global ones. Because I remember reading that this seems to speed up lua. Although I’m not sure if this works in luau. I’ve done a bit of testing and the results are very similar, so I’m not sure if I’m speeding up the code.