Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Code and Performances optimization questions

Discussion in 'Scripting' started by esitoinatteso, Jan 12, 2015.

  1. esitoinatteso

    esitoinatteso

    Joined:
    Sep 23, 2013
    Posts:
    26
    Hi chums! Since I'm not a professional programmer, I'm not aware of the best methods to avoid exhausting the machine with useless work... but maybe you know better!

    I'm currently writing the main enemy's script in my prototype, and I'd like to make him smart enough.
    To do that, I'll make him cache the player's position every now and then, and do stuff with that in mind.

    First question is... when would performances drop the most?
    1- if I have 100 enemies on screen looking for your position every 2-3 seconds ( with a Tag call)
    2- if I have 100 enemies updating their cache while the actual Tag call is made just once every 2-3 seconds by an empty game object to which is attached an " overlord" script

    Is there any considerable difference?

    What would be the Top 3 things to keep in mind when trying to lessen the stress of the machine in your opinion?
    I have no clue right now... except maybe for Raycasts called to specific layers ( does that makes a big difference?)

    Plus, another noob question:
    When I toggle the Stats in the editor, how do I read them?
    What are the most important things I should consider when comparing different method's performances?

    Thanks!
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    First one would be more costly because you'd be doing a Find() 100 times versus doing it once. That being said - if the player object doesn't change there's no reason to Find() it again after you Find() it the first time.

    Generally speaking - don't guess about what is causing your game to run poorly. Use the Profiler and tackle the most costly methods in order.
     
    esitoinatteso and angrypenguin like this.
  3. esitoinatteso

    esitoinatteso

    Joined:
    Sep 23, 2013
    Posts:
    26
    Hi KelsoMRK! I've been suspecting that the latter was better, thanks for pointing that out!

    I didn't know about that feature 'cause I'm not using UnityPro, but Profiler sounds awesome... I'll definitely buy it if everything goes as planned!
     
  4. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    In addition: Try to avoid using the static find functions in your gameplay loop. I only use them in Start() or Awake() if I need to connect a lot of objects that cant be done in the editor, or if I need to connect objects that are instantiated at runtime.

    In your case, why not have your enemy AI, or SceneController, or whatever, have a reference to the players location, and every X time interval, your enemy ai can do something with that information?

    Something like so:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public static class References {
    5.  
    6.     static GameObject _player;
    7.     static public GameObject player {
    8.         get {
    9.  
    10.             //FindWithTag is only called once, to find the player.
    11.             if (_player == null) {
    12.                 _player = GameObject.FindWithTag("Player");
    13.  
    14.                 if (_player == null) {
    15.                     throw new UnityException("Player GameObject could not be found!");
    16.                 }
    17.             }
    18.  
    19.             return _player;
    20.  
    21.         }
    22.  
    23.     }
    24.  
    25. }
    26.  
    27. // And then your AI could look something like this:
    28.  
    29. public class AIController : MonoBehaviour {
    30.  
    31.     public float attackDistanceThreshold = 5f;
    32.  
    33.     void Update() {
    34.  
    35.         DealWithPlayer();
    36.  
    37.     }
    38.  
    39.     void DealWithPlayer(){
    40.         GameObject player = References.player;
    41.  
    42.         if (Vector3.Distance(player.transform.position, transform.position) < attackDistanceThreshold) {
    43.             Debug.Log ("Now, you look out player. "+name+" is attacking you, and you will rue the day!");
    44.         }
    45.  
    46.     }
    47.  
    48. }
     
    esitoinatteso likes this.
  5. esitoinatteso

    esitoinatteso

    Joined:
    Sep 23, 2013
    Posts:
    26
    Hi BenZed and thanks for joining this thread!
    Your suggestions seems profitable and I really like the distanceThreshold idea, I'll draw on that to improve my enemies!
     
  6. SevenHams

    SevenHams

    Joined:
    Dec 27, 2012
    Posts:
    67
    If the player is always the same object you absolutely do not need to constantly Find() it. Like was said having a static player reference somewhere is significantly easier on resources. Just assign the player to that and reference it whenever you need. If you do need to change the player then you can point the reference to the new player object.

    If you know the object exists ahead of time it's better to assign the reference ahead of time rather than having it be sought.
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    My top tips for increasing performance. These are approximately in order.
    • Bench mark and profile everything. Using Unity. On the target device.
    • Write code for readability, maintainability and extendibility first. Optimise later. There is no point doing heavy optimisation until you have finished adding features.
    • Avoid heavy processing every frame. This includes Update, OnTriggerStay, FixedUpdate. You definitely need to use these, but there should be very little heavy lifting inside the functions
    • Cache everything. For most applications on most devices CPU cycles are more important then memory space. Once you have a reference to a Component or GameObject then don't let it go. You won't notice the performance impact of GetComponent and Find if you call them occasionally. If you call them every frame they will kill your performance.
    • Do your cheapest checks first. Checking if ammo > 0 is far cheaper then checking if a ray cast can hit. Do your cheapest processing first and bail out if it returns false.
    • Avoid frequent Instantiate and Destroy calls by using object pooling
    • Use properties and coroutines to avoid checking state every frame.
     
  8. esitoinatteso

    esitoinatteso

    Joined:
    Sep 23, 2013
    Posts:
    26
    Hi again! The static reference is a handy trick I've implemented, thanks for the advice!
    The cheapest checks first is something I'll have to remember!

    I've got a question though... I find myself in need of determine the direction of an enemy ( inside his IA script).
    I can't use rigidbody.velocity because I'm moving stuff with code, so that parameter is always 0,0,0.

    I was thinking about caching the previous position every frame. Realistically speaking, the game will have 10 enemies on screen at the same time at most, so I don't think this could be an issue ( but I'd like it to be performance friendly nevertheless).

    By knowing which direction x,y,z an enemy is going, I can Raycast to detect stuff on its path with origins from the proper vertex ( my game is 2d, no rotation ever, and I'm trying to set up this IA ignoring how professionals would do because I learn more this way imho).

    The real question is:
    checking where the enemy is moving every frame ( if it has moved) by comparing its current position.x vs previous.x ( and so on) and then Raycast just the Rays needed to detect things in that direction, would be better than Raycasting every frame from every vertex plainly ignoring the direction it's following? ( meaning 8 rays vs 4 at most)

    I'll try to guess... the first method is better when speaking of performances, am I right?
     
  9. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Stop worrying about the performance cost of 8 raycasts and just make your game instead :)
     
    esitoinatteso and Kiwasi like this.
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    This is very good advice. Build the game first. Optimise once it's done, if you hit performance limits.
     
  11. esitoinatteso

    esitoinatteso

    Joined:
    Sep 23, 2013
    Posts:
    26
    Lol! Ok :p!
    Thanks again pals