0
\$\begingroup\$

I was trying to implement an AddExplosionForce-script that was shown in a Unity live training session a few years back. It has out of date calls to rigidbodies because it uses the old gameobject.rigidbody way of accessing them. I tried doing the standard process of

  1. declare a rigidbody,
  2. link it to a GetComponent<>, and
  3. act on the rigidbody through the resulting variable.

However, as shown below, the rigidbodies I need to interact with are used in a foreach loop that goes through an array of colliders. How do I access the rigidbody of each collider in the array as it is used? (and if that is the wrong approach, please let me know). Will using GetComponent in that way harm performance?

Here is the original script from the video, w/ minor comments. I have left out my botched attempt at fixing it for the sake of brevity.

public class MassExplosionScriptOriginal : MonoBehaviour
{
    public float force;
    public float radius;

    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, 100))
            {
                Collider[] colliders = Physics.OverlapSphere(hit.point, radius);
                // overlap sphere collects all the colliders that it overlaps 
                // with/touches. From  the point you click (hit.point), create a sphere of the 
                // given radius (radius),collect all the colliders from the objects overlapped, 
                // and then return them with the array colliders. 

                foreach (Collider c in colliders) // declare a variable to hold a //collider
                {
                    if (c.rigidbody == null) continue;
                    // the if statement clause says that, if the collider touched //has no rigidbody, then skip it and continue on. 

                    c.rigidbody.AddExplosionForce(force, hit.point, radius, 1, ForceMode.Impulse);
                    // Whenever you click, this script will collect all the  
                    // colliders and then apply the explosive force to them. It works on everything
                }
            }
        }
    }
} 
\$\endgroup\$
2
\$\begingroup\$

I would simply use GetComponent in your foreach as you're doing and assign a variable, like so:

Collider[] colliders = Physics.OverlapSphere(hit.point, radius);
foreach (Collider c in colliders)
{
    Rigidbody r = c.GetComponent<Rigidbody>()
    if (r == null) continue;

    r.AddExplosionForce(force, hit.point, radius, 1, ForceMode.Impulse);
}

Depending on the number of objects returned by OverlapSphere and also the expense of OverlapSphere itself, performance will vary. But unless you're actually seeing performance issues or plan on dealing with hundreds of objects each frame, I wouldn't worry too much about it.

If it does become a problem or you are likely to deal with a lot of objects, you may find that moving the procedure to a Co-Routine rather than removing your GetComponent would be beneficial (executing at, say once every 250ms). You may also see some minor performance gain from changing your foreach to a for if there number of objects you expect to interact with is large.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.