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.
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.
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…
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
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.