Goal
Use the new TransformAspect.LookAt to look at an other entity Position using a ComponentLookup in a IJobEntity, eg.:
public struct HunterBehavior : IComponentData
{
public Entity TargetEntity;
}
public partial struct DemoJob : IJobEntity
{
[ReadOnly] public ComponentLookup<Translation> getTranslation;
public void Execute(ref TransformAspect transformAspect, ref HunterBehavior hunter)
{
var targetPosition = getTranslation[hunter.TargetEntity];
transformAspect.LookAt(targetPosition.Value);
}
}
public partial class DemoSystem : SystemBase
{
protected override void OnUpdate()
{
var getTranslation = this.GetComponentLookup<Translation>(isReadOnly: true);
this.Dependency = new DemoJob { getTranslation = getTranslation }.Schedule(this.Dependency);
}
}
Issue
The IJobEntity autogenerated code above generate the following error when trying to use a ComponentLookup that use of of the component included by the aspect:
Before converting to the aspect I could. The reason is that I could have a read-only translation and a writable rotation.
In the case of using a look at, I want to update the rotation only while seeking translation of other entities.
The workaround is acceptable in my case, so maybe it’s not a bug, but then a feature request. The aspect is nice, but it’s an all or nothing on the read / writes. It would be nice to be able to disable safety checks (like for the native containers) if we want to use the aspect while the safety checks at compile time think it’s unsafe.
Thank you for the info, I missed the part where the lookup on aspect where on a different model (TransformAspect.Lookup VS state.GetComponentLookup / state.GetBufferLookup). It may come an handy in the future for that part. Still think it would be nice to have the same API for discoverability (eg.: state.GetAspectLookup)
As for the example, that’s nice to be able to use the lookup directly inside an ISystem, but it still fail with the same erreur when trying to use in an IJobEntity, eg.:
public struct HunterBehavior : IComponentData
{
public Entity TargetEntity;
}
public partial struct DemoJob : IJobEntity
{
[ReadOnly] public TransformAspect.Lookup _transformLookup;
public void Execute(ref TransformAspect transform, ref HunterBehavior hunter)
{
var targetPosition = _transformLookup[hunter.TargetEntity];
transform.LookAt(targetPosition.Position);
}
}
public partial struct DemoSystem : ISystem
{
private TransformAspect.Lookup _transformLookup;
public void OnCreate(ref SystemState state)
{
_transformLookup = new TransformAspect.Lookup(ref state, isReadOnly: true);
}
public void OnDestroy(ref SystemState state)
{
}
public void OnUpdate(ref SystemState state)
{
_transformLookup.Update(ref state);
state.Dependency = new DemoJob { _transformLookup = _transformLookup }.Schedule(state.Dependency);
}
}
foreach in ISystem have many limitations at the moment, mainly the one where it can only run on the main thread. In my real scenarios, I have different jobs. Which would mean I would had to either all the other jobs to be inside the system.
At least, I have decent workarounds in different scenarios, but it would be nice to be able to have something that work more straightforward with IJobEntity.
The TransformAspect.Lookup was a good track to follow. Adding the the [NativeDisableContainerSafetyRestriction] on the TransformAspect.Lookup of the IJobEntity works. So as long as you know that it can’t have side effects in your situation, this should be good.
public partial struct DemoJob : IJobEntity
{
[NativeDisableContainerSafetyRestriction]
[ReadOnly] public TransformAspect.Lookup _transformLookup;
public void Execute(ref TransformAspect transform, ref HunterBehavior hunter)
{
var targetPosition = _transformLookup[hunter.TargetEntity];
transform.LookAt(targetPosition.Position);
}
}
So this allow to use the TransformAspect as the lookup when updating it in a IJobEntity.Execute ref parameter with the less compromises.
Yes it works and I do not need the [NativeDisableContainerSafetyRestriction], so I think it’s the best solution at the moment. It would be nice to be able to pass a ReadOnly container variant, but at least with this solution I have the advantages of being able to keep the same architecture with almost no code changes.