Using JetBrains ReSharper, it warns that using Physics.RaycastNonAlloc is preferred over Physics.RaycastAll. They do the same thing, but RaycastNonAlloc requires passing in a pre-initiallized RaycastHit
array. Unity themselves confirm this is a best practice since it reduces the amount of garbage on the heap.
Working it out, I came up with this InteractWithCombat()
method:
private bool InteractWithCombat()
{
// Raycast through the scene and return 5 hits
var hits = new RaycastHit[5];
int numHits = Physics.RaycastNonAlloc(GetMouseRay(), hits);
// If no hits, then we're done.
if (numHits <= 0) return false;
foreach (RaycastHit hit in hits)
{
if (hit.transform == null) continue; // Does the hit have a transform?
if (hit.transform.GetComponent<CombatTarget>() == null) continue; // Does the hit have a CombatTarget?
var target = hit.transform.GetComponent<CombatTarget>();
// CustomInputNames.Interact == "Interact" in ProjectSettings > Input
if (Input.GetButtonDown(CustomInputNames.Interact))
{
_combatBehavior.Attack(target); // This is initialized in Awake()
}
return true; // If we found a target, we're done evaluating hits.
}
return false; // We didn't find a target, so we're done.
}
You might be wondering about that extra null
check. I am too. Without it and just directly testing that CombatTarget
is not null, I get an Object reference not set to an instance of an Object
error.
I think the answer to simplifying this would be to user layer masking, which can be passed to RaycastNonAlloc
. At that point, I can just skip the null checks and just make sure that numHits > 0
, because nothing that is not a valid target should be on the layer.
Is that the way to go, or is there a better way?