Bonsoir
j'ai donc effectué quelques essais. Voici quelques éléments, même si j'ai besoin que quelqu'un confirme ou infirme mes conclusions.
Utilisation de StopWatch
Elle est très simple. StopWatch est en gros un chrono, qui utilise quand il le peut l'horloge
matérielle, plus précise que l'horloge système (voir la
documentation Microsoft).
Code : Tout sélectionner
using System.Diagnostics; // Librairie .Net
private Stopwatch mainChrono;
private void Awake () {
// Création chrono.
private mainChrono = new Stopwatch ();
// Lancement chrono.
private mainChrono.Start ();
}
private void Start () {
print ("Durée intermédiare : " + mainChrono.ElapsedMilliseconds.ToString ("0.0") + " millisecondes");
// Arrêt du chrono.
mainChrono.Stop ();
print ("Durée totale : " + mainChrono.ElapsedMilliseconds.ToString ("0.0") + " millisecondes");
}
Particularité des 2 méthodes
La méthode d'appel direct a besoin d'un event static, au contraire de la méthode avec FindObjectOfType<Test> ().
Description de la procédure de test.
L'objet du test est d'instancier 5000 instances d'un prefab. Le prefab est un cube sans collider et muni de ce script, duquel j'ai ôté le superflu. On bascule entre les méthodes en commentant / dé-commentant (initialement, la méthode Update faisait avancer le cube).
Code : Tout sélectionner
using UnityEngine;
public class Cube : MonoBehaviour {
private float m_Speed = 5f;
private void Start () {
// Méthode 1.
Test.OnAccelerateOrder += AccelerateOrder;
// Méthode 2.
// FindObjectOfType<Test> ().OnAccelerateOrder += AccelerateOrder;
}
public void AccelerateOrder (float _speedfactor) => m_Speed *= _speedfactor;
private void OnDisable () {
Test.OnAccelerateOrder -= AccelerateOrder;
//FindObjectOfType<Test> ().OnAccelerateOrder -= AccelerateOrder;
}
}
Un empty porte le script de test :
Code : Tout sélectionner
using System;
using System.Diagnostics;
using UnityEngine;
public class Test : MonoBehaviour {
public static event Action<float> OnAccelerateOrder; // Enlever static pour la méthode 2.
[SerializeField] private GameObject m_Object; // Référence sur le prefab du cube.
private const int NUM_OF_OBJECTS = 5000;
private GameObject [] m_GameObjects; // Tableau des cubes instanciés.
private bool isPrinted; // Evite d'arrêter le chrono à chaque update.
private Stopwatch mainChrono;
private void Awake () {
// Création chrono.
mainChrono = new Stopwatch ();
// Lancement chrono.
mainChrono.Start ();
}
private void Start () {
// Suivi des objets.
m_GameObjects = new GameObject [NUM_OF_OBJECTS];
// Lancement du test.
CreateCubes ();
// Durée de l'instanciation des 5000 cubes.
print ("Durée intermédiaire : " + mainChrono.ElapsedMilliseconds.ToString ("0.0") + " millisecondes");
}
private void Update () {
if (!isPrinted) {
mainChrono.Stop ();
isPrinted = true;
print ("Durée totale : " + mainChrono.ElapsedMilliseconds.ToString ("0.0") + " millisecondes");
}
}
private void CreateCubes () {
// Instantiation des objets.
for (int i = 0; i < NUM_OF_OBJECTS; i++) {
GameObject go = Instantiate (m_Object, new Vector3 (
UnityEngine.Random.Range (-50f, 50f), 0f, UnityEngine.Random.Range (-10f, 10f)),
Quaternion.identity, gameObject.transform);
go.name = "Cube" + i.ToString ("00000");
m_GameObjects [i] = go;
}
}
}
Résultats
Pour les 5000 objets, voici les moyennes en millisecondes de ce que j'ai mesuré sur mon PC (sachant que j'ai placé un 2ème chrono et pris d'autres résultats intermédiaires qui ne sont plus dans le script pour simplifier (méthode 1 // méthode 2).
Durée de l'instanciation des cubes : 185.7 // 187.5
Durée totale : 397 // 3836
Interprétation
La grosse différence de temps est due selon moi (mais je peux me tromper) à la fonction Start des cubes, qui effectue l'abonnement des cubes à l'événement OnAccelerateOrder (cet événement déclenche le changement de vitesse des 5000 cubes, qui est très rapide). En effet, j'avais un temps intermédiaire à la fin du Start du script de test qui donnait 264 ms et 260 ms, et je pense que tous les Start des cubes s'effectuent après le Start de test. La méthode 1 met donc 133 ms pour faire les Start, contre 3439 ms pour la méthode 2. Et c'est pire avec 10000 cubes, où la méthode 2 met 16600 ms pour faire ses 10000 Start (La documentation Unity sur FindObjectOfType précise d'ailleurs que "
Please note that this function is very slow." : l'utiliser dans une fonction Start, pourquoi pas, mais sur des milliers d'objets, ce n'est pas raisonnable.