DOTS removing components in a System causes Editor Loop spikes?

Hey everyone!
I’m currently getting my feet wet with ECS and followed the tanks tutorial.
Right now I’m experimenting a bit more with it to get more comfortable, and tried to change my code so each tank gets a random firing rate instead of everything firing at the same time.
I created the following System that checks for a FiringRate and an InitializeRandom component.
Once a FiringRate has been initialized, I figured I just discard the InitializeRandom component to stop it from being reinitialized in the next update.
This is however causing my game to run noticeably slower. When I try to profile this, the profiler however says my latency is within the EditorLoop instead of the expected System.
I’m working in Unity 6000.0.3f1.

Can anyone tell me how I should do this properly and what’s going wrong? Thanks in advance!

[UpdateBefore(typeof(ShootingSystem))]
public partial struct RandomizeFiringRate : ISystem
{
	private Random rng;
	private EntityQuery query;


	public void OnCreate(ref SystemState state)
	{
		rng = new Random(123);
		query = state.GetEntityQuery(typeof(FiringRate), typeof(InitializeRandom));
	}

	[BurstCompile]
	public void OnUpdate(ref SystemState state)
	{
		foreach (var (firingRate, initRandom) in SystemAPI.Query<RefRW<FiringRate>, RefRO<InitializeRandom>>())
		{
			var randomRate = rng.NextFloat(initRandom.ValueRO.Minimum, initRandom.ValueRO.Maximum);
			firingRate.ValueRW.Rate = randomRate;
			firingRate.ValueRW.Time = randomRate;
		}

		state.EntityManager.RemoveComponent<InitializeRandom>(query); //This line causes massive FPS drops, but the increase in processing time seems to be in the Editor Loop?
	}
}

Structural changes are slow. You can use enableable components to make this much faster.

Regarding profiling, the timeline view gives more information than the hierarchy view and I find it more useful 99% of the time. (I pretty much only use it to find a marker, select it, and then switch back to the timeline view to see what’s actually happening.) Profiling a build could also help, but I don’t think it’s necessary in this case.

Thanks for the answer, but I wonder if something other than the structural change is going wrong here.
If the problem was indeed this change, I would expect only the first frame(s) of the runtime to be slowed down as the tanks are all spawned in there and the system initializes and deletes their components, but in subsequent frames the initialization system shouldn’t be doing much as there are no more InitializeRandom components in the world to delete, and thus no more structural changes happen.

When I look at your linked documentation for enableable components, it already states the following:

Enableable components are ideal for states that you expect to change often and unpredictably, or where the number of state permutations are high on a frame-by-frame basis. Adding and removing components is the preferable way to manage components for low-frequency state changes, where you expect the state to persist for many frames.

Since I want the system to only run once for each tank during that tank’s lifetime, I would think this case falls under the category where removing the component is more in line with this advice…

I agree structural changes should be fine for initialization. But in that case I don’t think your change would impact performance at all. You could be measuring the impact of updating some particularly heavy editor window, Burst compilation, or something else. You can try profiling the editor (in play mode this should show both the game code as well as the editor loop) to see which part of the engine is causing the slowdown.

I think I found the problem! I was having the Entities Hierarchy window open. This one definitely slows the editor down to a crawl, but that makes sense when I’m having 1000 tanks each firing multiple bullets per second.

Thanks for the help!

1 Like