Documentation (https://docs.unity3d.com/2019.2/Documentation/ScriptReference/RaycastCommand.html) says:
If maxHits is larger than the actual number of results for the command the result buffer will contain some invalid results which did not hit anything. The first invalid result is identified by the collider being null. The second and later invalid results are not written to by the raycast command so their colliders are not guaranteed to be null. When iterating over the results the loop should stop when the first invalid result is found.
Soo, having
new RaycastCommand(from, direction, 4);
RaycastHit
is a struct
type thus itself can never be null
. So as the docs says
The first invalid result is identified by the collider being
null
.
NOTE: The order of the (optional) parameters in the constructor if not explicitly named is
new RaycastCommand(Vector3 from, Vector3 direction, float distance, int layerMask, int maxHits);
and their default values are
distance
= float.MaxValue
layerMask
= -5
maxHits
= 1
Again in words: The default value for maxHits
is 1
!
Unfortunately this is not visible in the docs but your IDE should reveal that.
Knowing this now you can see that your current example
new RaycastCommand(from, direction, 4);
actually says: The maximum distance of the ray is 4
but still allows only 1
single hit!
If you rather wanted to have 4
possible hits you have to call it as
new RaycastCommand(from, direction, maxHits: 4);
now if you call it like this a buffer with exactly 4
RaycastHit
entries will be created, no matter how many objects are hit or if any at all.
Then nothing was hit at all if
results[0].collider == null
and since unfortunately
The second and later invalid results are not written to by the raycast command so their colliders are not guaranteed to be
null
.
you would have to filter them e.g. like
var validResults = new List<RaycastHit>();
foreach(var r in results)
{
if(r.collider == null) break;
validResults.Add(r);
}
Then you could further also sort them to "nearest first" using Linq like e.g.
using System.Linq;
...
var orderedResults = validResults.OrderBy(r=>r.distance).ToList();
// Which is basically a shorthand for something like the following
// not sure though how Linq does it internally, I hope it does something more efficient ^^
var orderedResults = new List<RaycastHit>();
foreach(var r in validResults)
{
for(int i = 0; i < orderedResults.Count; i ++)
{
if(orderedResults[i].distance <= r.distance)
{
orderesResult.Insert(i + 1, r);
break;
}
}
}