I’m trying to develop a physics based destruction mini-game and I’ve been stuck for a couple of days when I’m trying to reload the whole scene to start fresh again.
Here is the video of what happens:
I’m using several system using jobs to detect collision like this:
[System.Serializable]
public partial class CollisioWallToActorDetectionSystem : SystemBase
{
private StepPhysicsWorld stepPhysicsWorld;
private EndSimulationEntityCommandBufferSystem commandBufferSystem;
protected override void OnCreate()
{
stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
commandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override void OnUpdate()
{
var jobHandle = Dependency;
Dependency.Complete();
var applicationJob = new ApplicationWallToRagdollJob
{
actorCollider = GetComponentDataFromEntity<RagdollComponent>(),
wallCollider = GetComponentDataFromEntity<WallColliderData>()
};
Dependency = applicationJob.Schedule(stepPhysicsWorld.Simulation, Dependency);
commandBufferSystem.AddJobHandleForProducer(Dependency);
}
[BurstCompile]
private struct ApplicationWallToRagdollJob : ICollisionEventsJob
{
public ComponentDataFromEntity<RagdollComponent> actorCollider;
public ComponentDataFromEntity<WallColliderData> wallCollider;
public void Execute(CollisionEvent triggerEvent)
{
if (wallCollider.HasComponent(triggerEvent.EntityA))
{
if (actorCollider.HasComponent(triggerEvent.EntityB))
{
WallColliderData wall = wallCollider[triggerEvent.EntityA];
wall.Destroy = true;
wallCollider[triggerEvent.EntityA] = wall;
}
}
if (wallCollider.HasComponent(triggerEvent.EntityB))
{
if (actorCollider.HasComponent(triggerEvent.EntityA))
{
WallColliderData wall = wallCollider[triggerEvent.EntityB];
wall.Destroy = true;
wallCollider[triggerEvent.EntityB] = wall;
}
}
}
}
}
So, what should I do to start clean? I’ve tried the few things I’ve found on Internet unsuccessfully and I’ve run out of options.
I’ve had issues myself in the past with clearing a world and reusing it. It looked like a use case Unity had not tested properly. I did not find a solution, but here’s the workaround I use:
Create a brand new world and dispose of the previous one. This brings a couple of challenges because you have to rebind the world to the player loop, but at least it works.
I modified script a little so we no longer have this strings around.
public void CleanAndRestartECS()
{
var worldName = World.DefaultGameObjectInjectionWorld.Name;
var defaultWorld = World.DefaultGameObjectInjectionWorld;
defaultWorld.EntityManager.CompleteAllTrackedJobs();
foreach (var system in defaultWorld.Systems)
{
system.Enabled = false;
}
defaultWorld.Dispose();
DefaultWorldInitialization.Initialize(worldName, false);
if (!ScriptBehaviourUpdateOrder.IsWorldInCurrentPlayerLoop(World.DefaultGameObjectInjectionWorld))
{
ScriptBehaviourUpdateOrder.AppendWorldToCurrentPlayerLoop(World.DefaultGameObjectInjectionWorld);
}
var scene = SceneManager.GetActiveScene();
var sceneName = scene.name;
SceneManager.LoadScene(sceneName, LoadSceneMode.Single);
}