L'outil a été initialement écrit pour vous aider à développer de simples jeux occasionnels dans Unity, du moins là-bas, il était très utile.
Mais je pense que je vais l'utiliser dans d'autres projets, et pas seulement dans l'unité.
Et, peut-être, cela vous sera utile aussi!
Lien source
Alors, à quoi sert-il?
Imaginez une situation: vous avez écrit un jeu occasionnel simple dans lequel vous devez appuyer dix fois sur l'écran pour terminer un niveau, et l'envoyer à votre patron (ou à un client gâté) pour un aperçu.
Suivi des tâches une par une:
- Ajoutons des publicités à la fin toutes les 1,5 minutes?
- Et après, quelque part au début, il y aura une fenêtre: "Achetez une prime pour qu'il n'y ait pas de publicité"?
- Quelque chose que cette fenêtre appuie brusquement, mais que ce soit après la publicité, mais seulement lorsque le joueur a appuyé sur start et passé deux niveaux?
- Et allez à 10, 20, 30 niveaux, il y aura une fenêtre "partager avec des amis"?
- Et à partir du niveau 10 tous les 2 niveaux, y aura-t-il une fenêtre "Evaluez-nous!"?
- Et un tas de plus!
Même après avoir subi une exécution cruelle et un blocage sans fin de votre enfant, après avoir effectué le centième contrôle de l'emplacement des fenêtres, vous serez tôt ou tard confronté à un tel problème: les fenêtres liées à la minuterie peuvent chevaucher les fenêtres liées aux niveaux eux-mêmes!
Cela devient de plus en plus difficile de refaire cela - après tout, les vérifications conditionnelles sont déjà à la hauteur, et votre collègue pourrait ajouter ses propres fenêtres avec un code complètement illisible! Que faire?
Tâche
Appelez la fenêtre à un certain moment (par exemple, en appuyant sur un bouton), et seulement si toutes les conditions spécifiées sont remplies (le temps est passé, le point requis a été atteint, etc.)
Décision
Pour cela, j'ai fait une classe Condition, voici ses principaux champs:
- timer int setedSeconds
- skips int setedSkips
- List <int> checkPoints
, , . .
, , . , , , NextSkip(). = 0, ,
. - , START() — .
, StartTimer() ResetSkips(). , IsReady()
true , (value > 0), START() .
: — ( ) setedSeconds, , , !
IsReady() , START() , , .
public Condition myCondition;
void Start(){
myCondition = new Condition("");
myCondition.setedSeconds = 120; // 2
myCondition.setedSkips = 5;
myCondition.START(); //
}
//
public void FinishRound(){
myCondition.NextSkip(); // ,
if (myCondition.IsReady())
{
// , ...
myCondition.START(); // START() . , IsReady == true
}
}
, , — List <int> checkPoints. - , , , ., , - . , : , ( , ). , Sheduler , , — .
public Condition myCondition;
void Start(){
myCondition = new Condition("",new List<int> { 1, 2, 5 }); // ,
myCondition.setedSeconds = 120;
myCondition.setedSkips = 5;
myCondition.START();
}
public void FinishRound(){
myCondition.NextSkip();
if (myCondition.IsReady() || myCondition.HasCheckPoint(currentLevel)) //
{
// , ...
myCondition.START();
}
}
, , =) AutoInvoke(Action CallBack, int checkPoint = 0) , NextSkip() START() , START() .
public Condition myCondition;
void Start(){
myCondition = new Condition("",new List<int> { 1, 2, 5 });
myCondition.setedSeconds = 120;
myCondition.setedSkips = 5;
myCondition.START();
}
public void FinishRound(){
myCondition.AutoInvoke(() => Debug.Log("hello World"), currentLevel);
// currentLevel,
}
Un objet de condition vous aidera à fournir rapidement un ensemble de conditions nécessaires pour le fonctionnement de n'importe quelle fonction !!!
Si votre tâche dans le TK est un peu plus difficile qu'un simple appel, par exemple, un appel toutes les deux fois ou après un certain temps, il sera déjà utile de recourir à la condition, car il s'agit d'abstraction et de lisibilité - il vous suffit de la démarrer et de vérifier sa disponibilité.
J'ai ajouté des attributs d'unité utiles aux champs de condition pour une initialisation facile via l'inspecteur!
L'essentiel est la flexibilité, et si soudainement quelqu'un propose sa propre fonctionnalité qui ne devrait pas entrer en conflit avec votre condition, il vous suffit de créer un planificateur général ...
Tâche suivante
Ajoutez de manière flexible différentes fenêtres (appel de fonction) à partir de différents endroits du programme, restez synchronisé et évitez les conflits de superposition!
Solution:
Et maintenant, nous sommes arrivés à la classe principale Sheduler, notre planificateur de conditions!
Il est préférable d'initialiser un objet de cette classe le plus tôt possible. Plus précisément dans une unité, il est préférable que l'objet soit DontDestroyOnLoad .
Si vous regardez à l'intérieur de Sheduler , vous pouvez voir les champs suivants:
- Point de contrôle actuel int currentheckPoint
- Une collection de toutes les conditions ajoutées et de leur comportement Dictionary & ltCondition, Action & gt ConditionHandlers - afin que le
planificateur sache quel rôle la condition finie doit jouer - Dictionary <int,Condition> CheckPoints — Sheduler, Dictionary, , . .
- Queue <Condition> WaitingConditions ,
Sheduler stocke le comportement de chaque condition et est déclenché selon cette classe, il est défini au moment de l'ajout de la condition public void Add (Condition newCondition, Action CallBack) , où il y a un délégué obligatoire dans les arguments. La méthode elle-même lit le nom de la condition et lève une exception si elle est vide ou a déjà été ajoutée - cela est nécessaire au cas où, pour une raison quelconque, vous auriez besoin de prendre une condition de la planification nommée List & ltCondition & gt GetConditions (paramètres string [] conditionName) . En outre, la méthode add Add () exécute immédiatement Start () de la condition ajoutée. Ceci est utile si vous exécutez Start ()la condition ajoutée sera oubliée par lequel des développeurs, et aussi afin d'éviter le rejet constant de cette fonction de Sheduler. Si vous avez besoin d'un autre endroit pour démarrer la condition, vous travaillez simplement avec la condition comme auparavant, vous pouvez toujours modifier ses compteurs. C'est la beauté de Sheduler - il gère où la condition est prête, et où elle a changé sa disponibilité, et effectue ce calcul au moment de l'appel de sa méthode principale Condition Invoke (params Condition [] badges) . Dans les arguments, vous pouvez spécifier certains badges, c'est-à-dire les conditions qui devraient fonctionner exclusivement, et celles dont le tour est venu, cependant, elles n'apparaissent pas dans la liste des badges, alors elles ne fonctionneront pas. Mais, si vous ne spécifiez rien, alors, comme prévu, tout le monde a le droit d'appeler au sommet de la file d'attente!
Assurez-vous de penser à l'endroit où les points de contrôle seront comptés pour Sheduler NextCheckPoint () , par exemple, à la méthode, à l'arrivée ou au début du tour, un
exemple complet de ce qui est nécessaire pour travailler avec le Sheduler:
public Condition OfferBuyVip;
public Condition OfferToShareWithFriends;
public Condition OfferToVisitSite;
public Sheduler OfferSheduler;
public void Start(){
OfferSheduler = new Sheduler(currentLevel); //
/*
*
*/
OfferSheduler.Add(OfferBuyVip, () => Debug.Log(" VIP"));
OfferSheduler.Add(OfferToShareWithFriends, () => Debug.Log(" "));
OfferSheduler.Add(OfferToVisitSite, () => Debug.Log(" , "));
}
public void FinishRound(){
OfferSheduler.NextCheckPoint(currentLevel); // ,
OfferSheduler.Invoke(OfferBuyVip, OfferToShareWithFriends) // ,
}
public void StartRound(){
OfferSheduler.Invoke(OfferToVisitSite); //
// , , Sheduler
}
C'est ainsi que nous sommes parvenus à ce que les trois fonctions de nos conditions soient appelées à des endroits différents, alors qu'elles se respectent et ne parcourent pas tout, mais observent la file d'attente (comme une file d'attente numérique moderne pour les coupons), et l'utilisateur, sautant rapidement de la ligne d'arrivée au début du jeu , ne sera pas contraint par le nombre de propositions. Avec Sheduler, il maintient une harmonie claire de simplicité et de flexibilité, car avec Sheduler et le délégué qui lui est transmis via la méthode Add (Condition newCondition, Action CallBack) , il est possible d'implémenter n'importe quelle connexion entre fenêtres.
Par exemple, lors de l'appel d'une bannière publicitaire, une offre d'achat Premium sans publicité apparaît après deux niveaux:
void Start(){
OfferSheduler = new Sheduler(currentLevel);
callAddBanner = new Condition(" ");
callAddBanner.setedSeconds = 80; // 80
OfferBuyVip = new Condition(" VIP ");
OfferSheduler.Add(callAddBanner,
delegate()
{
Debug.Log(" ");
OfferBuyVip.setedSkips = 2; //
OfferBuyVip.START(); //
}
);
OfferSheduler.Add(OfferBuyVip,
delegate ()
{
Debug.Log(" VIP");
OfferBuyVip.setedSkips = 0; // !
//,
}
);
}
void Finish(){
OfferSheduler.NextCheckPoint(currentLevel); //
//
OfferSheduler.Invoke(); //
//
}
Juste comme ça, maintenant toutes les 80 secondes, une publicité non distrayante sera déclenchée (après tout, elle n'est pas appelée pendant un tour important, mais à la ligne d'arrivée) et invoque également une offre d'achat d'une publicité quand cela vous convient! Et la meilleure chose est que maintenant, tous les développeurs de l'équipe peuvent ajouter leurs propositions à Sheduler, et Sheduler distribuera tout.