Unable to get ECS physics PhysicsVelocity and PhysicsGravityFactor data from outside the object

Hi, I was going through the Physics sample projects given by Unity for ECS, I opened scene 2d1 (trigger scene) and saw how it worked. My curiosity had the better of me and I wanted to create a system just to see the velocity and gravityFactor in the Inspector.

The First logic I made was to add a component called TrackComp so I can find the entity and get the data from its components.

Now, the first attempt I made, I wanted to access the data from ECS and present it on a MonoBehaviour. I went ahead and got a SystemHandle for the system, but how to get a specific Entity in the system got me confused (I am new to the whole ECS accessing thing). This ends me cancelling the approach, but I am adding the script in case someone out there can help me with this as this is what I really want to access.

The Final approach that I was more hopeful about was to make a new System and populate the data in my TrackComp as I can then at least access the data from outside the system as a intermediate step before I access it through some logic in my MonoBehaviour. I wrote the system, I have ensured that my new system runs after FixedStepSimulationSystemGroup in Update but I still see both my fields as having default data.

I am attaching all three scripts where TriggerGravityFactorAuthoring.cs is the default script by Unity.

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Physics;
using Unity.Physics.Systems;
using UnityEngine;
  
public struct TriggerGravityFactor : IComponentData
{
    public float GravityFactor;
    public float DampingFactor;
}
  
public class TriggerGravityFactorAuthoring : MonoBehaviour
{
    public float GravityFactor = 0f;
    public float DampingFactor = 0.9f;
  
    void OnEnable() {}
  
    class TriggerGravityFactorBaker : Baker<TriggerGravityFactorAuthoring>
    {
        public override void Bake(TriggerGravityFactorAuthoring authoring)
        {
            AddComponent(new TriggerGravityFactor()
            {
                GravityFactor = authoring.GravityFactor,
                DampingFactor = authoring.DampingFactor,
            });
        }
    }
}
  
// This system sets the PhysicsGravityFactor of any dynamic body that enters a Trigger Volume.
// A Trigger Volume is defined by a PhysicsShapeAuthoring with the `Is Trigger` flag ticked and a
// TriggerGravityFactor behaviour added.
[RequireMatchingQueriesForUpdate]
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateAfter(typeof(PhysicsSystemGroup))]
[BurstCompile]
public partial struct TriggerGravitySystem : ISystem
{
    ComponentDataHandles m_Handles;
  
    struct ComponentDataHandles
    {
        public ComponentLookup<TriggerGravityFactor> TriggerGravityFactorGroup; // component with gravity and dampning factor created by user
        public ComponentLookup<PhysicsGravityFactor> PhysicsGravityFactorGroup; // The factor by which gravity is applied in physics step to each PhysicsBody(rigidbody) - https://docs.unity3d.com/Packages/com.unity.physics@1.0/api/Unity.Physics.PhysicsGravityFactor.html?q=PhysicsGravityFactor
        public ComponentLookup<PhysicsVelocity> PhysicsVelocityGroup; // the velocity of a rigidbody in simulation - https://docs.unity3d.com/Packages/com.unity.physics@1.0/api/Unity.Physics.PhysicsVelocity.html?q=PhysicsVelocity
  
        public ComponentDataHandles(ref SystemState state)
        {
            // Constructor Sets the data based on SystemState data
            TriggerGravityFactorGroup = state.GetComponentLookup<TriggerGravityFactor>(true);
            PhysicsGravityFactorGroup = state.GetComponentLookup<PhysicsGravityFactor>(false);
            PhysicsVelocityGroup = state.GetComponentLookup<PhysicsVelocity>(false);
        }
  
