Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feature Request Make Physics2D API compatible with NativeArray

Discussion in 'Physics' started by FaithlessOne, Apr 1, 2023.

  1. FaithlessOne

    FaithlessOne

    Joined:
    Jun 19, 2017
    Posts:
    313
    Feature Request:
    The API of Physics2D currently uses managed types like List<T> or T[] (array) for returning results. For example to be seen here for raycasts:
    I would like to see support for the following native type for returning the results of raycasts, collider casts and so on:
    Also supporting native slice should be considered, but is not required for my desired use case:
    Reason:
    The Physics2D API cannot be "burstified" within ISystem structures used for the Entity Component System (ECS) when using arrays for the API calls. The List<T> or T[] (array) are managed and therefore rejected by Burst. Why would performance be an issue for 2D physics? A use case is the prediction system of Netcode for Entities. As stated in the following article predictions on client-side can be a "substantial overhead each frame" depending on the connection speed:
    "Burstifying" such ECS systems would improve performance. Here is some rudimentary sample code for such a system:

    Code (CSharp):
    1.  
    2.   [DisableAutoCreation]
    3.   [BurstCompile]
    4.   public partial struct MotionSystem : ISystem
    5.   {
    6.     private RaycastHit2D[] raycastUpHits;
    7.     private RaycastHit2D[] raycastDownHits;
    8.     private ContactFilter2D contactFilter;
    9.     private EntityQuery query;
    10.  
    11.     /// <inheritdoc />
    12.     [BurstCompile]
    13.     public void OnCreate(ref SystemState state)
    14.     {
    15.       this.raycastUpHits = new RaycastHit2D[10];
    16.       this.raycastDownHits = new RaycastHit2D[10];
    17.       this.contactFilter = new ContactFilter2D();
    18.       this.contactFilter.NoFilter();
    19.       this.contactFilter.SetLayerMask(LayerMask.GetMask("Platforms"));
    20.  
    21.       var builder = new EntityQueryBuilder(Allocator.Persistent)
    22.         .WithAspect<LogicalUnitAspect>()
    23.         .WithNone<Prefab>();
    24.       this.query = builder.Build(ref state);
    25.     }
    26.  
    27.     /// <inheritdoc />
    28.     [BurstCompile]
    29.     public void OnUpdate(ref SystemState state)
    30.     {
    31.       EntityCommandBuffer commandBuffer = new EntityCommandBuffer(Allocator.Temp);
    32.  
    33.       foreach (var entity in this.query.ToEntityArray(Allocator.Temp))
    34.       {
    35.         var logicalUnitAspect = SystemAPI.GetAspectRO<LogicalUnitAspect>(entity);
    36.         var logicalUnit = logicalUnitAspect.LogicalUnit.ValueRO;
    37.         var unitTransform = logicalUnitAspect.LocalTransform.ValueRO;
    38.  
    39.         var position = unitTransform.Position.ToVector2();
    40.         var hitUpCount = Physics2D.Raycast(position, Vector2.up, this.contactFilter, this.raycastUpHits, 1f);
    41.         var hitDownCount = Physics2D.Raycast(position, Vector2.down, this.contactFilter, this.raycastDownHits, 1f);
    42.  
    43.         if (hitDownCount > 0)
    44.         {
    45.           var firstDownHit = this.raycastDownHits[0];
    46.  
    47.           if (firstDownHit.distance < 0.02f)
    48.           {
    49.             if (hitUpCount > 0)
    50.             {
    51.               var firstUpHit = this.raycastUpHits[0];
    52.               unitTransform.Position = firstUpHit.point.ToFloat3() + new float3(0, 0.01f, 0f);
    53.             }
    54.             else
    55.             {
    56.               unitTransform.Position = firstDownHit.point.ToFloat3() + new float3(0, 0.01f, 0f);
    57.             }
    58.           }
    59.           else
    60.           {
    61.             unitTransform.Position += logicalUnit.Force * SystemAPI.Time.fixedDeltaTime;
    62.             logicalUnit.Force -= new float3(0, 9.81f * SystemAPI.Time.fixedDeltaTime, 0f);
    63.           }
    64.         }
    65.         else
    66.         {
    67.           unitTransform.Position += logicalUnit.Force * SystemAPI.Time.fixedDeltaTime;
    68.           logicalUnit.Force -= new float3(0, 9.81f * SystemAPI.Time.fixedDeltaTime, 0f);
    69.         }
    70.    
    71.         commandBuffer.SetComponent(entity, logicalUnit);
    72.         commandBuffer.SetComponent(entity, unitTransform);
    73.       }
    74.  
    75.       commandBuffer.Playback(state.EntityManager);
    76.     }
    77.   }
    This currently causes the follwing Burst-error:

    Burst error BC1011: Unable to get field My.Game.Scripts.MotionSystem.raycastDownHits because UnityEngine.RaycastHit2D[] is a class type


    Further Note: I am aware of that ECS has its own physics API (package: com.unity.physics). But the physics system is made for 3D. Furthermore I want to implement a collision system on my own because of specific requirements and handling and also don't want to use the full physics simulation of Unity.
     
    Last edited: Apr 1, 2023
    DungDajHjep likes this.