1 Unit on the Scene, Check my FPS after I disable this one script that makes the Health bar face the Camera. Keep in mind this is suppose to be an RTS game… so Imagine many units with this script
With Script
Without Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthBarRotation : MonoBehaviour
{
void Start()
{
SelectionManager.myunitsUI.Add(this);
}
private void LateUpdate()
{
transform.LookAt(Camera.main.transform); //Face the camera always
transform.Rotate(0, 180, 0); // Otherwise its Like Lookign at a Mirror!
}
}
So I changed it so that the Health Bar, Only looks at the camera when the units are selected. and the FPS is improved. but ofc the fps drops once they are selected
Well, the biggest thing is that GetComponent() calls are relatively expensive, and best-practice is that you shouldn’t be calling that every frame unless there’s no other/better way. In most cases, you’ll want to cache the collection of components during Start() or Awake(), and iterate over that collection.
But the better recommendation is that you should learn to profile the game and see exactly what is taking up the time. Attach the profile, turn on deep profiling, then see what’s actually taking up time. Note that with the profile attached your framerates will plummet, but you’ll be able to gauge relative differences. In this case, I’d assume GetComponentInChildren is causing the bulk of your performance issues, but who knows.
Thank you for reply, I have only been programming for just over 2 months, Would be great if you can explain to me how to “cache everything”. Atm, this last version of the script is placed on my GameMaster not the Units, its iterating though a list of “Selected units” that way I do less work, because only selected units Health Bars are shown atm. so how do I “catch” something inside a dynamic list?
A different, approach is to have two different lists - one for selected units, one for their health bars, and then just loop though the selected health bars instead. That requires having the two lists be in sync, but if you do what I suggested above, that’s not hard:
// add unit to selection:
SelectedUnitList.Add(unit);
SelectedUnitHealthbarList.Add(unit.HealthBarRotation);
// remove units from selection:
SelectedUnitList.Remove(unit);
SelectedUnitHealthbarList.Remove(unit.HealthBarRotation);
The biggest cost still in the script is Camera.main. It’s stupidly slow (it looks through the entire scene for a camera object tagged “main”). Assign it in Awake.
Secondly, just looking at the code and looking at the fps isn’t going to help much if you want to do serious optimization. You need to learn to use the profiler and understand it’s results.
Two reasons to use two lists:
More important: It’d be a bit easier to read - the code rotating the health bars wouldn’t have to worry about anything else than the health bars.
Less important/probably not noticeable: One less indirection step. The health bar and the unit isn’t necessarily in the same place in memory, so going through a reference to the health bar instead of a reference to the unit might be slightly better.
If you want to improve the method more, you should calculate the final rotation and set it instead of updating the rotation twice. Preferably you’d change the health bar so it doesn’t have to be rotated 180 degrees after looking at the camera, but in the meantime you could do:
var cameraPos = cameraTransform.position;
var rotationAdjustment = Quaternion.Euler(0f, 180f, 0f);
foreach (Unit myUnit in SelectionManager.SelectedUnitList)
{
var healthBarTransform = myUnit.healthBarReference.transform;
healthBarTransform.rotation = rotationAdjustment * Quaternion.LookRotation(cameraPos - healthBarTransform.position);
}
Works in two steps, this is as best as I can make it, not sure if I can make it in one step. or even if it will have higher performance as a result. Thanks a lot, came a long way
public float updateRate = 0.05f;
public GameObject cameraPos;
Vector3 cameraPosVectror;
Quaternion rotationAdjustment;
Transform healthBarTransform;
// Start is called before the first frame update
void Start()
{
rotationAdjustment = Quaternion.Euler(0f, 180f, 0f);
InvokeRepeating("slowHpBarRotation", 3, updateRate);
}
private void slowHpBarRotation()
{
cameraPosVectror = cameraPos.gameObject.transform.position;
foreach (Unit myUnit in SelectionManager.SelectedUnitList)
{
healthBarTransform = myUnit.healthBarReference.transform;
healthBarTransform.rotation = Quaternion.LookRotation(cameraPosVectror - healthBarTransform.position);
healthBarTransform.transform.rotation = healthBarTransform.transform.rotation * rotationAdjustment;
//Debug.Log(Quaternion.LookRotation(cameraPosVectror - healthBarTransform.position));
//rotationAdjustment *
}
}