Disabling Monobehaviours that are not close to the players

Hi,

I want to make a game in which several (at the moment 2) players each have a tank and have to conquer the other side’s base. I have a lot of buildings in the game that potentially slow it down a lot. So, I wanted to disable all objects that are not close to either player.

The first thing i did was to pool all Monobehaviours in an array when starting up the Game Manager Script (I will move this to Awake() before compiling, but at the moment awake is not started as the game manager already exists in the scene)

m_Scripts = FindObjectsOfType<MonoBehaviour>() as MonoBehaviour[]; //Pool all Scripts on the Map

My tanks are stored in another array in this class and each tank has a component that contains the trigger (a sphere collider I called activationSphere). So within the gameManager on every update of the playcycle, I want to call a function DisableByDistance(MonoBehaviour script) that checks whether the elements of Scripts are outside of the activationSpheres of all tanks. To this end I wrote:

 private void DisableByDistance(MonoBehaviour script) //Disable pooled Monobehaviour "script" if it is not close to any player
    {
        int tankCounter = 0; // Counts the number of tanks NOT close to the Monobehaviour
        for (int i = 0; i < m_Tanks.Length; i++)
        {

            Collider activationSphere = m_Tanks[i].m_Instance.transform.FindChild("ActivationSphere").GetComponent<Collider>();
           //pseudocode:
             If not (activationSphere intersects script.collider) then tankCounter++;
        }
       //pseudocode:
         if (tankCounter==m_Tanks.Length) //i.e. if no tanks are close to the monobehaviour
                 then disable script;
         else
                 enable script;

    }

So, I think that in principle this should work, but I have no clue how to code this. The colliders on the scripts are of different type (should I add specific colliders just for this task to have the same kinds of colliders?) and somehow I cannot access any of the methods OnTrigger… that should be accessible from the collider on the tank.

It would be awesome if someone could help me. I guess for an experienced user, this is a trivial problem,

Thanks a lot!!!

bustee

PS: Please feel free to propose totally different ways to achieve what I want. I am inexperienced and this was the first that came to my mind, so it is probably not very efficient.

PPS: I build this game on top of the Tanks! tutorial for unity beginner, so some of the notation might look familiar (if you did the tutorial).

First of all, monobehaviour is the scripts you write, if you disable it, it won’t work and it certainly wont hide the object

If you want to disable objects far away form the player, consider this first:
if the object is not on screen, unity will disable it (it matters if you have a top-down perspective)
yes, render calls do slow down a game, but not by a lot, i would suggest just simply reducing the tris in your mesh
If you want to disable every object if it gets far away, the update calls could affect the game more than the models
If the center of the ground is far away from you, it will woosh disappear, and you don’t want that

If you really want to disable objects, if they are far away, just do this:

GameObjects disableObjects;

void Start () {
   disableObjects = GameObject.FindGameObjectsWithTag("yourtaggoeshere");
   //this is important, so the important objects wont disappear
}

void FixedUpdate () {
   for (int n = 0; n < disableObjects.Length; n++) {
      if (Vector3.Distance(transform.position, disableObjects[n].transform.position) > "putADistanceHere") {
         disableObjects[n].GetComponent<Renderer>().SetActive(false);
      } else {
         activate it using the same method, I'm lazy
      }
   }
}

Okay, thanks a lot. I just read that the colliders are the bid issue with runtime problems, so I might just try to use your code to disable these. Thanks.

But I will try to not do it at the moment then. I was not aware that objects outside of the camera get disabled, so this might be fine anyhow.

The objects are culled automatically by the engine when not on screen, so there is no need for you to disable their renderer, as the game engine basically does this for you.

sidenote on the reply above:
dont put Getcomponent in a fixedUpdate (or Update, or lateUpdate) loop. Cache what you need in an array or list, and access that directly in an update loop. Otherwise you are destroying your performance.

2 Likes

thanks for the info.

1 Like

You could also look into occlusion culling so that buildings behind other buildings don’t get drawn (even if they’re inside the camera’s range).

Unity can do that.