Make NPC not collide with players?

I want to make it so that the NPC is not able to collide with players. I checked out the articles at https://developer.roblox.com/. I couldn’t find a tutorial for NPCs and Players. I only found how to stop collisions of players to other players using PhysicsService.

I tried to try to make some changes and make it work with NPCs and Players but it doesn’t works. I can still touch the NPC and push it.

Here is the code I managed to come up with.

local phys = game:GetService("PhysicsService")
local npcName = game.Workspace.CONFIGURATIONS.NPCName.Value

local npcGroup = "NPC"
local plrg = "Player"

phys:CreateCollisionGroup(npcGroup)
phys:CreateCollisionGroup(plrg)

phys:CollisionGroupSetCollidable(plrg, npcGroup, false)

local function setCollisionGroupsRecursive(object,isnpc)
	if not isnpc then
		if object:IsA("Part") then
			phys:SetPartCollisionGroup(object,plrg)
		end
		for _,child in ipairs(object:GetChildren()) do
			setCollisionGroupsRecursive(child,false)
		end
	elseif isnpc then
		if object:IsA("Part") then
			phys:SetPartCollisionGroup(object,npcGroup)
		end
		for _,child in ipairs(object:GetChildren()) do
			setCollisionGroupsRecursive(child,true)
		end
	end
end

setCollisionGroupsRecursive(game.Workspace[npcName], true)

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		setCollisionGroupsRecursive(char,false)
	end)
end)

Please tell me what I am doing wrong and how I can fix this. Also there are no errors in the Output regarding this.

What is your object hierarchy of your npcs and characters?

What is the behavior that you expect, and what is the current behavior?

The behavior I expect is that players walk through the NPC so it is not disturbed by player’s movements. The behavior right now is that it is not working. Player can collide with the NPC and can push and touch it.

Try this:

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAppearanceLoaded:Connect(function(char)
		setCollisionGroupsRecursive(char,false)
	end)
end)

This should wait for the players parts to load.

There are a few problems and optimizations with your code:

  • You have to define setCollisionGroupsRecursive before you can use it in its own function. It will error otherwise, I think. Correct me if I’m wrong.
  • You can set the collision group of a part’s descendants using Part:GetDescendants() instead of a recursive Part:GetChildren(), so you would not even have to use the previous optimization.
  • You might want to use :IsA("BasePart") instead of :IsA("Part"), since this may be causing some parts that are still collidable but not of class Part to not have their collision groups properly set.
local function setCollisionGroups(object,isnpc)
    local collGroup = isnpc and npcGroup or plrg
    for _,part in ipairs(object:GetDescendants()) do
        if part:IsA("BasePart") then
            phys:SetPartCollisionGroup(part,collGroup)
        end
    end
end

There is a visual editor for collision groups provided by Studio. The devforum thread that announced it is here. I believe it is in Model > Advanced > Collision Groups, the page on the dev wiki for navigating the Model tab is here. You will be able to modify which collision groups will collide more easily there.

When you see the visual editor

Collision groups for parts are managed solely by their CollisionGroupId property, 0 is for the first collision group, regardless of name, 1 is for the next group down, and so on. This can be used to set collision groups from the part’s properties instead of through PhysicsService.

I hope that helps, I feel like I’m just spitting out information though…

3 Likes

You can call a function within itself. This is called using a recursive function. It’s kind of like a loop. GetDesendants would also work, but it would not be that much faster, as GetDesendants uses a recursive function.

@StrategicPlayZ definitely use IsA BasePart instead of Part, as this will cover mesh parts. Good point @goldenstein64

2 Likes

Yes but this is a pointless reinventing of the wheel for a negligible performance gain, if any at all. GetDescendants is fine as far as calling the function on a single ancestor goes without handling recursion yourself.