DOTS [UpdateInGroup(typeof(LateSimulationSystemGroup))] Bug?

Just had a weird bug where If I add the projectile spawner to the LateSimulationSystemGroup the Entity is positioned wrong for a single frame from where it’s been set?

Is this a known issue or something that has a reason I that doesn’t seem to be documented

[UpdateInGroup(typeof(LateSimulationSystemGroup))]
partial struct BulletSpawnerSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (RefRW<BulletSpawner> bulletSpawner in SystemAPI.Query<RefRW<BulletSpawner>>().WithAll<PlayerOwner>())
        {
            float3 aimPosition = Player.Instance.WeaponsManager.AimPosition;
            float3 moveDir = Player.Instance.WeaponsManager.AimDirection;
            
            Entity bulletEntity = state.EntityManager.Instantiate(bulletSpawner.ValueRO.bulletEntity);
            
            RefRW<LocalTransform> bulletLocalTransform = SystemAPI.GetComponentRW<LocalTransform>(bulletEntity);
            bulletLocalTransform.ValueRW.Position = aimPosition;
            bulletLocalTransform.ValueRW.Rotation = quaternion.LookRotation(moveDir, math.up());
            
            RefRW<Bullet> bullet = SystemAPI.GetComponentRW<Bullet>(bulletEntity);
            bullet.ValueRW.direction = moveDir;
            bullet.ValueRW.startPosition = bulletLocalTransform.ValueRO.Position;
        }
    }
}

The above works fine, it’s only when it’s added to the LateSimulationSystemGroup it happens, If anyone knows why and could let me know it would be much appreciated.

You’re not setting the LocalToWorld value, which is what’s used for rendering. This gets updated within TransformSystemGroup which runs in the normal (non-OrderFirst/OrderLast) part of SimulationSystemGroup. Configure the LocalToWorld value on creation if you want to avoid the issue.

Thanks, But I’m not sure I understand, the position being set is WorldPosition on the Entities root LocalTransform?

Quick Google didn’t yield any info on adding a world relative position on instantiation?

Entities don’t have an inherent concept of “position” like you see in GameObjects’ Transform component. There is a transform mechanism in the Entities package that allows for storing (transform components) and computing (transform systems) transform data, but you have options as to which components are used. Your code shows LocalTransform, but more likely than not, the entity also has LocalToWorld.

The idea is that LocalToWorld (allows for affine transformations) is used for Entities Graphics, and is required for renderable (see TransformUsageFlags.Renderable) entities as its value is read to determine where an object is rendered, not LocalTransform. LocalToWorld can also be used for static physics bodies. LocalTransform (limited transform expressiveness compared to LocalToWorld) is used for dynamic and also static physics bodies. Entities can have one or both depending on what the feature you’re using needs.

When LocalTransform is present, LocalToWorld will be computed from various things including the LocalTransform value, unless there’s other components with [WriteGroup(typeof(LocalToWorld))] present which indicates your systems will handle setting up LocalToWorld. The LocalToWorld value is normally computed once per frame as defined in my previous message.

If you need an object to be immediately ready to be rendered at the position you want and you haven’t made your system update before the TransformSystemGroup where it would compute a value for LocalToWorld, you need to make sure the LocalToWorld itself has the right transformation in addition to your LocalTransform, i.e. set up both components after you instantiate the entity. Assuming you’re not making use of PostTransformMatrix, the easy thing to do would to be to use LocalTransform.ToMatrix to get a 4x4 transformation matrix that represents the same transformation as your LocalTransform.

There’s details about the transform system in Entities in this section of the Entities docs.

1 Like

That makes sense & is very much needed information going forward.

Thank you for taking the time to give a detailed explanation!