Scripting solvers

Changing solver parameters

ObiSolvers expose global simulation parameters such as gravity, velocity damping, or inertia scaling. These are grouped into a "paremeters" struct. Changes to this struct will only be made effective upon calling solver.PushSolverParameters(). Here's some sample code to change gravity and damping:

solver.parameters.gravity = new Vector3(0,-2,0);
solver.parameters.damping = 0.3f;
solver.PushSolverParameters();

Global constraint parameters such as iteration count and relaxation factor are also grouped in one struct per constraint type. After modifying one of these structs, you also need to call solver.PushSolverParameters(); to make the changes effective. For instance, to set the amount of distance constraint iterations to 3:

solver.distanceConstraintParameters.iterations = 3;
solver.PushSolverParameters();

For a complete list of all solver/constraint parameters, please refer to the API documentation.

Solver callbacks

Solvers expose a variety of events that are triggered at different stages during simulation. You can hook your own custom code to these, it will be executed at specific moments. Here's a list of all callbacks in the solver:

OnCollision
Called at the end of each simulation step, when all simplex-collider contacts are available. For more information, see scripting collisions.
OnParticleCollision
Called at the end of each simulation step, when all simplex-simplex contacts are available. For more information, see scripting collisions.
OnUpdateParameters
Called at the end of solver.PushSolverParameters();. Note that PushSolverParameters() is also called internally by the engine at certain points, having this callback allows you to react to a change in solver parameters regardless of who changed them or when.
OnPrepareFrame
Called at the start of the updater's PrepareFrame(). Depending on which ObiUpdater is being used, this can either be Unity's FixedUpdate() -if using ObiFixedUpdater or ObiLateFixedUpdater- or Update() -if using ObiLateUpdater-.
OnPrepareStep
Called at the start of the updater's BeginStep(): at the very beginning of each simulation step before updating active particles/simplices and the solver's simulation frame.
OnBeginStep
Called at the start of the updater's BeginStep(): at the beginning of each simulation step, after updating active particles/simplices but right before emitters spawn/kill particles and collision detection is performed (both simplex-collider and simplex-simplex).
OnSubstep
Called at the start of the updater's Substep(): right before each substep.
OnEndStep
Called at the start of the updater's EndStep(): at the end of the current simlation step, after all substeps have been performed, and OnCollision/OnParticleCollision have been called and external forces/torques been reset to zero.
OnInterpolate
Called at the start of the updater's Interpolate(): after all simulation for the current frame has been performed and particle positions have been interpolated, but before updating rendering components.

Here's a sample script that applies a force to all particles at the start of each step by subscribing to OnBeginStep:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;

[RequireComponent(typeof(ObiActor))]
public class ApplyForces : MonoBehaviour {

	public ObiParticleGroup group;
	public float intensity = 1;

	public void OnEnable()
	{
		GetComponent<ObiActor>().OnBeginStep += Actor_OnPreSolverStep;
	}

	public void OnDisable()
	{
		GetComponent<ObiActor>().OnBeginStep -= Actor_OnPreSolverStep;
	}

	void Actor_OnPreSolverStep(ObiActor actor, float stepTime)
	{
		foreach (int i in group.particleIndices)
		actor.solver.externalForces[actor.solverIndices[i]] = Vector3.left * intensity;
	}
}