Search Unity

Resolved ObjectDisposedException: Cannot access a disposed object. When using PhysicsWorld.CastRay().

Discussion in 'Physics for ECS' started by Waka-Takaki, Dec 25, 2021.

  1. Waka-Takaki

    Waka-Takaki

    Joined:
    Jan 19, 2014
    Posts:
    27
    Hi all,

    Can someone point out the issue with my code here please. I'm getting this error when I try to perform a raycast from the mouse screen position:

    Code (CSharp):
    1. ObjectDisposedException: Cannot access a disposed object.
    2. Object name: 'The NativeArray has been disposed, it is not allowed to access it'.
    I have a PlayerInputSystem that is used to provide input data to entities that need it.
    In
    OnCreate()
    I get the physics world:
    Code (CSharp):
    1. physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld;
    In
    OnUpdate()
    I'm doing this:
    Code (CSharp):
    1. Vector2 mousePosition = playerActions.MousePosition.ReadValue<Vector2>();
    2. float3 raycastHitPoint = RaycastMousePosition(mousePosition);
    I also get some other inputs, and then I have an Entities.ForEach() and update my input data component to pass this data to the entities.

    And here is the RaycastMousePosition method:
    Code (CSharp):
    1.     private float3 RaycastMousePosition(Vector2 mousePosition)
    2.     {
    3.         UnityEngine.Ray mouseRay = Camera.main.ScreenPointToRay(mousePosition);
    4.         RaycastInput mouseRaycast = new RaycastInput
    5.         {
    6.             Start = mouseRay.origin,
    7.             End = mouseRay.GetPoint(RAYCAST_DISTANCE),
    8.             Filter = CollisionFilter.Default
    9.         };
    10.  
    11.         if (physicsWorld.CastRay(mouseRaycast, out Unity.Physics.RaycastHit raycastHit))
    12.         {
    13.             return raycastHit.Position;
    14.         }
    15.  
    16.         return float3.zero;
    17.     }
    The error is not very descriptive, but I can comment out the raycast and the error disappears. It seems that my physicsWorld is disposed at this point. Is there something I am missing?
     
    Joyixir likes this.
  2. Waka-Takaki

    Waka-Takaki

    Joined:
    Jan 19, 2014
    Posts:
    27
    Unity version: 2020.3.19f1
    Unity Physics version: 0.6.0-preview.3
    Entities version: 0.17.0-preview.42
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Have you got the physics dependency handle?
     
  4. Waka-Takaki

    Waka-Takaki

    Joined:
    Jan 19, 2014
    Posts:
    27
    I haven't specifically applied any dependencies. I didn't think you had to add manual dependencies when extending
    SystemBase 
    and adding code in OnUpdate(). I wondered whether it is to do with incorrect UpdateInGroup/After/Before attributes. Here is the full system:

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3. using Unity.Physics;
    4. using Unity.Physics.Systems;
    5. using Unity.Mathematics;
    6.  
    7. [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    8. [UpdateAfter(typeof(ExportPhysicsWorld))]
    9. [UpdateBefore(typeof(EndFramePhysicsSystem))]
    10. public class PlayerInputSystem : SystemBase
    11. {
    12.     private Input input;
    13.     private Input.PlayerActions playerActions;
    14.     private PhysicsWorld physicsWorld;
    15.  
    16.     private float RAYCAST_DISTANCE = 100;
    17.  
    18.     protected override void OnCreate()
    19.     {
    20.         input = new Input();
    21.         input.Enable();
    22.         playerActions = input.Player;
    23.         physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld;
    24.     }
    25.  
    26.     protected override void OnUpdate()
    27.     {
    28.         float horizontal = playerActions.Horizontal.ReadValue<float>();
    29.         float vertical = playerActions.Vertical.ReadValue<float>();
    30.         Vector2 mouseDelta = playerActions.MouseDelta.ReadValue<Vector2>();
    31.         Vector2 mousePosition = playerActions.MousePosition.ReadValue<Vector2>();
    32.  
    33.         // playerActions.Action.triggered is broken!
    34.         // Use playerActions.Action.ReadValue<float>() != 0 ? true : false; for bools instead
    35.         bool jump = playerActions.Jump.ReadValue<float>() != 0 ? true : false;
    36.         bool orient = playerActions.Orient.ReadValue<float>() != 0 ? true : false;
    37.         bool mouseLook = playerActions.MouseLook.ReadValue<float>() != 0 ? true : false;
    38.  
    39.         float3 raycastHitPoint = RaycastMousePosition(mousePosition);
    40.  
    41.         Entities
    42.             .ForEach(
    43.             (ref PlayerInputData inputData) =>
    44.             {
    45.                 inputData.horizontal = horizontal;
    46.                 inputData.vertical = vertical;
    47.                 inputData.jump = jump;
    48.                 inputData.orient = orient;
    49.                 inputData.mouseLook = mouseLook;
    50.                 inputData.mouseDelta = mouseDelta;
    51.                 inputData.mouseRayHitPoint = raycastHitPoint;
    52.             }).Schedule();
    53.     }
    54.  
    55.     private float3 RaycastMousePosition(Vector2 mousePosition)
    56.     {
    57.         UnityEngine.Ray mouseRay = Camera.main.ScreenPointToRay(mousePosition);
    58.         RaycastInput mouseRaycast = new RaycastInput
    59.         {
    60.             Start = mouseRay.origin,
    61.             End = mouseRay.GetPoint(RAYCAST_DISTANCE),
    62.             Filter = CollisionFilter.Default
    63.         };
    64.  
    65.         if (physicsWorld.CastRay(mouseRaycast, out Unity.Physics.RaycastHit raycastHit))
    66.         {
    67.             return raycastHit.Position;
    68.         }
    69.  
    70.         return float3.zero;
    71.     }
    72. }
    73.  
     
  5. Waka-Takaki

    Waka-Takaki

    Joined:
    Jan 19, 2014
    Posts:
    27
    I have manged to solve the issue. The problem is that I was taking a reference to the PhysicsWorld in OnCreate(), but I need to get a new PhysicsWorld each time I need to cast.

    Here are the changes:
    Code (CSharp):
    1.     private BuildPhysicsWorld buildPhysicsWorld;
    2.  
    3.     // ... etc.
    4.  
    5.     protected override void OnCreate()
    6.     {
    7.         buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    8.  
    9.         // ... etc.
    10.     }
    11.  
    And the changes in my
    RaycastMousePosition()
    method:
    Code (CSharp):
    1. private float3 RaycastMousePosition(Vector2 mousePosition)
    2.     {
    3.         CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
    4.  
    5.         // ... etc.
    6.  
    7.         if (collisionWorld.CastRay(mouseRaycast, out Unity.Physics.RaycastHit raycastHit))
    8.         {
    9.             return raycastHit.Position;
    10.         }
    11.  
    12.         return float3.zero;
    13.     }
    I also made some other changes that were unrelated to the error. I switched to CollisionWorld, removed unnecessary attributes and added the [AlwaysUpdateSystem] attribute.
     
    Joyixir likes this.