I’m trying out the ECS again. It says in the docs that ComponentSystem is only intended for prototyping and such, and that we should use job systems instead.
I’m making my first basic systems for this project and ComponentSystem API looks rather fine. But the job system is incredibly bloated with boilerplate code.
Actual code here is nonsense, just to test the API, but it’s based on the real thing I’m trying to do: operate camera position based on input and control settings.
Am I doing the job system right? Is there a way to decrease the amount of code? (I tried single IJob it wasn’t better) Will API be improved to make these simple tasks easier?
I’m doing the same thing with “CameraPivot” and “CameraHolder” but imagine that I’m not (in real code it won’t be)
public class CameraControlSystem : ComponentSystem
{
protected override void OnUpdate()
{
var input = Entities.WithAll<MainDirectionalInput>()
.ToEntityQuery().GetSingleton<MainDirectionalInput>();
var control = Entities.WithAll<MainCameraControl>()
.ToEntityQuery().GetSingleton<MainCameraControl>();
Entities.WithAll<CameraHolder>()
.ForEach((Entity e, ref Translation pos, ref Rotation rot) =>
{
if (input.Forward.IsHold)
{
pos.Value += math.forward(rot.Value)
* control.HorizontalVelocity * Time.deltaTime;
}
if (input.Backward.IsHold)
{
pos.Value += math.forward(rot.Value)
* control.HorizontalVelocity * Time.deltaTime;
}
});
Entities.WithAll<CameraPivot>()
.ForEach((Entity e, ref Translation pos, ref Rotation rot) =>
{
if (input.Forward.IsHold)
{
pos.Value += math.forward(rot.Value)
* control.HorizontalVelocity * Time.deltaTime;
}
if (input.Backward.IsHold)
{
pos.Value += math.forward(rot.Value)
* control.HorizontalVelocity * Time.deltaTime;
}
});
}
}
Just comparing to MB approach. ~25% less symbols than ComponentSystem.
public class MonobehaviourApproach : Monobehaviour
{
[SerializeField] private MainDirectionalInput input;
[SerializeField] private MainCameraControl control;
[SerializeField] private Transform _pivotTransform;
[SerializeField] private Transform _cameraTransform;
private void Update()
{
if (input.Forward.IsHold)
{
_pivotTransform.position += _pivotTransform.forward
* control.HorizontalVelocity * Time.deltaTime;
}
if (input.Backward.IsHold)
{
_pivotTransform.position += _pivotTransform.forward
* control.HorizontalVelocity * Time.deltaTime;
}
if (input.Forward.IsHold)
{
_cameraTransform.position += _pivotTransform.forward
* control.HorizontalVelocity * Time.deltaTime;
}
if (input.Backward.IsHold)
{
_cameraTransform.position += _pivotTransform.forward
* control.HorizontalVelocity * Time.deltaTime;
}
}
}
Job system requires ~100% more lines of code. The boilerplate ratio is insane for simple tasks that require data from multiple different entities.
public class CameraControlJobSystem : JobComponentSystem
{
private EntityQuery _inputQuery;
private EntityQuery _controlQuery;
protected override void OnCreateManager()
{
_inputQuery = GetEntityQuery(new ComponentType[]
{ ComponentType.ReadOnly<MainDirectionalInput>() });
_controlQuery = GetEntityQuery(new ComponentType[]
{ ComponentType.ReadOnly<MainCameraControl>() });
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
return new MoveJob
{
DeltaTime = Time.deltaTime,
Input = _inputQuery.GetSingleton<MainDirectionalInput>(),
Control = _controlQuery.GetSingleton<MainCameraControl>(),
}.Schedule(this, new ZoomJob
{
DeltaTime = Time.deltaTime,
Input = _inputQuery.GetSingleton<MainDirectionalInput>(),
Control = _controlQuery.GetSingleton<MainCameraControl>(),
}.Schedule(this, inputDeps));
}
[BurstCompile]
[RequireComponentTag(typeof(CameraPivot))]
protected struct MoveJob : IJobForEach<Translation, Rotation>
{
public MainDirectionalInput Input;
public MainCameraControl Control;
public float DeltaTime;
public void Execute(ref Translation pos, ref Rotation rot)
{
if (Input.Forward.IsHold)
{
pos.Value += math.forward(rot.Value)
* Control.HorizontalVelocity * Time.deltaTime;
}
if (Input.Backward.IsHold)
{
pos.Value += math.forward(rot.Value)
* Control.HorizontalVelocity * Time.deltaTime;
}
}
}
[BurstCompile]
[RequireComponentTag(typeof(CameraHolder))]
protected struct ZoomJob : IJobForEach<Translation, Rotation>
{
public MainDirectionalInput Input;
public MainCameraControl Control;
public float DeltaTime;
public void Execute(ref Translation pos, ref Rotation rot)
{
if (Input.Forward.IsHold)
{
pos.Value += math.forward(rot.Value)
* Control.HorizontalVelocity * Time.deltaTime;
}
if (Input.Backward.IsHold)
{
pos.Value += math.forward(rot.Value)
* Control.HorizontalVelocity * Time.deltaTime;
}
}
}
}