I’ve read in the manual that GenerateAuthoringComponent is going away.
Will there be any replacement?
It seems like a lot of unnecessary boiler plate for simple components, which only transfer some value.
Am I missing something?
I’ve read in the manual that GenerateAuthoringComponent is going away.
Will there be any replacement?
It seems like a lot of unnecessary boiler plate for simple components, which only transfer some value.
Am I missing something?
there are a new PI called “Baker”. Official - Exciting developments in upcoming Entities 1.0 releases - Unity Forum
Yes, it seems cumbersome, especially if we need to upgrade. We have 200+ components using GenerateAuthoringComponent and we make heavy use of the conversion pipeline. I really want to use 1.0 but converting all the components to use the monobehaviour and baker will take a huge amount of time on its own, let alone the adjustments needed for the other upgrade steps. Waiting to see if any automated processes or tools pop up to improve this; it may just not be worth it at this point for us though.
I’d expect something like [GenerateAuthoringComponent]
, but instead of “magic invisible thing” like in 0.50, it would use code generator and generate authoring component and baker in “nested file”.
It could use partial methods so developers can easily provide their own implementation of baker.
This seems like logical solution, maybe the ECS team haven’t implemented it yet.
The attribute GenerateAuthoringComponent, while very convenient to use, had a lot of problems:
For 1.0 we did not have time to implement a full replacement in the package before feature freeze. However, in one of the next releases we will ship a sample with an alternative API to the attribute, which will hopefully be just as convenient to use. You will be able to copy that implementation in your projects and adapt it according to your needs.
It looks like this:
[Serializable] // The component must be serializable, to make it work with the Unity serialization system and be displayed in the inspector
public struct SpawnerComponent : IComponentData
{
public Entity Prefab; // Entity fields are displayed as GameObject fields in the inspector. The Entity reference is resolved in the baker of the base class
public float3 Offset;
[Range(1, 100)] // Fields can be displayed with custom property drawers...
public int InstanceCount;
[HideInInspector] // ... or can be hidden from the inspector
public int _Padding;
}
public class SpawnerComponentAuthoring : ComponentAuthoring<SpawnerComponent>{} // The ComponentAuthoring base class comes with a default baker which resolves the Entity fields from the assigned GameObject references and bakes all other values.
All component types that can be baked are supported, including managed components.
One key aspect of this solution is that it is not a closed box. You will be able to refine your baked data with custom bakers, just like you would if you wrote everything yourself.
[Serializable]
public struct Properties
{
public float3 Speed;
public float3 Position;
public float3 Rotation;
}
// Complex component, created during the prototyping phase and optimized for editing the data.
[BakingType]
[Serializable]
public struct ComplexAuthoringComponent : IComponentData
{
public Entity Reference;
public Properties Properties;
}
public struct SpeedComponent : IComponentData
{
public float3 Speed;
}
public struct SpawnPrefabComponent : IComponentData
{
public Entity Prefab;
}
// Authoring component, optimized for convenient editing of the data.
public class BakingOnlyComponentAuthoring : ComponentAuthoring<ComplexAuthoringComponent>
{
// Define a baker for the authoring type.
// The base baker for the ComponentAuthoring base class is always going to be evaluated first.
// This ensures that entity references are are already resolved when the baker for the derived class runs.
class BakingOnlyComponentBaker : Baker<BakingOnlyComponentAuthoring>
{
public override void Bake(BakingOnlyComponentAuthoring authoring)
{
AddComponent(new SpawnPrefabComponent() { Prefab = authoring.Data.Reference });
AddComponent(new SpeedComponent { Speed = authoring.Data.Properties.Speed });
}
}
}
// Bake additional authoring properties that could not be processed in a baker.
[RequireMatchingQueriesForUpdate]
[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]
partial class BakeAuthoringPosition : SystemBase
{
protected override void OnUpdate()
{
foreach (var (authoring, transform) in
SystemAPI.Query<ComplexAuthoringComponent, RefRW<LocalTransform>>()
.WithAll<BakedEntity>()
.WithEntityQueryOptions(EntityQueryOptions.IncludeDisabledEntities | EntityQueryOptions.IncludePrefab))
{
transform.ValueRW.Value = TransformData.FromPositionRotation(authoring.Properties.Position,
quaternion.Euler(math.radians(authoring.Properties.Rotation)));
}
}
}
Good step forward thanks
Also it will be good to have one step further and make ComponentAuthoring options. I mean to be able to add something like ComponentsAuthoringBox component to GameObject and the add any IComponentData to it and it will serialize and base them all not only one specific component.
This way we need this line public class SpawnerComponentAuthoring : ComponentAuthoring<SpawnerComponent>{}
only if we really need it. In other cases, ComponentsAuthoringBox will be sufficient and we can work with the same IComponentData in runtime and in edit time without writing 2 paths for IComponent data and corresponding Authoring counterpart.
Could you show a sample of how the API would look like?
The API we’re providing consists of just base classes for each supported ECS component type.
ComponentAuthoring<TComponentData>
ComponentObjectAuthoring<TComponentData>
BufferAuthoring<TComponentData>
SharedComponentAuthoring<TComponentData>
SharedComponentManagedAuthoring<TComponentData>
We went with an explicit approach specifically to encourage people to think about the baking step and optimize their data in the long run, and we thought having to define an authoring component explicitly is not a big cost.
Hi @bogdancoder . I have a couple of things want to ask and confirm with u about A{PI replacement at 1.0 baker.
Just one Compoennt ComponentsAuthoringBox that can be used instead of declaring:
ComponentAuthoring
ComponentObjectAuthoring
BufferAuthoring
SharedComponentAuthoring
SharedComponentManagedAuthoring
All logic of all components put inside ComponentsAuthoringBox so it can handle all cases
Just because your way ask us to place each component in separate cs file that is bad. Always was bad.
And working with 2 component types instead of only one in most cases overengineering.
You can call GetEntity() on any component or prefab reference you have access to in the baker. If it is a prefab reference, then it will get converted to entities and you will get the primary entity referencing it.
We do not guarantee a particular order of execution to bakers *(with one exception, see below). You cannot rely on a baker adding a component before another baker, which is why the API does not allow you to query the primary entity in a baker. You can only add to the primary entity by querying the authoring component.
To get around this, you can add TemporaryBakingType components in bakers and do your post processing to arrange your final data in a baking system.
*) In the next version of the package, the bakers for base component types, which are decorated with the BakeDerivedTypesAttribute will be evaluated before bakers for derived component types.
I see. But it’s working at 0.51 just with simple dstManager.GetComponentData(entity) API. My use case is I want to have 2 separate modules i.e Foo and Bar so I created FooAuthoring And BarAuthoring. FooAuthoring will just create entity and add the AComponent and then BarAuthoring will just call dstManager.GetComponentData(entity) API to do the work. So want both doing their own thing independently with the order that FooAuthoring will run first then follow by BarAuthoring. Basically the ordering depends on the ordering u put at game object. For this case BarAuthoring will put at last before FooAuthoring.
I dunno why this 1.0 Baker now make it so complicated with this simple use case. Hopefully this can be improved to get back the convenient of 0.51 authoring experience.
Btw where should I put [BakingVersion(“a”, 1)] attribute tag? At the class derived by Baker or MonoBehaviour?
The attribute can be used on bakers and baking systems.
What is the difference between [TemporaryBakingType]
and [BakingType]
?
where does the TransformData.FromPositionRotation
come from ??
Components decorated with the [TemporaryBakingType] attribute are stripped after each baking iteration, so you can use them in baking systems to identify entities that a baker has modified during the current baking iteration.
During incremental baking, components with the [BakingType] attribute persist in the baking world.
This allows baking systems to process entities which haven’t been modified during the current baking iteration,
but which are dependencies to the final result of the baking.
Components with the [BakingType] or [TemporaryBakingType] attribute are not exported in the runtime data.
The transform API will come in a future release of the package.
@bogdancoder Btw how should I achieve the same result with current 1.0 baker that split it as Foo and Bar module without need to get each other authoring to do baking? If cannot, do I need to do something like at Bar module I create FooBakingSystem and get BarAuthoring to do the work?
From your description, it sounds like the Bar module knows about Foo. Therefore, in Bar you can have a BarBakingSystem operate on both AComponent and BComponent, where BComponent comes from BarAuthoring and AComponent comes from FooAuthoring. If the FooAuthoring and BarAuthoring are on the same GameObject, they will be on the same entity.
Currently we do not have an API for getting the component index on the GameObject, but this is something we have in our backlog to add. In the meantime you can have AComponent and BComponent derive from a common base class and use the GetComponents API in the baker to get the list of components, then search your current authoring component in the list and find the index.
This example is a bit theoretical. If you have a concrete problem, perhaps it would be easier if you post a code snippet and explain in more detail what you’re trying to achieve.
Any update on when this feature could will become available?
What if I want to be able to add components to the sub entities created when a MeshRenderer has a mesh with multiple submeshes?
For example:
MyRootObject [Contains MeshRenderer with 2 submeshes]
This bakes into:
Root Entity (MyRootObject) [without any rendering]
If I want to apply a component to the entity/entities that renders the submeshes in MyRootObject, I don’t see I way with bakers or post bake systems to archive this? There is no way to distinguish child entity 1, 2, or 3 even though they originates from different GameObject.
If I add some component to the entity that comes from GetEntity(MyRootObject); (would be Root Entity). Later in a post bake system I can look for that and then maybe add components to the children, but Child Entity 3 will be included in that logic and that would be an error.
Am I missing something here?
Edit, I realized I can tag all entities that I can access in the baking tool, and then in post bake filter out and see what is new and correlate that to figure it out. But that seems a bit hacky or complex for how simple the original problem is.
Is this ComponentAuthoring<> available yet? I just spent a few hours trying to make my own base Baker that would automate baking of an IComponentData struct but then realized Bakers don’t work on MonoBehaviours with generic types