x


Lags because of GameObjectsFindWithTag();

HI!I have script, which works so good without FindClosestEnemies(); function. Here is part of code:

GameObject FindClosestEnemy()
{       
    gos = GameObject.FindGameObjectsWithTag("Player");
    GameObject closest=null;

    for(int i=0;i<100;i++){}    

    float distance = Mathf.Infinity;
    Vector3 position = transform.position;

    foreach(var go in gos){     
        var diff = (go.transform.position-position);
        var curDistance=diff.sqrMagnitude;
        if(curDistance<distance)
        {
            closest=go;
            distance=curDistance;          
        }
    }
}

With this function, i have <15fps, without >200; What Should I do? I think i shoud change this: gos = GameObject.FindGameObjectsWithTag("Player");, but i have not any ideas how to do it. (I make RTS game^ and this cannon's(Turrel) script(part of one)

[Edit by Berenger, code formatting]

more ▼

asked Apr 28 '12 at 09:07 PM

BANNERTM gravatar image

BANNERTM
4 14 15 16

Why is there a for loop there, and why are you using Mathf.Infinity? Just asking, maybe I will understand your code better. How many enemies do you have in your scene?

Apr 28 '12 at 09:19 PM bompi88

Enemies? from 1 to infinity(it's RTS game), as for Mathf.Infinity - i don't know i took this function from offical documentation

Apr 28 '12 at 10:05 PM BANNERTM

are you calling this function every update? maybe you can get the enemy-objects in an variable at awake and update it whenever a player joins your network or disconnects it? It would probably be better?

Apr 28 '12 at 10:14 PM bompi88

Math.Infinity is for a standard "Price is Right" loop. Each new object steps in the winner's circle if it can beat the previous distance by being closer. You start a loop like that by assigning it something anyone can beat -- like how the winner's circle starts saying $0 in the Price is Right.

Since the "winner" here is the smaller distance, you start with it super-high.

Apr 29 '12 at 08:43 AM Owen Reynolds

How to use Awake in C#?

Apr 29 '12 at 11:23 AM BANNERTM
(comments are locked)
10|3000 characters needed characters left

7 answers: sort voted first

I agree your code looks odd.

But why don't you cache the list of players rather then fetching them each time you enter this routine?

more ▼

answered Apr 28 '12 at 10:14 PM

jeffpk gravatar image

jeffpk
16 5 5 8

The code doesn't really look odd except the useless empty for-loop (for(int i=0;i<100;i++){})

Apr 29 '12 at 11:24 AM Bunny83
(comments are locked)
10|3000 characters needed characters left

The best way depends on how many enemies / objects will be there, what's the max-distance and how are they distributed across the map.

  1. Use Physics.OverlapSphere with your max distance to get a list of all objects within the max distance. Make sure you put all units that should be selectable on a seperate unit-layer. Every enemy need to have a collider attached. This function is way faster then any of Unitys search-functions, especially when you have many objects and a max detection distance.
  2. Another way is that each enemy register / unrigisters itself by some kind of static Unit-Manager. This manager always holds an updated list of all units. If the map is really big and you have a lot of enemies (200+), it's better to use the first version.

I know in a lot questions people suggest to use FindGameObjectsWithTag, but keep in mind it has to iterate through all objects so it's quite slow. OverlapSphere uses the physics system which probably uses some kind of space partitioning which minimize the overhead.

Your sorting loop is already in it's optimal form ;)

more ▼

answered Apr 29 '12 at 11:47 AM

Bunny83 gravatar image

Bunny83
45.5k 11 49 207

Just realized that your function doesn't return anything. You should add a return closest; at the end of the function after the foreach-loop.

Apr 29 '12 at 12:40 PM Bunny83
(comments are locked)
10|3000 characters needed characters left

I solved the problem!!!!!!!!!!!!!!!!!!!!!! i just put body of function in update - all works fine!!!

more ▼

answered Apr 29 '12 at 05:30 PM

BANNERTM gravatar image

BANNERTM
4 14 15 16

(comments are locked)
10|3000 characters needed characters left

It certainly better to get the reference to things like player once at the start. Whether its going to make a lot of difference to your routine I don't know.

So do something like:

 private var playerObject: GameOject;

 function Startup()
 {
     playerObject= GameObject.FindGameObjectsWithTag("Player");
 }

 function DoWhatever()
 {

 // You can use "playerObject" instead of doing a find on it

 }

Thats good practice regardless.

more ▼

answered Apr 28 '12 at 10:17 PM

Fabkins gravatar image

Fabkins
675 15 20 26

From performance point of view it'S of course way better, but don't forget that in most RTS games enemies will be added / removed during the game, so you need an updated version of the enemy array.

Apr 29 '12 at 11:27 AM Bunny83
(comments are locked)
10|3000 characters needed characters left

Call it once every second or two. It will even make the enemies look cooler (when a better target comes closer, they'll sometimes take a few shots at the old target before noticing.)

"Easy" way is a counter: if(AIcheck>0) AIcheck--; else { AIcheck=100; // do long loop.

Slightly CPU faster way is a coroutine, called at start, like:

IEnumerator getClosestRunner() {
  // each enemy waits a random amount, so they don't all check same frame:
  yield return new WaitForSeconds(Random.Range(0.0f, 1.5f);
  while(true) {
    getClosest();
    yield return new WaitForSeconds(1.5f);
  }
}

getClosest is what you already have. Maybe it runs GameObject.Find, or uses a predone list. It's split out of the "every 1.5 secs" loop so you can call it when your current target dies, or when you're first spawned.

more ▼

answered Apr 29 '12 at 08:35 AM

Owen Reynolds gravatar image

Owen Reynolds
11.6k 1 7 45

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x2097
x56

asked: Apr 28 '12 at 09:07 PM

Seen: 686 times

Last Updated: Apr 29 '12 at 05:30 PM