Hello nikobelic,
Comme d'autre te l'on déjà mentionné, la classe que tu as créée est fonctionnelle, toutefois tu semble mélanger la notion d'une classe qui étant dérivée de "MonoBehaviour" qui est en fait une classe de composant qui ne peut s’exécuter qu'au travers d'un GameObject qui le contient et celle d'une classe de base en C#.
D'ailleurs le fait d'avoir nommé deux constructeurs en démontre cette petite incompréhension.
Dans la pratique pour que ton Update soit appelé il faut que ce script soit attaché au moins à un GameObject instancié dans ta scène. C'est ce GameObject qui créer ta classe et appelle ton Update.
Dans ce cas ton constructeur de base qui surcharge celui de "MonoBehaviour" sera bien sur appelé à la création de l'objet, mais hormis le fait que cette nécessite est très rare à devant être mise en oeuvre, et le problème majeur dans ton écriture est de ne pas appeler aussi le constructeur de base.
La bonne méthode d'écriture devait être :
public class Timer : MonoBehaviour
{
public Timer():base()
{
// Tes initialisations
}
}
Passons à ton deuxième constructeur.
Sur le même principe puisque tu créer une classe dérivée la bonne méthode est aussi d'appeler le constructeur de base. Tu peut simplifier en appelant toi même ton propre constructeur qui fait le boulot correctement.
public Timer(bool startRunning) : this()
{
// Autres init
}
Bon cela ne règle pas le problème de fond que quoi qu'il en soit puisque en aucun cas tu ne pourra utiliser ce deuxième constructeur de façon directe, ni le premier bien sur (c'est un crash assuré).
On va laisser le problème du deuxième constructeur, regardons déjà les choses à comprendre dans le premier s'il est bien écrit.
Un petit script affecté à un GameObject pour permettre de comprendre :
using UnityEngine;
public class Heritage : MonoBehaviour
{
private int _var_0;
public int VAR_1 = 1;
public Heritage()
: base()
{
Debug.Log("Constructor");
}
private void Awake()
{
Debug.Log("Awake");
}
private void Start()
{
Debug.Log("Start");
}
private void OnEnable()
{
Debug.Log("OnEnable");
}
}
Si tu examine ta console debug tu remarque que ton constructeur est bien appelé. Il est appelé plusieurs fois même, c'est normal car quand tu passe du mode editor en mode run, l'inspecteur d'objet lui aussi doit de nouveau instancier ta classe. Attention cela peut être très très gênant et source de bugs difficile à traquer, si tu utilise une ressource non partageable (par exemple file) à la création et tu la libère pas à la destruction de l'objet.
On peut vérifier le truc en rajoutant un destructeur à notre classe.
~Heritage()
{
Debug.Log("Destructor");
}
La tu peut remarquer dans la console, qu'il est difficile de maîtriser ce qui se passe en coulisse d'une façon séquentielle dans le cadre d'un "MonoBehaviour".
Le deuxième point que je souhaite te souligner dans le cadre d'une surcharge du constructeur de base d'un "MonoBehaviour", c'est en ce qui concerne les champs publics présent dans l'inspecteur d'objets (je parle de champs et non de propriétés).
Ceux ci sont sérialisé avec le GameObject et sont dé sérialisés juste avant le Awake().
En gros si dans notre constructeur nous modifions ce type de champ, cela n'aura aucun effet.
Exemple :
public int VAR_1 = 1;
public Heritage()
: base()
{
VAR_1 = 12;
}
private void Awake()
{
Debug.Log(VAR_1);
}
Tu remarquera que VAR_1 contient toujours la valeur 1 !!!
En gros pour conclure, surcharger un constructeur n'a que peut d’intérêt dans le cas d'un descendant de "MonoBehaviour", sauf cas très très particulier qui dépasse ton besoin exprimé.
A mon sens, ta demande que nomme Timer et qui ressemble plus à un chronomètre peut être écrit dans une classe très basique et unitaire.
Le fait même d'utiliser l'Update pour calculer le temps écouler n'est pas vraiment optimum en terme de temps de traitement (une fois par trame... oufff).
Voici à titre d'exemple une classe utilisable qui fait le boulot, et qui ressemble plus a ce que tu souhaitais réaliser :
using UnityEngine;
public class MyTimer
{
private float _startTime;
private float _lastTime;
private bool _running;
public float Counter
{
get
{
if (_running)
return Time.realtimeSinceStartup - _startTime;
else
return _lastTime;
}
}
public MyTimer()
{
_running = false;
_lastTime = 0f;
}
public MyTimer(bool startRunning)
{
_running = startRunning;
if (_running)
Start();
}
public void Start()
{
_running = true;
_startTime = Time.realtimeSinceStartup;
}
public void Pause()
{
_running = false;
_lastTime = Time.realtimeSinceStartup - _startTime;
}
public void Reset()
{
_startTime = Time.realtimeSinceStartup;
_lastTime = 0f;
}
}
Pour l'utiliser rien de plus simple, un script de démo lié à un GameObject :
using UnityEngine;
public class GuiTimer : MonoBehaviour {
private MyTimer _mytimer;
private void Awake()
{
_mytimer = new MyTimer();
// autre possibilité
// _mytimer = new MyTimer(true ou false);
}
private void OnGUI()
{
if (_mytimer == null)
return;
GUILayout.BeginVertical("box");
if (GUILayout.Button("Start timer"))
_mytimer.Start();
if (GUILayout.Button("Pause timer"))
_mytimer.Pause();
if (GUILayout.Button("Reset timer"))
_mytimer.Reset();
GUILayout.EndVertical();
GUILayout.Label(string.Format("Compteur : {0}", _mytimer.Counter));
}
}
Bon ben voilà, si des choses doivent être développée dans ce que je vient d'exposé, n'hésite pas.
Bonne continuation.