Filter baking output
By default, every entity and every component created in the conversion world is part of the baking output.
However, not every GameObject in an authoring scene is relevant to keep as an entity. For example, a control point on a spline might only be used during authoring, and can be discarded at the end of baking.
To exclude entities from the baking output, you can add the BakingOnlyEntity
tag component to the entity. When you add this tag component, Unity doesn't store the entity in the entity scene, and doesn't merge it into the main world. A baker can directly add BakingOnlyEntity
to an entity, or you can add the BakingOnlyEntityAuthoring
to a GameObject to achieve the same effect.
You can also exclude components with the following attributes:
[BakingType]
: Filters any components marked with this attribute from the baking output.[TemporaryBakingType]
: Destroys any components marked with this attribute from the baking output. This means that components marked with this attribute don't remain from one baking pass to the next, and only exist during the time that a particular baker ran.
You can exclude components to pass information from a baker to a baking system. For example, a baker can record the bounding box of an entity as a baking type, and later in the baking process, a baking system can collect all the bounding boxes and compute a convex hull. If only the hull is useful, the bounding boxes can be discarded.
In this particular example, you have to use the [BakingType]
attribute rather than [TemporaryBakingType]
. This is because the convex hull system need to access all bounding boxes, and not only the ones that changed. However, if it was a system that needed to process all the entities whose bounding boxes intersect with the ground plane, it would be better to only process those entities whose bounding boxes effectively changed. Therefore you could use [TemporaryBakingType]
.
The following is an example that uses [TemporaryBakingType]
:
[TemporaryBakingType]
public struct TemporaryBakingData : IComponentData
{
public float Mass;
}
public struct SomeComputedData : IComponentData
{
// Computing this is too expensive to do in a Baker, we want to make use of Burst (or maybe Jobs)
public float ComputedValue;
}
public class RigidBodyBaker : Baker<Rigidbody>
{
public override void Bake(Rigidbody authoring)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new TemporaryBakingData{Mass = authoring.mass});
// Even though we don't compute the data, we add the type from the Baker
AddComponent(entity, new SomeComputedData());
}
}
[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]
[BurstCompile]
partial struct SomeComputingBakingSystem : ISystem
{
// We are doing performance critical work here, so we use Burst
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
// Because TemporaryBakingData is a [TemporaryBakingType] it only exists the same Bake pass that RigidBodyBaker ran
// This means this Baking System will only run if the inputs to RigidBodyBaker change and cause it to re-bake
// Additionally, because we are using no managed types in this system, we can use Burst
foreach (var (computedComponent, bakingData) in
SystemAPI.Query<RefRW<SomeComputedData>, RefRO<TemporaryBakingData>>())
{
var mass = bakingData.ValueRO.Mass;
float result = 0;
// Do heavy computation here, which is taking advantage of Burst
// result = ...
computedComponent.ValueRW.ComputedValue = result;
}
}
}