La herramienta se escribió originalmente para ayudarlo a desarrollar juegos casuales simples en Unity, al menos allí fue bastante útil.
Pero creo que lo usaré en otros proyectos, y no solo en la unidad.
¡Y, quizás, también te sea útil!
Enlace fuente
Entonces, ¿para qué es?
Imagina una situación: escribiste un simple juego casual en el que necesitas tocar la pantalla diez veces para completar un nivel y lo enviaste a tu jefe (o un cliente mimado) para una vista previa.
Seguido de tareas una por una:
- ¿Agreguemos anuncios al final cada 1,5 minutos?
- Y vayamos después de que en algún lugar al principio habrá una ventana: "Compre una prima para que no haya publicidad"
- Che, esta ventana aprieta fuerte, pero deja que sea después del anuncio, pero solo cuando el jugador aprieta inicio y pasa dos niveles?
- Y vamos a los niveles 10, 20, 30, ¿habrá una ventana de "compartir con amigos"?
- Y vamos desde el nivel 10 cada 2 niveles, ¿habrá una ventana de "Califícanos"?
- ¡Y mucho más!
Incluso después de pasar por una ejecución cruel y un bloqueo interminable de su hijo, después de haber realizado la centésima verificación de la ubicación de las ventanas, tarde o temprano se enfrentará a ese problema: ¡las ventanas atadas al temporizador pueden superponerse a las ventanas atadas a los niveles mismos!
Se vuelve cada vez más difícil rehacer esto; después de todo, las verificaciones condicionales ya están hasta el cuello, ¡además su colega podría agregar sus propias ventanas con un código completamente ilegible! ¿Qué hacer?
Tarea
Llame a la ventana en un momento determinado (por ejemplo, presionando un botón), y solo si se cumplen todas las condiciones especificadas (ha pasado el tiempo, se ha alcanzado el punto requerido, etc.)
Decisión
Para esto, hice una clase de condición, aquí están sus campos principales:
- timer int setedSeconds
- salta int seted
- 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 objeto de condición le ayudará a proporcionar rápidamente un conjunto de condiciones necesarias para el funcionamiento de cualquier función!
Si su tarea en la asignación técnica es un poco más difícil que una simple llamada, por ejemplo, una llamada cada dos veces o después de algún tiempo, ya será útil recurrir a la condición, porque esto es abstracción y legibilidad; solo tiene que iniciarlo y verificar su preparación.
¡Agregué atributos de unidad útiles a los campos de condición para una fácil inicialización a través del inspector!
Lo principal es la flexibilidad, y si de repente a alguien se le ocurre su propia funcionalidad que no debería entrar en conflicto con su condición, solo necesita crear un planificador general ...
siguiente tarea
Agregue de manera flexible diferentes ventanas (llamada de función) desde diferentes lugares en el programa, manténgase sincronizado y evite conflictos de superposición.
Solución: ¡
Y ahora llegamos a la clase principal de Sheduler, nuestro planificador de condiciones!
Es mejor inicializar un objeto de esta clase lo antes posible. Específicamente en una unidad, es mejor que el objeto sea DontDestroyOnLoad .
Si miras dentro de Sheduler , puedes ver los siguientes campos:
- Punto de control actual int currentheckPoint
- Una colección de todas las condiciones agregadas y su comportamiento Dictionary & ltCondition, Action & gt ConditionHandlers - para que el
planificador sepa qué papel debe desempeñar la condición terminada - Dictionary <int,Condition> CheckPoints — Sheduler, Dictionary, , . .
- Queue <Condition> WaitingConditions ,
Sheduler almacena el comportamiento de cada condición y se dispara de acuerdo a esta clase, se establece al momento de agregar la condición public void Add (Condition newCondition, Action CallBack) , donde hay un delegado requerido en los argumentos. El método en sí lee el nombre de la condición y genera una excepción si está vacío o ya se ha agregado; esto es necesario en caso de que, por alguna razón, necesite tomar una condición de la programación llamada List & ltCondition & gt GetConditions (params string [] conditionName) . Además, el método add Add () ejecuta inmediatamente Start () de la condición añadida. Esto es útil si ejecuta Start ()la condición agregada será olvidada por cuál de los desarrolladores, y también para evitar la eliminación constante de esta función de Sheduler. Si necesita un lugar diferente para iniciar la condición, simplemente trabaje con la condición como antes, siempre puede cambiar sus contadores. Ésta es la belleza de Sheduler: maneja dónde está lista la condición y dónde ha cambiado su disposición, y realiza este cálculo en el momento de llamar a su método principal Condition Invoke (params Condition [] badges) . En los argumentos, puede especificar algunas insignias, es decir, aquellas condiciones que deberían funcionar exclusivamente, y aquellas a quienes llegó el turno, sin embargo, no aparecieron en la lista de insignias, entonces no funcionarán. Pero, si no especifica nada, entonces, como debería ser, ¡todos tienen derecho a llamar en el pico de la cola!
Asegúrese de pensar dónde se contarán los puntos de control para Sheduler NextCheckPoint () , por ejemplo, en el método, al final o al comienzo de la ronda, un
ejemplo completo de lo que se requiere para trabajar con 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
}
Es así como nos aseguramos de que las tres funciones de nuestras condiciones sean llamadas en diferentes lugares, mientras se respeten entre sí y no se arrastren todo en fila, sino que respeten la cola (como una moderna cola digital de cupones), y al usuario, saltando rápidamente desde la meta hasta el inicio del juego. , no se esforzará por el número de propuestas. Con Sheduler, mantiene una clara armonía de simplicidad y flexibilidad, porque con Sheduler y un delegado que se le pasa a través del método Add (Condition newCondition, Action CallBack) , es posible implementar cualquier conexión entre ventanas.
Por ejemplo, al invocar un banner publicitario, aparece una oferta para comprar Premium sin publicidad después de dos niveles:
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(); //
//
}
Simplemente así, ahora cada 80 segundos se activará un anuncio que no distraiga (después de todo, no se llama durante una ronda importante, sino en la línea de meta) y también invocará una oferta para comprar un anuncio cuando sea conveniente para usted. Y lo mejor es que ahora cualquier desarrollador del equipo puede agregar sus propuestas a Sheduler, y Sheduler distribuirá todo.