Revisiting RaycastAll vs. RaycastNonAlloc

I was a bit unsatisfied with the answer to the question earlier about using RaycastAll vs. RaycastNonAlloc so I wanted to discuss this further.

The case here is every frame we want to raycast and then sort the results by distance order.

Using the presented solution, there is an allocation by RaycastAll to create the array of RaycastHit objects and then another in RaycastAllSorted to create the distance array. It fills the need but those allocations, which will become garbage once we exit InteractWithComponent, will add up.

If we instead considered using RaycastNonAlloc, we could avoid these allocations altogether. Rather than allocate two arrays every frame that get immediately discarded, we can allocate two reasonably sized arrays as class-level fields and reuse them. This avoids the allocations and garbage on every frame that the above solution suffers from. ‘Reasonably sized’ can be fairly large to avoid any missed objects and then possibly tuned later.

I see there was also a post that built an interesting utility class that ultimately uses RaycastNonAlloc. Or, that’s a bit much, one might simply modify Sam’s solution to use RaycastNonAlloc directly.

1 Like

The garbage from RaycastAll every frame is definitely not insignificant, and is only mitigated by the fact that we’re only doing it once per frame. While I didn’t see a major performance hit compared to @Brandon_Richards’s utility class in PlayerController, I once got the silly idea of using Physics.RaycastAll() with enemies when they are within range of the player to determine if they can see the player. It was a train wreck. There was substantive improvement with NonAlloc.

I recommend using Brandon’s solution out of the box rather than adapting PlayerController to the PhysicsNonAlloc directly.

2 Likes

Thanks Brian. I personally implemented a variation of Sam’s solution and later found @Brandon_Richards’ solution which I really like and will probably take advantage of in the future.

I really appreciate you bubbling this up.

There’s a simple subset of Brandon’s code that everyone can adopt and I think gives you a lot of benefit. So long as you’re only Raycasting 1-2x per frame, the layermask alone gives you a nice FPS boost, especially when you’re moving the mouse around. I have one layermask for my terrain and a separate one for my combat /interactables (character, pickups). Very easy to adapt the existing solution.

e.g.

RaycastHit[] hits = Physics.RaycastAll(GetMouseRay(), float.MaxValue, interactableLayerMask);

bool hasHit = Physics.Raycast(GetMouseRay(), out RaycastHit hit, terrainLayerMask);

I set the layermask with [SerializeField]. Then create two new layers and set your terrain game object with the terrain layer and the character and pickup prefabs with the interactable layermask.

1 Like

Privacy & Terms