Turns out collisions and a few other bits weren't really ready for in-editor simulation. In addition to extending ObiUpdater, you will need to make a few changes:
- Add [ExecuteInEditMode] to BurstColliderWorld.cs/OniColliderWorld.cs. This will allow collision data structures to be initialized in-editor.
- Add [ExecuteInEditMode] to ObiParticleAttachment.cs. This will allow attachments to run in edit mode.
- Comment out lines 1106-1126 of ObiActor.cs. These are intended to override renderable particle positions at edit time, to allow particle positions to reflect changes to the actor's transform in absence of simulation.
- Line 146 of ObiClothRendererBase.cs, remove "Application.isPlaying" from the if() statement. This was intended to reduce work done in-editor.
With these changes, you can then use this ObiUpdater subclass to step the simulation forward in editor by clicking the inspector's "update" button.
Code:
using UnityEngine;
namespace Obi
{
/// <summary>
/// Updater class that will perform simulation at edit time.
[AddComponentMenu("Physics/Obi/Obi Editor Updater", 801)]
[ExecuteInEditMode]
public class ObiEditorUpdater : ObiUpdater
{
/// <summary>
/// Each FixedUpdate() call will be divided into several substeps. Performing more substeps will greatly improve the accuracy/convergence speed of the simulation.
/// Increasing the amount of substeps is more effective than increasing the amount of constraint iterations.
/// </summary>
[Tooltip("Amount of substeps performed per FixedUpdate. Increasing the amount of substeps greatly improves accuracy and convergence speed.")]
public int substeps = 1;
[InspectorButton("UpdateEditor")]
public bool update;
private void OnValidate()
{
substeps = Mathf.Max(1, substeps);
}
private void UpdateEditor()
{
Step(0.02f);
}
private void Step(float timestep)
{
ObiProfiler.EnableProfiler();
BeginStep(timestep);
float substepDelta = timestep / (float)substeps;
// Divide the step into multiple smaller substeps:
for (int i = 0; i < substeps; ++i)
{
// Simulate Obi:
Substep(substepDelta);
}
EndStep(substepDelta);
Interpolate(timestep, timestep);
ObiProfiler.DisableProfiler();
}
}
}
If you describe your use case more accurately, I can come up with better solutions for it after Christmas. Potential improvements include writing an in-editor fixed timestep loop to circumvent the absence of FixedUpdate() calls, supporting simulation reset, updating Unity's rigidbody physics in sync, and some others.
cheers!