        // On every update, we update the data stored in the three groups
        public void Update(ref SystemState state)
        {
            TriggerGravityFactorGroup.Update(ref state);
            PhysicsGravityFactorGroup.Update(ref state);
            PhysicsVelocityGroup.Update(ref state);
        }
    }
  
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
        // This system requires data to be present in the Query if we want to run the system.
        state.RequireForUpdate(state.GetEntityQuery(ComponentType.ReadOnly<TriggerGravityFactor>()));
        // https://docs.unity3d.com/Packages/com.unity.entities@1.0/api/Unity.Entities.SystemState.RequireForUpdate.html
        // create a new object to have local reference to all data we needed from SystemState
        m_Handles = new ComponentDataHandles(ref state);
    }
  
    [BurstCompile]
    public void OnDestroy(ref SystemState state)
    {
    }
  
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        // update local data
        m_Handles.Update(ref state);
        // create a new Job which does not run unless the previous Dependencies are completed.
        state.Dependency = new TriggerGravityFactorJob
        {
            TriggerGravityFactorGroup = m_Handles.TriggerGravityFactorGroup,
            PhysicsGravityFactorGroup = m_Handles.PhysicsGravityFactorGroup,
            PhysicsVelocityGroup = m_Handles.PhysicsVelocityGroup,
        }.Schedule(SystemAPI.GetSingleton<SimulationSingleton>(), state.Dependency);
    }
  
    [BurstCompile]
    struct TriggerGravityFactorJob : ITriggerEventsJob
    {
        [ReadOnly] public ComponentLookup<TriggerGravityFactor> TriggerGravityFactorGroup; // user defined component
        public ComponentLookup<PhysicsGravityFactor> PhysicsGravityFactorGroup; // Physics gravity Factor present all over this system at this frame
        public ComponentLookup<PhysicsVelocity> PhysicsVelocityGroup; // the velocity of all rididbody(physicsBody) in system at this frame
  
        public void Execute(TriggerEvent triggerEvent)
        {
            Entity entityA = triggerEvent.EntityA;
            Entity entityB = triggerEvent.EntityB;
  
            bool isBodyATrigger = TriggerGravityFactorGroup.HasComponent(entityA);
            bool isBodyBTrigger = TriggerGravityFactorGroup.HasComponent(entityB);
  
            // Ignoring Triggers with user defined component overlapping other Triggers
            if (isBodyATrigger == isBodyBTrigger)
                return;
  
            bool isBodyADynamic = PhysicsVelocityGroup.HasComponent(entityA);
            bool isBodyBDynamic = PhysicsVelocityGroup.HasComponent(entityB);
  
            // Ignoring overlapping static bodies
            if ((isBodyATrigger && !isBodyBDynamic) || (isBodyBTrigger && !isBodyADynamic))
                return;
  
            var triggerEntity = isBodyATrigger ? entityA : entityB;
            var dynamicEntity = isBodyATrigger ? entityB : entityA;
  
            var triggerGravityComponent = TriggerGravityFactorGroup[triggerEntity];
            // tweak PhysicsGravityFactor
            {
                var component = PhysicsGravityFactorGroup[dynamicEntity];
                component.Value = triggerGravityComponent.GravityFactor;
                PhysicsGravityFactorGroup[dynamicEntity] = component;
            }
            // damp velocity
            {
                var component = PhysicsVelocityGroup[dynamicEntity];
                component.Linear *= triggerGravityComponent.DampingFactor;
                PhysicsVelocityGroup[dynamicEntity] = component;
            }
        }
    }
}

TrackGravityDampning.cs is the MonoBehaviour script which I added in Unity trying to fetch ECS values inside Unity and hit a point that I could not understand how I should approach the problem.

using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;
  
public class TrackGravityDampning : MonoBehaviour
{
    public float currGravity;
    public Vector3 currVelocity;
    private Entity targetEntity = Entity.Null;
    private Entity GetRandomEntity()
    {
        EntityQuery entitiesWithoutGravity = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntityQuery(typeof(TrackComp));
  
        if (entitiesWithoutGravity.CalculateEntityCount() <= 0)
        {
            return Entity.Null ;
        }
  
        NativeArray<Entity> queryNativeArray = entitiesWithoutGravity.ToEntityArray(Unity.Collections.Allocator.Temp);
        return queryNativeArray[0];
    }
  
    private void Start()
    {
        SystemHandle tSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<TriggerGravitySystem>();
        if (tSystem != null)
        {
            Debug.Log("Got the system Hanel");
        }
        //TriggerGravityFactor tSystemBase = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged(typeof(TriggerGravitySystem));
    }
  
    private void LateUpdate()
    {
        if (targetEntity != Entity.Null)
        {
            currGravity = 0f; // need a logic to access PhysicsGravityFactor component of this entity
            currVelocity = Vector3.zero; // need a logic to access PhysicsVelocity's Linear component of this entity
        }
        else
        {
            currGravity = 0f;
            currVelocity = Vector3.zero;
        }
  
        if (Input.GetKeyDown(KeyCode.Space))
        {
            targetEntity = GetRandomEntity();
        }
    }
}

TrackCompAuthoring.cs is the new system I made along with the TrackComp and I still get no data in the Component view of Inspector (runtime) even though my new system runs after Unity’s system.

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Systems;
using UnityEngine;
  
public class TrackCompAuthoring : MonoBehaviour
{
    public GameObject target;
    void OnEnable() {}
}
  
public class TrackCompBaker : Baker<TrackCompAuthoring>
{
    public override void Bake(TrackCompAuthoring authoring)
    {
        AddComponent(new TrackComp()
        {
            targetE = GetEntity(authoring.target)
        }
        );
    }
}
  
