You would definitely want to use Collision Filtering and Collision Groups for this.
Then assign the player’s character’s parts to a “Player” collision group when a character is added to the workspace using the Player.CharacterAdded event signal.
Example:
Assuming you’ve premade a collision group using the Collision Filtering article I linked above ^
-- Regular "Script" inside "ServerScriptService"
local PhysicsService = game:GetService("PhysicsService")
game.Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
for index, inst in pairs(Character:GetDescendants()) do -- we loop through every instance parented to the "Character" model
if inst:IsA("BasePart") then -- we check if the instance is a "BasePart" (you can only set the collision group for BaseParts)
PhysicsService:SetPartCollisionGroup(inst, "Player") -- we set the BasePart's collision group using PhysicsService
end
end
end)
end)