Ability to simulate physics while in edit mode

I’m developing map tools and I need some way to simulate physics while editing in studio. There are a few use cases for this.

  1. Fun physics-based object placement.
    The ability to physically drop objects into the scene would allow for models to be placed in a physically accurate way. You could use a plugin to throw rocks across the ground and watch them sink into place after they settle.

  2. Stable object placement for non-Anchored parts.
    Currently when placing unanchored objects, we’re just estimating how the object will settle. Everything falls down once simulation begins, and you risk objects tipping over or glitching with intersecting parts. With this feature, we could enable simulation on an object and let it settle before finalizing it via a plugin.

  3. Efficient map development with fast iteration time.
    Large projects can take seconds to start up. With physics built into the editor, map artists could spawn as a character within the workspace with no wait time and no disruption to their workflow. This most likely needs custom camera and character controls which is completely fine; We’ll figure that out. We just need to be able to simulate physics.

Here are a few possible behaviors. The second one is more intuitive, but might be more difficult to implement:

  1. Simulation affects all non-Anchored parts. There would be a service property that enables this.
  2. Simulation affects all non-Anchored non-Archivable parts. CFrame changes would not affect ChangeHistoryService, as objects don’t save or affect undo history when Archivable is false (which is extremely useful.) There could be a service property that enables this, or it could happen by default.

I mainly just need rigid collisions, but constraints would be useful too. This is a very practical feature that other game engines have, and plugin creators could do a lot with it.

29 Likes

The IK dragger (dragger Mode: Physical) does a form of this. It’s just using the physics engine in a different mode with positional correction only, no velocity integration or solving for forces. This can be useful for snapping together mechanisms like cars before you start simulation, even if it’s not a true “warm starting” solution since it won’t get your mechanism settled into static equilibrium. Some other features that we’re working on will probably force us to think about the “warm starting” use case in more depth soon.

In theory it would be a natural extension of the physical dragger to add a “simulate selection” option. Not sure how it would work in team create though. Maybe only applying position changes when simulation ends?

Good idea that we’ll like to tackle, but no promises if or when we’ll be able to get to it!

Third use case is a little terrifying. Even if we treat the rest of the world as anchored I’d be terrified of subtle side effects of the Humanoid running all over the edit-mode world. Also not sure how this would work in team create! Might be a better investment for us to spend time profiling and optimizing DataModel copy and play solo startup. Iteration time matters.

2 Likes

I’m hoping for something more general, where specific instances or models can be simulated from plugins somehow (where non-simulating objects are treated as anchored.) CFrame and Velocity changes could be treated as non-archivable until the simulation stops for the specific model. That way we can create all kinds of physics-based studio tools.

The ability for plugins to “settle” complex models when placing them is probably the most important use-case, but there are other possibilities too. I want to make tools that allow map artists to quickly simulate complex objects, so they don’t need to waste time rotating it perfectly.

A low level method for instantly stepping through simulation could be used to preview where models will settle in advance, but that might be more difficult to support long-term.


I don’t expect humanoids to run normally if at all. Plugin creators can use “luanoids” to achieve this without getting humanoids involved. Maybe Humanoid.HipHeight could simulate so that developers can settle NPCs, but it’s not entirely necessary.

I already use luanoids for characters, so I could easily instantiate a character with custom controls from within my plugin. It’s just a few parts, an AlignOrientation, a VectorForce, a few attachments, and a weld or two. (I insert a disabled humanoid into the model make sure the physics doesn’t throttle on low-end devices, but I can omit that in studio.) This character would be non-archivable and just used to quickly try out what’s been created and get a sense of scale.


It’s already pretty fast for general use. For my project, what map artists are working on is created locally and placed in a non-archivable folder; a new player+server would need to process and recreate the map, which can take a few seconds for highly detailed worlds. It’s designed this way for various reasons, but mainly so there can be dozens of detailed maps with 1M+ objects with no lag when editing. I go into more detail in this post and this post. The specific area they’re working on is already initialized right there in edit mode. I’d like to create a seamless level design experience where artists can try things out while building, and be able to place models down and lean them without needing to rotate them precisely. Most of the work is already done, I just need to be able to simulate parts and forces for specific models.

2 Likes

So I think you’re asking for something like:

-- Simulate only specific parts and constraints until all parts sleep 
-- or maximum duration of time has been simulated. Blocking.
RunService:RunSimulationUntilSleep(
    whitelistDescendants : {Instance}, 
    maxSimulationTime : number)
-- Start simulating only specific parts and constraints until paused 
-- by RunService:Pause().
RunService:RunSimulation(whitelistDescendants : {Instance})

Which I think would support what you want as well as some theoretical Studio actions.

4 Likes

Some way to pause specific instances without pausing everything would be helpful, although this could be achieved by anchoring or replacing models when done. It would also be useful to know when the model sleeps, but this could be done by polling the CFrame.

RunService:Run() alone is almost sufficient for these use-cases assuming everything that isn’t being worked on is anchored. The main issue is that undo/redo history can’t be used during the simulation, and whitelisted methods would be much safer for public plugins to use.

Also, calling RunService:Run() twice in edit mode causes studio to freeze for some reason:

game:GetService("RunService"):Run()
wait(1)
game:GetService("RunService"):Pause()
wait(1)
game:GetService("RunService"):Run()
1 Like