public struct TrackComp : IComponentData
{
    public Entity targetE;
    public float gravity;
    public float3 velocity;
}
  
  
public partial class TrackCompSystem : SystemBase
{
    protected override void OnUpdate()
    {
        TrackComp trackComp = SystemAPI.GetSingleton<TrackComp>();
  
        //foreach ((PhysicsVelocity phyVel, PhysicsGravityFactor physicsGravity) in //SystemAPI.Query<PhysicsVelocity, PhysicsGravityFactor>())
        //{
        //    trackComp.gravity = physicsGravity.Value;
        //    trackComp.velocity = phyVel.Linear;
        //}
        trackComp.gravity = EntityManager.GetComponentData<PhysicsGravityFactor>(trackComp.targetE).Value;
        trackComp.velocity = EntityManager.GetComponentData<PhysicsVelocity>(trackComp.targetE).Linear;
    }
}

com.unity.entities 1.0.0-pre.15 comes with dedicated tools for that; you don’t need to write your own here. I suggest you start with Windows / Entities / Hierarchy as it lists all entities in Play Mode. This window has a search bar and writing there c=TriggerGravityFactor will query for all entities with this components for you to inspect their data.

Entities can be split in multiple Worlds (World is like a Scene but for entities) in some cases, so watch for that in the future.

To list entities filtered by system, open WindowsEntitiesSystems window, find and select your system there to see list of queries in the inspector. Clicking a window icon next to query name ( “Query #1”) will open up a window with “Entities” tab; selecting entities there allows you to inspect their data in the Inspector.

Query type defines a search query - it is a filter to find specific type of entities. Many systems define multiple such queries but it should be just a single one ideally (single responsibility for simplicity and clarity).

TrackCompAuthoring.cs

using UnityEngine;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Physics;

// add this component to one of the physics bodies in the sub scene
[RequireComponent(typeof(Unity.Physics.Authoring.PhysicsBodyAuthoring))]
public class TrackCompAuthoring : MonoBehaviour { }
  
public class TrackCompBaker : Baker<TrackCompAuthoring>
{
    public override void Bake(TrackCompAuthoring authoring) => AddComponent(new TrackComp { });
}
  
public struct TrackComp : IComponentData
{
    public float gravity;
    public float3 velocity;
}
  
public partial class TrackCompSystem : SystemBase
{
    protected override void OnUpdate()
    {
        var copyJob = new CopyToTrackCompJob { };
        Dependency = copyJob.ScheduleParallel(Dependency);
    }
  
    [Unity.Burst.BurstCompile]
    partial struct CopyToTrackCompJob : IJobEntity
    {
        public void Execute(ref TrackComp trackComp, in PhysicsVelocity phyVel, in PhysicsGravityFactor physicsGravity)
        {
            trackComp.gravity = physicsGravity.Value;
            trackComp.velocity = phyVel.Linear;
        }
    }
}

TrackGravityDamping.cs

using UnityEngine;
using Unity.Mathematics;
using Unity.Collections;
using Unity.Entities;
using Unity.Physics;
  
public class TrackGravityDamping : MonoBehaviour
{
    [SerializeField] float _gravity;
    [SerializeField] Vector3 _velocity;
    [SerializeField] bool _read = true;
    [SerializeField] bool _write = false;
    EntityManager _entityManager;
    EntityQuery _query;
  
    void Start()
    {
        var world = World.DefaultGameObjectInjectionWorld;
        _entityManager = world.EntityManager;
  
        // this query will search for entities with all 3 component types: 
        _query = _entityManager.CreateEntityQuery(new EntityQueryDesc
        {
            All = new ComponentType[] {
                typeof(TrackComp),
                typeof(PhysicsGravityFactor),
                typeof(PhysicsVelocity)
            }
        });
    }
  
    void FixedUpdate()
    {
        if (_read)
        {
            _query.CompleteDependency();
            foreach (var gravityFactor in _query.ToComponentDataArray<PhysicsGravityFactor>(Allocator.Temp))
                _gravity = gravityFactor.Value;
            foreach (var velocity in _query.ToComponentDataArray<PhysicsVelocity>(Allocator.Temp))
                _velocity = velocity.Linear;
        }
        if (_write)
        {
            _query.CompleteDependency();
            foreach (Entity entity in _query.ToEntityArray(Allocator.Temp))
            {
                _entityManager.SetComponentData(entity, new PhysicsGravityFactor { Value = _gravity });
                _entityManager.SetComponentData(entity, new PhysicsVelocity { Linear = _velocity, Angular = new float3(0, 0, 0) });
            }
        }
    }
}