Collision Filter issues & extreme lag from people joining in at once

I am helping to develop an event which has a large quantity of people moving at the same time. I made a collision filter, which changed the cancollide value if a player was in a group or owned a gamepass. I received the error that the player was a datamodel, or something related to that. I could only replicate it in the server where there was a lot of people joining. I need help asap, my code is down here:

local physics = game:GetService("PhysicsService")
local Players = game:GetService("Players")
local GamePassService = game:GetService('MarketplaceService')

local gamePassForcefield = game.Workspace.GroupDoorModel.GamePassDoor

local gamePassForceFields = "GamePass"

local hasGamePass = "gamePassPlayers"

local GamePassId = 6318668

physics:CreateCollisionGroup(gamePassForceFields)

physics:CreateCollisionGroup(hasGamePass)


physics:SetPartCollisionGroup(gamePassForcefield, gamePassForceFields)


physics:CollisionGroupSetCollidable(gamePassForceFields, hasGamePass, false)


local function setCollisionGroupRecursive(object, groupName)
	if object:IsA("BasePart") then
		physics:SetPartCollisionGroup(object, groupName)
	end
	for _, child in ipairs(object:GetChildren()) do
		setCollisionGroupRecursive(child, groupName)
	end
end

local function onCharacterAdded(character)
	local player = game.Players:GetPlayerFromCharacter(character)
	if GamePassService:UserOwnsGamePassAsync(player.userId, GamePassId) or player:GetRankInGroup(4837748) == 3 or player:GetRankInGroup(4837748) > 5 then
	local collisionGroupName = hasGamePass
	setCollisionGroupRecursive(character, collisionGroupName)
	end

end
local function onPlayerAdded(player)
	player.CharacterAdded:Connect(function(character)
		onCharacterAdded(character)
	end)
end

Players.PlayerAdded:Connect(onPlayerAdded)

I do not care about optimization at this time, just getting it to work.

If I had to make a wild guess based on the vague error description, perhaps ‘player’ is returning nil (which could happen if GetPlayerFromCharacter is invoked when someone is leaving right after joining?). You may want to check if local player = game.Players:GetPlayerFromCharacter(character) returns nil and return if that’s the case. For more in-depth suggestion you’d need to supply the full error message.

N.B. GetDescendants() is essentially the recursive version of GetChildren()

I am pretty sure it exactly said Player:IsInGroup error: Player not in datamodel, I have no idea how to replicate this error again as I said before.

That would confirm the idea that player left during the group checks, I imagine it would help to check for player being nil.

is this related to why some players could not get through the door even after owning the gamepass?

If the script throws an error and stops executing, it would stop assigning the CollisionGroup to new players I imagine.

couldn’t I use pcall to let the function keep running even after it has an error?

Ideally you don’t use pcall to solve errors if the cause isn’t clear, but it should work as well.

A possible cause is that you only iterate through the Character’s children rather than all its descendants, so parts from accessories are left out. (Oops, replied to the wrong reply)

It’s recursively calling the function on the children’s children as well, this shouldn’t be the issue.

Oops, missed that. Thanks! Kinda got thrown off by the slight lack of indentation in the onCharacterAdded function.

I sort of have a problem with my onCharacterAdded function, even after the character is reset, they do not get added to the collisionGroup. Is there a way to possibly assign a collision group right after a player buys the gamepass?

You could probably listen to the ProcessReceipt callback, although this page only lists it for developer products, I’m not entirely sure if it works the same for gamepasses.

For gamepasses you should probably use PromptGamePassPurchaseFinished.

1 Like

Okay, I edited my script and used some pcall functions to make it work no matter what.

local physics = game:GetService("PhysicsService")
local Players = game:GetService("Players")
local GamePassService = game:GetService('MarketplaceService')

local gamePassForcefield = game.Workspace.GroupDoorModel.GamePassDoor

local gamePassForceFields = "GamePass"

local hasGamePass = "gamePassPlayers"

local GamePassId = 6318668

physics:CreateCollisionGroup(gamePassForceFields)

physics:CreateCollisionGroup(hasGamePass)


physics:SetPartCollisionGroup(gamePassForcefield, gamePassForceFields)


physics:CollisionGroupSetCollidable(gamePassForceFields, hasGamePass, false)


local function setCollisionGroupRecursive(object, groupName)
	if object:IsA("BasePart") then
		physics:SetPartCollisionGroup(object, groupName)
	end
	for _, child in ipairs(object:GetDescendants()) do
		setCollisionGroupRecursive(child, groupName)
	end
end

local function onCharacterAdded(character)
	local player = game.Players:GetPlayerFromCharacter(character)
	if player == nil then return end
	if pcall(GamePassService:UserOwnsGamePassAsync(player.userId, GamePassId) or player:GetRankInGroup(4837748) == 3 or player:GetRankInGroup(4837748) > 5) then
	local collisionGroupName = hasGamePass
	setCollisionGroupRecursive(character, collisionGroupName)
	end

end
local function onPlayerAdded(player)
	player.CharacterAdded:Connect(function(character)
		onCharacterAdded(character)
	end)
end

local function gamepassPurchaseFinished(player, gamePassId, wasPurchased)
	if player == nil then return end
	if player.Character:FindFirstChild("Humanoid") then
		if gamePassId == 6318668 then
			if wasPurchased == true then
				local character = player.Character
				local collisionGroupName = hasGamePass
				pcall(setCollisionGroupRecursive(character, collisionGroupName))
			end
		end
	end
end


GamePassService.PromptGamePassPurchaseFinished:Connect(gamepassPurchaseFinished)
Players.PlayerAdded:Connect(onPlayerAdded)

Unless I’m unaware of changes Roblox made to pcall, I imagine you need to write pcall(setCollisionGroupRecursive(character, collisionGroupName)) as pcall(setCollisionGroupRecursive,character,collisionGroupName) otherwise it’d be calling pcall with the return value of that function

setCollisionGroupRecursive returns nothing, so this would error. You were probably thinking of something like this.

pcall(setCollisionGroupRecursive,character,collisionGroupName)

Considering you’re getting the descendants, why do you need to make it recursive?

1 Like

I completely forgot that there was a function that recursively returned the children, I fixed that; thank you for the pcall syntax thing, I am new to using more advanced things such as that.

Same issue as in Best method for a gamepass-only door? (posted by same poster)

Closing to prevent forked discussion – please continue discussing / giving support in the topic above.