You could just loop through the parts and set their positions each physics frame.
I suggest using CollectionService to keep track of all your physics parts, it would be better than looping through all descendants.
Something like this (obviously not complete)
local function LockPartToZ(part, zOffset)
zOffset = zOffset or 0
part.Position = Vector3.new(part.Position.X, part.Position.Y, zOffset)
end
local parts = {} -- table of parts. there are many ways you could obtain this,
-- some are faster than others
local function Update()
for _, part in pairs(parts) do
LockPartToZ(part, 0)
end
end
game:GetService("RunService").Stepped:Connect(Update)
But, is this solution laggy? I need the movement to replicate and I guess I have to use a script for this to work for everyone as I may add a multiplayer mode…
Now the thing is that will this make the server laggy?
Pretty sure you could put in a BodyPosition with a MaxForce of math.huge on the z axis (relative to your camera [this is important!]). e.g.
for i, v in next, game.Workspace:GetDescendants() do
if v.Name == 'Fake_2D' and v:IsA "BasePart" then -- Find all parts you want to only move on x/y axis
local bp = Instance.new 'BodyPosition'
bp.MaxForce = Vector3.new(0, 0, math.huge)
bp.Position = v.Position * Vector3.new(0, 0, 1)
bp.Parent = v
end
end
All parts will be free to move in X/Y direction, but not on the Z axis (does not account for rotation, you’d need to use a BodyGyro to stop yaw rotation relative to viewframe).
Edit: Tested it and I can confirm this works.
p.s. if this is only for a character, then just instantiate one BodyPosition inside the character’s HumanoidRootPart - it doesn’t need to be replicated to all instances within a welded model.
When you say (relative to your camera position), it is due to the Z Axis and basically, it is as if I try Humanoid:Move(), I can set this relative to the camera.
But, I guess yes, does this work with a scripted camera that is always focusing the Player’s Humanoid in a specific way ?
Because I never really understood this “relative to the camera”
EDIT: I will test both of your solutions later on, thank you so much though !
It’s a very simple thing to run every frame. If you’re smart about how you fill up that parts table (i.e. use a CollectionService and only fill it up once), no, it won’t be laggy for several hundred parts.
@Isocortex’s solution will also work fine, but may be more resource intensive because it forces roblox to do additional physics calculations. I’d have to benchmark them.
In reference to the positional Z axis relative to your camera, I mean what you’re defining as depth in your world. I don’t know how you’ve set up your environment, so for all I know, the way you want to view your position is actually from Z/Y in 3D space (which would translate to X/Y in 2D when projected to the camera).
If your camera is offset from the humanoid and viewing it in a 2D-esque fashion, it would not be advisable to take the camera into account when calling :Move() as you want the character to move relative to itself/worldspace (forwards/backwards in 2D space), not the camera.
Regardless of the above, yes this would work if the camera is always focusing on the humanoid, but you need to account for:
The in-built humanoid method to rotate the character in 3D space to move alternate directions
If the character is subject to any physics, you need to account for any other rotational movement and counter it with another BodyForce e.g. BodyGyro