In Roblox, you may want players to pass through one another, for example in competitive games. To achieve this, two steps are necessary:
- Creating a collision group that controls what objects can collide
- A runtime script that assigns player characters to the collision group
Collision groups allow you to selectively enable and disable collisions between parts. By putting all player characters into the same collision group and disabling collisions within this group, we can ensure that players never collide with each other, while still colliding with the environment.
Creating the Collision Group
The first step is a setup routine that you run once directly in the Studio command bar. This script registers the collision group using PhysicsService:RegisterCollisionGroup(COLLISION_GROUP) and disables collisions between parts within this collision group using PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP, COLLISION_GROUP, false). Furthermore you can customise the name of the collision group by changing local COLLISION_GROUP = 'player' to any string you desire (Keep in mind that some values are reserved, e.g. “Default”).
--!strict
--[[
author: @quinacon
created: 2025/08/21
updated: 2025/08/31
]]
local COLLISION_GROUP = 'player'
local PhysicsService = game:GetService('PhysicsService')
local function initialise()
if PhysicsService:IsCollisionGroupRegistered(COLLISION_GROUP) then
error(`Collision group {COLLISION_GROUP} already exists. Please choose a different name.`)
end
if PhysicsService:GetMaxCollisionGroups() <= #PhysicsService:GetRegisteredCollisionGroups() then
error(`Cannot create collision group {COLLISION_GROUP}: Maximum Number of collision groups reached.`)
end
local success, errorMessage = pcall(function()
PhysicsService:RegisterCollisionGroup(COLLISION_GROUP)
PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP, COLLISION_GROUP, false)
end)
if not success then
error('Creating collision groups failed: ' .. errorMessage)
end
print(`Successfully created collision group {COLLISION_GROUP}`)
end
initialise()
The Runtime Script
To ensure that the script references the correct collision group, local COLLISION_GROUP = 'player' in this script has to match the value you chose during setup.
The addCharacter(character: Model) function sets the CollisionGroup property for both current parts and future parts to be added to the character.
The addPlayer(player: Player) function ensures that addCharacter() is applied each time a character of the player spawns.
Finally, the script connects addPlayer() to the PlayerAdded event event and iterates over all current players.
--!strict
--[[
author: @quinacon
created: 2025/08/21
updated: 2025/08/31
]]
local COLLISION_GROUP = 'player'
local Players = game:GetService('Players')
local function addCharacter(character: Model)
character.DescendantAdded:Connect(function(basePart)
if not basePart:IsA('BasePart') then
return
end
basePart.CollisionGroup = COLLISION_GROUP
end)
for _, basePart in character:GetDescendants() do
if not basePart:IsA('BasePart') then
continue
end
basePart.CollisionGroup = COLLISION_GROUP
end
end
local function addPlayer(player: Player)
player.CharacterAdded:Connect(addCharacter)
if player.Character then
addCharacter(player.Character)
end
end
Players.PlayerAdded:Connect(addPlayer)
for _, player in Players:GetPlayers() do
task.spawn(addPlayer, player)
end