Search Unity

RaycastCommand returns 1st hit only regardless of the value assigned to the `maxHit` parameter!

Discussion in 'Entity Component System' started by Backer_Sultan, Sep 9, 2019.

  1. Backer_Sultan

    Backer_Sultan

    Joined:
    Nov 5, 2018
    Posts:
    6
    RaycastCommand has a parameter called `maxHits` and descriped as: The maximum number of Colliders the ray can hit. (https://docs.unity3d.com/ScriptReference/RaycastCommand.html)

    The thing is that it never hits more than one object regardless of the number you pass to the `maxHits` parameter.

    According to the description: The result for a command at index N in the command buffer will be stored at index N * maxHits in the results buffer.

    According to this description, if I write the following code:
    ```
    var results = new NativeArray<RaycastHit>(6, Allocator.Temp);

    var commands = new NativeArray<RaycastCommand>(2, Allocator.Temp);

    // Set the data of the first command
    Vector3 origin = Vector3.forward * -10;
    Vector3 direction = Vector3.forward;

    commands[0] = new RaycastCommand(origin, direction, maxHits: 3);
    commands[1] = new RaycastCommand(origin, direction, maxHits: 2);
    ```
    After the job is complete, the results array should look like this:
    results[0] is first hit from first command
    results[1] is second hit from first command
    results[2] is third hit from first command
    results[4] is first hit form second command
    results[5] is second hit from second command.


    The actual output is quite different. It's actually:
    results[0] is first hit from first command
    results[1] is second hit from first command
    results[2..5] memory garbage as `results[2].collider = null` is true.

    Am I missing something here or is it really not working as it's supposed to?
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
  3. Backer_Sultan

    Backer_Sultan

    Joined:
    Nov 5, 2018
    Posts:
    6
    @eizenhorn so the documentation is not correct. They should probably reflect what the command does more clearly.
     
  4. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    You could implement your own version of raycast with multiple hits. Do a normal raycast, and when it hits something, set the start to where it hit plus a small dx in the direction of the original raycast. Keep doing this until you either reach the end of the original raycast or the final raycast does not hit anything. This is far less efficient than a theoretical max hits raycast, but it will work in the meantime

    Edit: consider using Unity.Physics' version of raycast. It can be used inside of a job instead of being a separate atomic job itself like RaycastCommand, allowing for more complex workloads
     
    Deleted User likes this.
  5. HarryCodder

    HarryCodder

    Joined:
    Feb 20, 2015
    Posts:
    84
    This is not a documentation problem. It's an API problem.
    Why is there a maxHits parameter on RaycastCommand if a raycast command cannot return more that one hit ?
     
    Darkgaze likes this.
  6. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    If this bothers you, try asking why SpherecastCommand has maxHits field and its internal.
    If constructor is not used - its zero, and will cause no hits to be returned at all.

    Because Unity. ¯\_(ツ)_/¯
     
    Last edited: Apr 9, 2021
    apkdev likes this.
  7. HarryCodder

    HarryCodder

    Joined:
    Feb 20, 2015
    Posts:
    84
    Just out of curiosity, I tried chaining raycast command jobs so that a raycast command would use the result of the previous raycast command for the same ray as a new starting point.
    Technically it works but it also takes more that double the time needed by Physics.RaycastNonAlloc to do the same job.

    I've not tried to call Physics methods inside of a job like @Abbrew suggested, my understanding was that this was not possible.

    EDIT: Yeah, it's not possible to use the Physics API outside of the main thread.
     
    Last edited: Apr 10, 2021
  8. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    RaycastCommand is deprecated. Use the new CollisionWorld API instead, that version allows you to check for multiple hits
     
  9. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Its a completely different thing, since Unity.Physics is a separate physics engine.

    And no, RaycastCommand is not deprecated. And probably wont be in closest 5-10 years.
     
    Anthiese and MNNoxMortem like this.
  10. HarryCodder

    HarryCodder

    Joined:
    Feb 20, 2015
    Posts:
    84
    xVergilx likes this.
  11. Darkgaze

    Darkgaze

    Joined:
    Apr 3, 2017
    Posts:
    397
    Still 2021. "As stated in an identical case 1041352, this behaviour is by design. Scripting API is being updated."

    Oh lord...

    Thanks for the github
     
  12. Darkgaze

    Darkgaze

    Joined:
    Apr 3, 2017
    Posts:
    397
    Ok. Apart from the code from @cerea1 (thanks a lot!!) I ended up rewriting it again to make it similar to the RaycastCommand.ScheduleBatch method. But this time using much less memory, and improved efficiency, using just one job and reusing data structs.

    It's as easy as adding the script to your project and calling:
    RaycastCommandMultihit.ScheduleBatch(...) and it will return the correct results.

    I created a gumroad pack as I generally do for these kind of complicated stuff that I need to upload.
    You can download the script and use it freely. All the information is here:

    https://lidiamartinez.gumroad.com/l/wKyFk