jueves, 24 de octubre de 2013

4) Dale al diseñador lo que quiere. Arquetipos para todos

¡Muy buenas!

Aquí nos encontramos de nuevo en el mágico mundo Digimon de la programación en UnrealScript. Hoy con nosotros: ¡Arquetipos! ¿Y qué narices es esto? Instancias de objetos referenciadas que se pueden tocar en tiempo real para el disfrute y frote de la gente que tiene que montar el juego. De este modo, desde el Content Browser, guardaremos en un paquete nuestros propios Pawn con una configuración determinada, que podremos modificar mientras el juego está funcionando. En el código, referenciaremos ese Pawn para que lo lea tal y como lo queramos.
Igualmente, haremos un "fake" de arquetipo para nuestras cámaras, ya que, de momento, y aunque pueden ser actores también en las escenas, nosotros creamos una clase que no tiene "materialización" en la escena hasta que no comienza el juego. Crearemos una clase NULLCameraTDAttributes, cuyas variables leeremos desde nuestra cámara NULLCameraTopDown, para poder modificar en tiempo real sus características. ¡Al lío!

Nuestra aventura de hoy nos lleva a adentrarnos en el magico mundo del editor. En el Content Browser, pestaña Actor Classes, buscamos bajo la categoría NULLGame, nuestro NULLPawn. Botón derecho y crear Arquetipo. Nos pide un Paquete, un nombre de agrupamiento y el nombre del arquetipo. Podemos poner NULLCharacters como nombre del paquete, de agrupamiento Characters y como nombre de arquetipo arc_NULLTestPawn.

Ahora si volvemos al content browser, bajo el apartado Packages abajo a la izquierda por defecto, hay una carpeta llamada NewPackages. La desplegamos y vemos nuestro paquete. Botón derecho y guardar. Lo lleváis a la carpeta Content/NULLContent/ y lo guardáis con la jerarquía de carpetas que queráis como os sintáis más cómodos y ordenados.

Ya tenemos nuestro arquetipo. Tendremos que buscarlo en el content browser después para conocer su Full Name y dárselo a una de nuestras variables de NULLGameInfo.

En primer lugar, GameInfo tiene una función encargada de "spawnear" un Pawn por defecto para que PlayerController lo posea (no me pongo érotico, es que PlayerController tiene una función UnPossess y Possess cual espíritu maligno para controlar los Pawns que le indiquemos). Dicha función es "function Pawn SpawnDefaultPawnFor(Controller NewPlayer, NavigationPoint StartSpot)"

Mi recomendación es que le echéis un ojo en la clase base. Ahora colocamos esta función en la clase que ya tenemos de GameInfo

NULLGameInfo.uc

...
/**
 * Returns a pawn of the default pawn class
 *
 * @param    NewPlayer - Controller for whom this pawn is spawned
 * @param    StartSpot - PlayerStart at which to spawn pawn
 *
 * @return    pawn
 */
function Pawn SpawnDefaultPawnFor(Controller NewPlayer, NavigationPoint StartSpot)
{
    //local class<Pawn> DefaultPlayerClass;
    local Rotator StartRotation;
    local Pawn ResultPawn;

    //Comentamos esta línea ya que no vamos a utilizar una clase para el jugador
    //Si no nuestro propio arquetipo
    //DefaultPlayerClass = GetDefaultPlayerClass(NewPlayer);

    // don't allow pawn to be spawned with any pitch or roll
    StartRotation.Yaw = StartSpot.Rotation.Yaw;

    //ResultPawn = Spawn(DefaultPlayerClass,,,StartSpot.Location,StartRotation);
    //Aquí podéis ver la diferencia entre el original de la función
    //Y como spawneamos nuestro arquetipo.
    //Nos faltará declarar la variable
    //var const archetype Pawn DefaultPawnArchetype;
    //Al inicio de nuestra clase
    ResultPawn = Spawn(DefaultPawnArchetype.Class,,,StartSpot.Location,StartRotation,DefaultPawnArchetype);

    if ( ResultPawn == None )
    {
        `log("[NULLGameInfo] Couldn't spawn player of type "$DefaultPawnArchetype.Class$" at "$StartSpot);
    }
    return ResultPawn;
}
...


Bien, como indico en los comentarios nos faltará añadir la variable:

var const archetype Pawn DefaultPawnArchetype;

y darle un valor en nuestro DefaultProperties. El cual, iremos al editor, buscaremos nuestro Pawn creado en su paquete y copiaremos su nombre total Copy Full Name to Clipboard y lo pegaremos de este modo

DefaultProperties
{
  DefaultPawnArchetype=<IntroduzcaAquí SuTabacoGracias>
}

Comentamos la línea: //DefaultPawnClass=class'NULLGame.NULLPawn' ya que ya no usamos un Pawn normal, si no un arquetipo.

Y Voilá. Podremos ejecutar en el Editor nuestro juego y modificar mediante el content browser y seleccionando el arquetipo con F4 sus propiedades.

Podemos hacer la prueba y buscar otra skeletal Mesh y ver cómo cambia en tiempo real :D

¡Por cierto! Si no sabéis ejecutar un tipo de juego concreto en el Editor, es en la pestaña View->WorldProperties->GameType y allí en DefaultGameType y GameType for PIE colocáis vuestra clase de juego NULLGameInfo. Luego le dáis a la flechita verde que hay en la barra de arriba o en la venta que queráis ejecutar el juego y a disfrutar.

Tened en cuenta, que la malla se carga al iniciar el juego. Si desligáis el skeletalMeshComponent actual mientras se ejecuta, la malla desaparecerá pero no se cargará la nueva hasta volver a iniciar. Al ser placeable, un diseñador puede arrastrar a la escena el arquetipo y comprobar el aspecto final que desee en el juego.

Ahora podemos, colocar las variables de nuestra cámara en una clase que herede de las más básicas en UDK, que es Object, ocultar todo componente que no nos interese y dejar sólo al descubierto las variables y valores que queramos modificar.

Para ello generamos una clase llamada NULLCameraTDAttributes:

NULLCameraTDAttributes.uc

class NULLCameraTDAttributes extends Object
HideCategories(Object);

var (Camera) float altitude;

defaultproperties
{
    altitude=500.0f
}

HideCategories es un flag que oculta las categorías indicadas separadas por comas que no queramos mostrar en las propiedades desde el editor (con F4). De este modo, creamos una categoría camera (al colocar entre paréntesis en una variable como se indica), con la variable altitude.

Vamos al editor y creamos nuestro arquetipo de NULLCameraTDAttributes (ojo que seguramente tendréis que desactivar algun booleano de los que aparecen en la pestana Actor Classes del Content Browser para poder ver esta clase) y siguiendo pasos parecidos a los que hemos realizado antes con el Pawn.

Ahora en nuestra cámara deberemos consultar este valor. Creamos una variable:
var const NULLCameraTDAttributes CameraAttributes;

En la funcion UpdateViewTarget(out TViewTarget OutVT, float DeltaTime) cambiamos donde teníamos a pelo la altura de la cámara en unidades de Unreal por CameraAttributes.altitude.

Ahora nos faltará colocar en nuestra cámara en default properties en valor de la variable CameraAttributes.

IMPORTANTE: En DefaultProperties de vuestro Pawn, debéis colocar Mesh=NameDelSkeletalMesh para poder modificar la malla del mismo mediante el arquetipo.

¡Y ya podemos en tiempo real cambiar la altura de nuestra cámara!

¡Nos vemos en el siguiente tutorial!





No hay comentarios:

Publicar un comentario