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.