Collision Filtering – Puzzle Platformer

In this tutorial we will cover how to build a puzzle platformer mechanic using collision filters. Specifically, we will build a force field that allows players to pass through, but blocks the motion of crates.

In our example level we have a ledge that the player has to jump on top of. In front of the ledge is a pit covered with a force field named ForceField. Next to the pit is a wooden crate (unanchored) named Crate.

PuzzlePlatformer.png

In this case we want the player to be able to fall through the force field. But if the crate is pushed onto the force field, it should rest on top of it and not fall through. To do this, we will need to set up collision groups for the objects involved.

First, we’ll insert a Script to manage the collision groups. Inside of it we need to make variables for PhysicsService and the parts of our level.

local PhysicsService = game:GetService("PhysicsService")
 
local forceField = game.Workspace.ForceField
local crate = game.Workspace.Crate

Next we need to create the collision groups. In this case, we will need two groups, one for force fields and one for crates. We can use the CreateCollisionGroup and SetPartCollisionGroup functions of PhysicsService to do this.

local PhysicsService = game:GetService("PhysicsService")
 
local forceField = game.Workspace.ForceField
local crate = game.Workspace.Crate
 
local forceFieldGroup = "ForceFieldGroup"local crateGroup = "CrateGroup" PhysicsService:CreateCollisionGroup(forceFieldGroup)PhysicsService:CreateCollisionGroup(crateGroup) PhysicsService:SetPartCollisionGroup(forceField, forceFieldGroup)PhysicsService:SetPartCollisionGroup(crate, crateGroup)

Note that we also made variables for our collision group names. Collision groups aren’t instances (like parts) and can only be accessed through the PhysicsService by name. It is recommended to save this name in a variable. That way, we don’t have to write the over and over again later in the code (we can just use the variable), and if we ever had to rename the group we only would have to do that in one place.

Last we need to set up the collision rules between the groups. The force field will collide with the crate group, but not with the default group (so that the player and other objects can fall through it). The crate group will collide with everything but the force field group. To configure whether two groups will collide, we can use the CollisionGroupSetCollidable function.

local PhysicsService = game:GetService("PhysicsService")
 
local forceField = game.Workspace.ForceField
local crate = game.Workspace.Crate
 
local forceFieldGroup = "ForceFieldGroup"
local crateGroup = "CrateGroup"
 
PhysicsService:CreateCollisionGroup(forceFieldGroup)
PhysicsService:CreateCollisionGroup(crateGroup)
 
PhysicsService:SetPartCollisionGroup(forceField, forceFieldGroup)
PhysicsService:SetPartCollisionGroup(crate, crateGroup)
 
PhysicsService:CollisionGroupSetCollidable(forceFieldGroup, "Default", false)

And this is all we need to do to set up our mechanic. Notice that we only had to specify that the force field group doesn’t collide with the default group. Groups always start off by colliding with each other, so there is no need to explicitly instruct the groups to collide (the only time one would have to do that is if the groups were previously set to not collide with each other).

Now when the play goes through our game they will fall through the force field, but will be able to push the crate and jump on top of it to progress.

CollisionGroupPuzzlePlatformer1.gif

CollisionGroupPuzzlePlatformer2.gif