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.
OnSimulationStart
Called at the start of current's frame simulation.
OnSimulationEnd
Called at the end of current's frame simulation.
OnInterpolate
Called after all simulation for the current frame has been performed and particle positions have been interpolated, but before updating rendering components. This is the ideal place to modify renderablePositions/renderableOrientations.

Here's a sample script that applies a force to a particle group at the start of each step by subscribing to OnSimulate:

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>().OnSimulationStart += Actor_OnSimulate;
	}

	public void OnDisable()
	{
		GetComponent<ObiActor>().OnSimulationStart -= Actor_OnSimulate;
	}

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