ControllerPartSensor does not sense parts unless inserted after local character is parented to Workspace

When working with the new physics controllers, a ControllerPartSensor will always have its SensedPart property set to ‘nil’ if you are creating a client-sided character for your player and having the ControllerPartSensor parented to the character’s root part before the character is parented to the world.

This means that if you are creating a character for your player on the client, the following code will not initialize the physics controllers properly.

local Character = game.ReplicatedStorage.Character:Clone() -- path to character model
Character:SetPrimaryPartCFrame(CFrame.new(0, 6, 0))

-- insert part sensor before parenting. This will *not* work properly
local Sensor = Instance.new("ControllerPartSensor")
Sensor.SearchDistance = 3.5
Sensor.Parent = Character.PrimaryPart
Character.ControllerManager.GroundSensor = Sensor

Character.Parent = game.Workspace
game.Players.LocalPlayer.Character = Character

However, if you first parent the character to the Workspace before inserting the ControllerPartSensor, it will initialize properly.

local Character = game.ReplicatedStorage.Character:Clone() -- path to character model
Character:SetPrimaryPartCFrame(CFrame.new(0, 6, 0))

Character.Parent = game.Workspace
game.Players.LocalPlayer.Character = Character

-- insert part sensor after parenting. This *will* work properly
local Sensor = Instance.new("ControllerPartSensor")
Sensor.SearchDistance = 3.5
Sensor.Parent = Character.PrimaryPart
Character.ControllerManager.GroundSensor = Sensor

This behavior is counterintuitive because the standard ‘best practice’ is to only parent an object to the data model after all its properties and children are initialized to avoid additional replication from taking place.

Reproduction

Below is a place file to reproduce this issue. The two LocalScripts to pay attention to are ‘Broken’ and ‘Working’ inside the StarterPlayerScripts container. As you may expect, the ‘Broken’ LocalScript displays the broken behavior where the character’s RootPart will fall to the ground after the character is parented to the Workspace. The ‘Working’ LocalScript will show the character model hovering slightly above the ground.

Set the Enabled property on one of those two LocalScripts to false and the other one to true, then press ‘Play’ to test the game in Play Solo. There are some other scripts added to the game to overwrite/disable default character and camera controls (i.e. Health, Animate, PlayerModule). The camera is positioned to show the SpawnLocation so you can get a good view of the problem. The game also briefly first loads and destroys your personal avatar because apparently it’s required before some things are loaded.

sensor_bug.rbxl (57.9 KB)

Expected behavior

In the reproduction file I expect the ‘Working’ and ‘Broken’ LocalScripts to demonstrate identical behavior. In both cases the character model should show the RootPart floating slightly above the ground.

5 Likes

Thanks for the report! We’ll follow up when we have an update for you.

2 Likes

I reported this issue first occurring on October 7th, but the post got no replies and was recently closed by moderators.

This issue does not occur when streaming is disabled, which makes sense because the sensor replicates after other instances are already inside the Character.

3 Likes

After having an issue with the Ground Sensor, I found this post.
Tried initializing the Sensor after the Character is parented to workspace.
And the Sensor started functioning properly.

Can confirm this is still an issue.

1 Like

This bug still exists. I had this issue when cloning a character model from ServerStorage that contained a ControllerPartSensor. The Ground Sensor will detect floors server-side but not client-side.

A temporary workaround I found was changing the SearchDistance property through a local script after the character has been inserted into the workspace (using task.wait() if necessary). Changing this property seems to “activate” the sensor for the client and will work as expected.

This problem does not occur when Streaming Enabled is off, as someone had mentioned earlier. The workaround above works with Streaming Enabled.

Edit: Changing the SearchDistance property will update the sensor only once. The ControllerPartSensor seems to behave as if UpdateType is set to manual on the client-side. SensedPart does not update when cloning the character from ServerStorage or ReplicatedStorage. However, if the character starts in the workspace, sensor updates as expected.

1 Like