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?
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.
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:
using UnityEngine;
using System.Collections;
public static class References {
static GameObject _player;
static public GameObject player {
get {
//FindWithTag is only called once, to find the player.
if (_player == null) {
_player = GameObject.FindWithTag("Player");
if (_player == null) {
throw new UnityException("Player GameObject could not be found!");
}
}
return _player;
}
}
}
// And then your AI could look something like this:
public class AIController : MonoBehaviour {
public float attackDistanceThreshold = 5f;
void Update() {
DealWithPlayer();
}
void DealWithPlayer(){
GameObject player = References.player;
if (Vector3.Distance(player.transform.position, transform.position) < attackDistanceThreshold) {
Debug.Log ("Now, you look out player. "+name+" is attacking you, and you will rue the day!");
}
}
}
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!
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.
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.
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?