sábado, 14 de diciembre de 2013

9) Powered by Kismet!

¡Muy buenas!
A continuación vamos a ver las bases para poder crear vuestras propias cajitas de Kismet. Para el que no sepa qué es Kismet, es un sistema de nodos que utiliza UDK para realizar "fragmentos" de código que actúen sobre actores en el mapa. Es un envoltorio de código para que se puedan crear ciertos comportamientos por medio de un entorno visual. Se utiliza fundamentalmente para "allanar" terreno a los diseñadores y poder trabajar de manera más independiente sin depender tanto del programador. 
En Kismet, existen 3 tipos de nodos (cajitas):
  1. Actions
  2. Events
  3. Conditionals
Vamos a centrarnos en las primeras ya que la estructura general es la misma en todas.

Action

La estructura básica de las acciones es la siguiente:
// extend UIAction if this action should be UI Kismet Action instead of a Level Kismet Action
class NULLSeqAction_Example extends SequenceAction;
var Object NameOfTheVariableInTheCodeSeeAtTheTopOfThisClass;
//Esta clase recibe este evento cuando recibe una señal positiva de otro nodo en //algún input
event Activated()
{
if(InputLinks[0].bHasImpulse)
{ //Si recibimos un impulso positivo de el primer elemento dentro de nuestro arrat de entradas, ejecutamos este bloque de código.
OutputLinks[0].bHasImpulse = true;
}
else
{ //If we don’t have a positive pulse, then our output is false
OutputLinks[0].bHasImpulse = false;
}
}
defaultproperties
{
ObjName=”NULLExample Action” //Nombre del nodo tal como se ve en el editor //de Kismet
ObjCategory=”NULLGame Actions” //Nombre de la categoría a la que pertenece //para poder ordenar mejor nuestros nodos de Kismet
InputLinks(0)=(LinkDesc=”Name of the input (connection) from the left side of the node”) //Démonos cuenta de que cuando hablemos de Eventos no necesitamos //InputLinks
//They are just input to select different behaviour in the node. InputLinks(n), //n=0,1,2,3,4,5…
VariableLinks.Empty //Clean up inherited variables
//Variables are connected to the node from the bottom
VariableLinks(0)=(
ExpectedType=class’SeqVar_Object’, //This is the most generic class, but you can see in Engine/Classes/SeqVar_* other like SeqVar_Int
LinkDesc=”Name of this variable shown in editor”,
PropertyName=NameOfTheVariableInTheCodeSeeAtTheTopOfThisClass,
bWriteable=true) //If you can modify this variable or it is just read only
OutputLinks(0)=(LinkDesc=”Output”) //Different output from the right side of the node
}
Tened cuidado si copiáis y pegáis el código (no deberíais hacerlo, recordad las sabias palabras de José Luis), pero como se que lo vais hacer, el que avisa no es traidor. Los comentarios entre los parámetros en InputLinks no funcionarán. Borradlos cuando los hayáis leído y entendido o para hacer pruebas.
Recordad, que podemos acceder al grafo de escena desde la clase WorldInfo y si bien, tenemos la función GetWorldInfo() que nos devuelve una referencia del mismo. Si trabajamos desde ciertas clases como Actor, podemos consultarlo directamente como WorldInfo. Recordad también que WorldInfo posee una referencia al GameInfo que estáis utilizando actualmente y que podéis realizar comparativas haciendo castings y comparando con none. 
También podéis acceder al PlayerController local con la función GetALocalPlayerController().
Como imagináis, podéis modificar variables declaradas en VariableLink que conecten con vuestros nodos de Kismet si tienen el flag Writeable (Si no utilizan una copia de sus valores). Podéis hacer un casting del tipo de objeto que queréis con simplemente declarar una variable en la clase con el nombre que designéis en PropertyName. Por supuesto, si no puede hacerlo, su valor será none.
(var MyClass myPropertyVariableName)
Como ejercicio, tratad de crear un nodo Action que reciba un pulso positivo en su input y éste haga que escriba mediante `log() algo. Conectamos esta Action con un Evento Trigger touch (añadimos al mapa, un trigger con botón derecho, AddActor->Add Trigger) y teniéndolo seleccionado en el mapa, en la ventana de Kismet, seleccionamos usar un Evento con este trigger. Colocamos en sus propiedades en la ventana de Kismet la variable MaxTriggerCount=0, para recibir todos los eventos de Touch y no sólo el número >0 que le indiquemos (es un problema bastante común, ya que por defecto esta variable está a 1 y sólo detectará Touch una vez si no lo modificamos).

Events

La estructura de la clase de eventos es similar a las acciones con algún cambio en sus defaultproperties:
// extend UIEvent if this event should be UI Kismet Event instead of a Level Kismet Event
class NULLSeqEvent_Example extends SequenceEvent;
defaultproperties
{
ObjName=”NULLSeqEvent_Example”
ObjCategory=”NULLGame Events”
VariableLinks.Empty //Clean up inherited variables
//Variables are connected to the node from the bottom
VariableLinks(0)=(
ExpectedType=class’SeqVar_Object’, //This is the most generic class, but you can see in Engine/Classes/SeqVar_* other like SeqVar_Int
LinkDesc=”Name of this variable shown in editor”,
PropertyName=NameOfTheVariableInTheCodeSeeAtTheTopOfThisClass,
bWriteable=true) //If you can modify this variable or it is just read only
OutputLinks(0)=(LinkDesc=”Output”) //Different output from the right side of the node
//Exclusive!
MaxTriggerCount=0 //Max number of times this event could be triggered
bPlayerOnly=false //Not only triggeable by PlayerController
}
Para poder lanzar estos eventos, necesitamos indicar qué clases van a utilizarlos:
En defaultProperties de las clases que queremos que los utilicen, añadimos:
SupportedEvents.Add(class’SeqEvent_*’) 
o si queremos controlar el orden de prioridad si utilizan varios eventos...
SupportedEvents(n)=class’SeqEvent_*’ donde n es la prioridad cuanto menor su número, mayor su prioridad (al estar en la estructura de datos SupportedEvents antes).
Hay que tener cuidado al heredar de otra clase si utiliza eventos, ya que podríamos "chafar" algunos de los eventos que utiliza el padre. Utilizad Add en estos casos para concatenar eventos utilizados o bien, reescribir con el nuevo orden todos los eventos que soporta vuestra clase.
Una vez hemos preparado una clase para que reciba los eventos, si es placeable, podremos en Kismet, al tener una instancia de dicha clase en la escena, aplicarle un evento de Kismet propio de ese tipo. Para activarlo, tenemos dos opciones diferentes:
Global, activa todos los eventos de un tipo TriggerGlobalEventClass(class’SeqEvent_*’,self)
Local, activa el evento * del objeto actual TriggerEventClas(class’SeqEvent_*’,self)
Si quieres activar más de un evento, consultad ActivateEventClass (link)
Este es un primer acercamiento a la programación de nodos de Kismet. Los Conditionals tienen un funcionamiento similar, aunque de base son menos utilizados.

No hay comentarios:

Publicar un comentario