Does a Physics.OverlapSphere persist once drawn?

I'm using an OverlapSphere to detect Collectables around my player. I've noticed that after a few seconds, the list of Collectables (collectablesInRange) becomes erratic, and I'm wondering if I'm accidentally drawing multiple OverlapSpheres that are conflicting with each other. I'm not completely sure how they work, and I haven't seen any good videos or anything in the docs to help me further. It's been a few days now, so I'm hoping someone here can point me in the right direction.

This gif (@imgur) shows the list become erratic in action. The framerate is low, but you can still see how it gets worse as time goes.

This is the essential code used to replicate the issue. I'm considering just creating a SphereCollider and using OnTriggerEnter/Exit methods, but I'd like to understand what's happening here if I can. If one of you could shed some light, I'd really appreciate it!

using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Inventory { public class PickUpRadius : MonoBehaviour { [SerializeField] private float detectionRadius; [SerializeField] private List<Collectable> collectablesInRange = new (); private bool _runDetection; private void Awake() => _runDetection = true; private void Update() { if (_runDetection) DetectCollectables(); else StartCoroutine(DetectionCooldown()); } private void DetectCollectables() { var hits = new Collider[20]; Physics.OverlapSphereNonAlloc(transform.position, detectionRadius, hits, LayerMask.GetMask("Collectable")); collectablesInRange = (from hit in hits where hit != null select hit.GetComponent<Collectable>()).ToList(); _runDetection = false; } private IEnumerator DetectionCooldown() { yield return new WaitForSeconds(0.1f); _runDetection = true; } private void OnDrawGizmosSelected() { Gizmos.color = new Color32(100, 255, 100, 100); Gizmos.DrawWireSphere(transform.position, detectionRadius); } } } 
0

1 Answer

To solve this problem you need to organize the code, consider that when you use IEnumerator to determine the Interval you will no longer need to Update. So I deleted Update and _runDetection in the following code and organize system like below.

public LayerMask collectable; // Add collectable layer here private IEnumerator Detection() { while (true) { collectablesInRange = Physics.OverlapSphere(transform.position, detectionRadius, collectable.value) .Select(c => c.GetComponent<Collectable>()).OfType<Collectable>().ToList(); yield return new WaitForSeconds(0.1f); } } 

In the next step, all you have to do is call this method in the Awake function.

private void Awake() => StartCoroutine(Detection()); 

By modifying this command, you can receive them nonAllocated. This worked well in my unity.

collectablesInRange = hits.Select(h => h?.GetComponent<Collectable>()).OfType<Collectable>().ToList(); 
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like