You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This page describes how to register additional BepuSimulation instances from
code instead of declaring them in GameSettings.sdgamesettings, and how to
attach a CollidableComponent (body, static, character) to a specific
simulation by index using the IndexBasedSimulationSelector.
It is the runtime counterpart of the Bepu Configuration asset that the
Game Studio exposes. Both paths end up populating the same BepuConfiguration.BepuSimulations list.
Note
The Bepu integration registers BepuConfiguration as an IService. The
first call to Services.GetService<BepuConfiguration>() triggers BepuConfiguration.NewInstance(...), which also adds the PhysicsGameSystem to the game system collection. From that moment on the
simulations declared in the configuration start ticking.
When to use this
You typically want to add simulations from code in the following cases:
You ship a game without a Game Studio asset for BepuConfiguration (for
example a tool, a benchmark, or a project bootstrapped from Stride.CommunityToolkit).
You need more than one isolated simulation (for example: world physics,
ragdoll/debris physics, UI/preview physics) and you want gameplay code to
decide how many of them exist.
You want to recreate the configuration on the fly when loading a different
level.
For shipping projects that already use the editor, prefer editing the Bepu Configuration in GameSettings.sdgamesettings so designers can tweak
gravity, time scale, solver iterations, etc.
Add simulations from a startup script
The recommended entry point is a StartupScript that runs before any CollidableComponent is attached. It is safe to call GetService here: if the
configuration was already loaded from GameSettings.sdgamesettings, you get
that instance back; otherwise a fresh one is created and registered.
usingStride.BepuPhysics;usingStride.BepuPhysics.Definitions;usingStride.Core.Mathematics;usingStride.Engine;namespaceMyGame.Physics;publicclassBepuSimulationsBootstrap:StartupScript{publicoverridevoidStart(){// Resolve (or create) the BepuConfiguration registered as IService.// NewInstance is invoked once; subsequent calls return the cached// instance held by the ServiceRegistry.varbepuConfig=Services.GetService<BepuConfiguration>()??(BepuConfiguration)BepuConfiguration.NewInstance(Services);// Optional: if you want to take full control of the list, clear the// default simulation that NewInstance() inserts when nothing was// configured in the game settings.// bepuConfig.BepuSimulations.Clear();// Index 0 - main world simulation.bepuConfig.BepuSimulations.Add(newBepuSimulation{Enabled=true,ParallelUpdate=true,PoseGravity=newVector3(0,-9.81f,0),FixedTimeStepSeconds=1.0/60.0,TimeScale=1f,MaxStepPerFrame=3,SoftStartDuration=TimeSpan.FromSeconds(1),SoftStartSubstepFactor=4,});// Index 1 - effects simulation (debris, ragdolls) running at half speed// and without gravity.bepuConfig.BepuSimulations.Add(newBepuSimulation{Enabled=true,PoseGravity=Vector3.Zero,TimeScale=0.5f,ParallelUpdate=true,});// Index 2 - preview/UI simulation, disabled by default; enable it on// demand when an inventory or character preview is opened.bepuConfig.BepuSimulations.Add(newBepuSimulation{Enabled=false,PoseGravity=newVector3(0,-2f,0),});}}
Important
The position of each simulation in BepuConfiguration.BepuSimulations is
what IndexBasedSimulationSelector targets. Do not reorder the list once
collidables have been attached, or you will silently move them to a
different simulation the next time they re-attach.
Add simulations during game bootstrapping
When the project does not load a game settings asset (for example game.AutoLoadDefaultSettings = false in a benchmark or a tool), populate the
configuration in the Game.Run(start: ...) callback so that it exists before
the first scene loads:
Every CollidableComponent (i.e. BodyComponent, StaticComponent, CharacterComponent) exposes a SimulationSelector property. By default this
is SceneBasedSimulationSelector.Shared, which picks the simulation whose AssociatedScene matches the entity's scene.
To bypass that lookup and target a known simulation by its index in BepuConfiguration.BepuSimulations, assign an IndexBasedSimulationSelector:
usingStride.BepuPhysics;usingStride.BepuPhysics.Definitions;usingStride.BepuPhysics.Definitions.Colliders;usingStride.Core.Mathematics;usingStride.Engine;publicclassSpawnDebrisOnEffectsSimulation:StartupScript{publicoverridevoidStart(){// Target simulation index 1 (the "effects" simulation defined above).varselector=newIndexBasedSimulationSelector{Index=1};// Dynamic body.varbody=newBodyComponent{Collider=newBoxCollider{Size=newVector3(0.5f)},SimulationSelector=selector,CollisionLayer=CollisionLayer.Layer0,Mass=1f,Gravity=false,// simulation 1 has no gravity anyway};// Static collider on the same simulation.varground=newStaticComponent{Collider=newBoxCollider{Size=newVector3(50,1,50)},SimulationSelector=selector,};vardebris=newEntity("Debris"){body};debris.Transform.Position=newVector3(0,5,0);Entity.Scene.Entities.Add(debris);varfloor=newEntity("EffectsFloor"){ground};Entity.Scene.Entities.Add(floor);}}
Move a collidable between simulations at runtime
Assigning a new SimulationSelector to an attached CollidableComponent
detaches it from its current simulation and reattaches it to the one returned
by the new selector. There is no need to remove and re-add the component:
This is convenient for transferring objects between, for example, a paused
"preview" simulation and the live world simulation.
Things to keep in mind
IndexBasedSimulationSelector.Index must be valid the moment a collidable
is attached. Add your simulations in a StartupScript (or in Game.Run's start callback) so the configuration is populated before any
physics entity enters the scene.
Simulations created in code are not persisted in GameSettings.sdgamesettings. They live only for the duration of the
process.
BepuSimulation owns a Bepu BufferPool and a ThreadDispatcher. Removing
a simulation at runtime is not handled out of the box; design your code so
the set of simulations is stable once gameplay starts.
SceneBasedSimulationSelector is still available if you prefer to associate
simulations with scenes via BepuSimulation.AssociatedScene. Use whichever
selector matches how you organize your project.
See also
BepuConfiguration - holds the list of simulations, registered as an IService and serialized in GameSettings.sdgamesettings.
BepuSimulation - the runtime simulation object that wraps a Bepu Simulation and exposes ray casts, sweeps and overlap queries.
ISimulationSelector / SceneBasedSimulationSelector / IndexBasedSimulationSelector - strategies used by CollidableComponent to
resolve which simulation an entity belongs to.
CollidableComponent - base class for BodyComponent, StaticComponent
and CharacterComponent.
Create Bepu simulations at runtime
This page describes how to register additional
BepuSimulationinstances fromcode instead of declaring them in
GameSettings.sdgamesettings, and how toattach a
CollidableComponent(body, static, character) to a specificsimulation by index using the
IndexBasedSimulationSelector.It is the runtime counterpart of the Bepu Configuration asset that the
Game Studio exposes. Both paths end up populating the same
BepuConfiguration.BepuSimulationslist.Note
The Bepu integration registers
BepuConfigurationas anIService. Thefirst call to
Services.GetService<BepuConfiguration>()triggersBepuConfiguration.NewInstance(...), which also adds thePhysicsGameSystemto the game system collection. From that moment on thesimulations declared in the configuration start ticking.
When to use this
You typically want to add simulations from code in the following cases:
BepuConfiguration(forexample a tool, a benchmark, or a project bootstrapped from
Stride.CommunityToolkit).ragdoll/debris physics, UI/preview physics) and you want gameplay code to
decide how many of them exist.
level.
For shipping projects that already use the editor, prefer editing the
Bepu Configuration in
GameSettings.sdgamesettingsso designers can tweakgravity, time scale, solver iterations, etc.
Add simulations from a startup script
The recommended entry point is a
StartupScriptthat runs before anyCollidableComponentis attached. It is safe to callGetServicehere: if theconfiguration was already loaded from
GameSettings.sdgamesettings, you getthat instance back; otherwise a fresh one is created and registered.
Important
The position of each simulation in
BepuConfiguration.BepuSimulationsiswhat
IndexBasedSimulationSelectortargets. Do not reorder the list oncecollidables have been attached, or you will silently move them to a
different simulation the next time they re-attach.
Add simulations during game bootstrapping
When the project does not load a game settings asset (for example
game.AutoLoadDefaultSettings = falsein a benchmark or a tool), populate theconfiguration in the
Game.Run(start: ...)callback so that it exists beforethe first scene loads:
Attach a collidable to a specific simulation
Every
CollidableComponent(i.e.BodyComponent,StaticComponent,CharacterComponent) exposes aSimulationSelectorproperty. By default thisis
SceneBasedSimulationSelector.Shared, which picks the simulation whoseAssociatedScenematches the entity's scene.To bypass that lookup and target a known simulation by its index in
BepuConfiguration.BepuSimulations, assign anIndexBasedSimulationSelector:Move a collidable between simulations at runtime
Assigning a new
SimulationSelectorto an attachedCollidableComponentdetaches it from its current simulation and reattaches it to the one returned
by the new selector. There is no need to remove and re-add the component:
This is convenient for transferring objects between, for example, a paused
"preview" simulation and the live world simulation.
Things to keep in mind
IndexBasedSimulationSelector.Indexmust be valid the moment a collidableis attached. Add your simulations in a
StartupScript(or inGame.Run'sstartcallback) so the configuration is populated before anyphysics entity enters the scene.
GameSettings.sdgamesettings. They live only for the duration of theprocess.
BepuSimulationowns a BepuBufferPooland aThreadDispatcher. Removinga simulation at runtime is not handled out of the box; design your code so
the set of simulations is stable once gameplay starts.
SceneBasedSimulationSelectoris still available if you prefer to associatesimulations with scenes via
BepuSimulation.AssociatedScene. Use whicheverselector matches how you organize your project.
See also
BepuConfiguration- holds the list of simulations, registered as anIServiceand serialized inGameSettings.sdgamesettings.BepuSimulation- the runtime simulation object that wraps a BepuSimulationand exposes ray casts, sweeps and overlap queries.ISimulationSelector/SceneBasedSimulationSelector/IndexBasedSimulationSelector- strategies used byCollidableComponenttoresolve which simulation an entity belongs to.
CollidableComponent- base class forBodyComponent,StaticComponentand
CharacterComponent.