PFM: Añadiendo un PNJ básico en UDK

En esta entrada crearemos un PNJ (Personaje No Jugador) básico que servirá de base para crear los futuros enemigos. En esta primera versión obtendremos un personaje muy sencillo, pero animado y con una mínima inteligencia que le permitirá moverse en dirección al jugador.

El proceso es similar a la introducción de un personaje manejable por el jugador. Si para ese caso teníamos 2 clases importantes como son el Pawn y el PlayerController, en este caso serán el Pawn y un AIController. Como se ve la idea es la misma, tener por un lado la representación visual del personaje y por encima una entidad que lo controle, sea jugador humano o inteligencia artificial. El proceso de modelado, animación y configuración del personaje en UDK no varía apenas, veámoslo por encima.

Modelado, texturizado, rigging, animaciones…

El modelo que voy a usar es extremadamente sencillo, rozando la calidad Minecraft 😆

pfm04_01

Le he aplicado textura, creado el esqueleto y realizado el rigging. Aparte he creado dos sencillas animaciones, una para cuando esté quieto y otra para cuando se mueva. Si no tienes un modelo propio disponible puedes descargar este en el enlace al final del artículo.

Importando el personaje, animaciones y texturas en UDK

El proceso de importar el Skeletal Mesh, las animaciones y las texturas es idéntico a lo que vimos al cambiar el personaje protagonista. Se importa primero el modelo, se crea un AnimSet en el Content Browser y se importan las animaciones, comprobando que funcionen como queremos.

pfm04_02

Las texturas se importan de la misma manera que se vió anteriormente. En mi caso son 2 texturas. El motivo es que se creará un material que usará las dos (siguiente apartado).

pfm04_03

Material

El material creado en el editor de materiales es el siguiente:

pfm04_04

Como se ve, una de las texturas se conecta con el canal Difuso y el Especular (para permitir los reflejos). La otra textura, que sólo muestra la lente azul del robot, se conecta al canal Emisivo. El canal emisivo permite determinar qué textura se visualizará independientemente de la iluminación. Así, aunque el visor del robot esté en la sombra se mantendrá iluminado.

AnimTree

El siguiente paso es crear el árbol de animaciones. En este caso será más sencillo que para el personaje protagonista, pero los pasos son análogos.

pfm04_05

UnrealScript

Tenemos un Skeletal Mesh con su árbol de animaciones listo, ahora sólo queda darle vida! Para ello necesitaremos crear las clases que comentamos al principio. Veamos la clase PFMEnemyPawn, que representa la marioneta que moverá el controlador.


class PFMEnemyPawn extends UDKPawn
placeable;

defaultproperties
{
    // Iluminación de entorno del Pawn
    Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
        bSynthesizeSHLight=TRUE
        bIsCharacterLightEnvironment=TRUE
        bUseBooleanEnvironmentShadowing=FALSE
        InvisibleUpdateTime=1
        MinTimeBetweenFullUpdates=.2
    End Object
    Components.Add(MyLightEnvironment)

    // SkeletalMesh
    Begin Object Class=SkeletalMeshComponent Name=EnemyMesh
        SkeletalMesh=SkeletalMesh'Test.Enemy.Enemy'
        AnimSets(0)=AnimSet'Test.Enemy.EnemyAnimSet'
        AnimTreeTemplate=AnimTree'Test.Enemy.EnemyAnimTree'
        LightEnvironment=MyLightEnvironment
        bEnableSoftBodySimulation=True
        bSoftBodyAwakeOnStartup=True
        bAcceptsLights=True
    End Object
    Mesh=EnemyMesh
    Components.Add(EnemyMesh)

    // Cilindro de colisión
    Begin Object Name=CollisionCylinder
        CollisionRadius=50.0
        CollisionHeight=25.0
        BlockNonZeroExtent=true
        BlockZeroExtent=true
        BlockActors=true
        CollideActors=true
    End Object
    CollisionComponent=CollisionCylinder
    Components.Add(CollisionCylinder)

    // Se especifica el controlador
    ControllerClass=class'PFM.PFMEnemyController'

    GroundSpeed=400.0           //Velocidad máxima en suelo
    bCanBeBaseForPawns=true     //Permite que se le suban encima otros pawns
}

Como vemos en el Pawn simplemente definimos la apariencia visual del personaje, creando los 3 componentes que también creamos para el personaje jugador: La iluminación de entorno, el skeletal mesh y el cilindro de colisión. Sólo 2 apuntes:

La palabra placeable que se pone después de declarar la clase permite que podamos instanciar esta clase desde el editor, pudiendo así colocar nuestro PNJ donde queramos directamente en el editor.

Con la línea ControllerClass=class’PFM.PFMEnemyController’, especificamos qué controlador será el que maneje este Pawn por defecto (luego podría usarse otro, pero por defecto usará el que le indiquemos). Vamos a ver el controlador PFMEnemyController:


class PFMEnemyController extends AIController;

var Pawn playerPawn;

// Evento llamado cuando el Controlador posee a un Pawn
event Possess(Pawn inPawn, bool bVehicleTransition)
{
    super.Possess(inPawn, bVehicleTransition);
    // Se activa la física de movimiento
    Pawn.SetMovementPhysics();
}

// Estado de búsqueda
auto state Mirando
{
    // Se ha visto al jugador
    event SeePlayer(Pawn SeenPlayer)
    {
        playerPawn = SeenPlayer;
        GoToState('Persiguiendo');
    }
}

// Estado de persecución
state Persiguiendo
{
    Begin:
    while(true)
    {
        //Moverse hacia el jugador
        MoveToward(playerPawn, playerPawn, 100.0f,true);
    }
}

defaultproperties
{
}

Como vemos esta clase hereda de AIController, pues es un controlador manejado por el ordenador, no el jugador. Este es un controlador muy sencillo, nuestro PNJ tendrá sólo 2 estados “mentales”: Buscar al jugador y seguirlo cuando lo vea. Unrealscript tiene la ventaja que integra en el lenguaje las máquinas de estados, por lo que definir estados que impliquen un comportamiento diferente es muy sencillo.

El estado Mirando es el que se activa por defecto (auto) y simplemente atiende al evento SeePlayer, que se activa cuando el jugador entra en el campo de visión de nuestro PNJ. Cuando se dé el caso, guardaremos una referencia del jugador y cambiaremos al estado Persiguiendo.

En el estado Persiguiendo el único cometido del PNJ es desplazarse hacia donde esté el jugador y lo hará todo el rato (while(true) es una condición que siempre se cumple). La función MoveToward es muy útil para esto pues hará que el PNJ se desplace teniendo en cuenta la física y chocándose si hay paredes de por medio.

Esto es todo lo que necesitamos para crear un comportamiento sencillísimo pero que servirá de base para los enemigos reales del juego.

“It’s alive!!”

Vamos al editor para que se compilen los nuevos scripts y colocamos un PFMEnemyPawn en el mapa (Lo encontraremos en el Content Browser, en la pestaña de Actor Classes). Al probar el mapa….

Está viiivo!!

Descargar el modelo, texturas y animaciones. Si no funciona el enlace, avisad en los comentarios y lo arreglo.
Banner Blog

Anuncios

40 pensamientos en “PFM: Añadiendo un PNJ básico en UDK

  1. Pingback: PFM: Navegación de personajes en UDK – Pathfinding y NavigationMesh | El Blog de Marcos

  2. Pingback: PFM: Diseño y creación de enemigo Speeder | El Blog de Marcos

    • Supongo que te refieres a cómo crear los huesos. No, no tengo ningún tutorial del tema, pues es algo más relacionado con el modelado. Por internet hay muchos tutoriales sobre eso.

  3. Buenas Marcos, tras unos meses de práctica conseguí mas o menos el soldado que buscaba. Pero al ponerlo se atacan entre ellos :/ ¿que debo de hacer para que no se maten los unos a los otros y que solo disparen al jugador?, saludos

    • Bueno, supongo que tus soldados están extendiendo UTBot y por eso se atacan entre sí… Lo más correcto sería crear tus propias clases de inteligencia pero quizá lo más sencillo sea que ellos estén todos en el mismo equipo. No sé exactamente cómo hacerlo pero podrías probar extendiendo tu GameInfo de UTTeamGame y asignando al comienzo del juego todos los bots al mismo equipo.. Algo así funcionaría pero ahora mismo no se decirte loas pasos exactos.. investiga un poco a ver qué tal 😉

  4. Una cosita, también puse las arañitas estilo minecraft, y en el UDK me salía el PFMenemy y todo eso, luego al compilar los scrips me daban avisos y cuando iniciaba el nivel no se veía la araña, ¿que hago?

  5. Yo no tengo la carpeta PFM yo tengo el UDK-2013-07 como ahi que puedo hacer? :/ … Esta padrisimo tus tutoriales gracias a ti he aprendido un monton gracias por el aporte

  6. Oye tengo un problema, a ver si me ayudas, tengo el world configurado en Utteam y he tratado crear jugadores para ambos equipos pero no puedo ¿me podrías explicar como? lamento tener que comentar esto cuando no viene al caso, gracias de antemano…

  7. Al introducir el Pawn en el ‘mapa’ y ejecutarlo, no me aparece el PNJ, sabràs decirme el porque?

    Al compilar me sale todo correcto

  8. Hola!!
    Antes que nada muchas gracias por el foro que creaste! La verdad me ha sido de gran ayuda para comprender la forma en cómo funciona el UDK. En estos momentos estoy trabajando en agregar un PNJ pero al momento de compilar las siguientes líneas me marca lo siguiente “Warning, Unknown propery in defaults”. El warning me aparece en las siguientes líneas:
    Components.Add(MyLightEnvironment)

    SkeletalMesh=SkeletalMesh’X.Mesh.enemy_mesh’

    AnimSets(0)=AnimSet’X.Anims.enemy_anims’

    AnimTreeTemplate=AnimTree’X.Anims.Enemy_AnimTree’

    Components.Add(EnemyMesh)

    Components.Add(CollisionCylinder)

    Como puedes observar me aparece el warning en las líneas que contienen la letra “”. ¡Podrías ayudarme por favor?

  9. Buenos días, Marcos! Antes que nada gracias por tus tutoriales. Creo que el código que colocaste referente a PFMEnemyPawn, está incorrecto en algunas líneas. Creo que en la 14, ya que desde mi explorador veo algunas instrucciones en código HTML. No sé si sea problema de mi explorador o al momento de copiarlo a tu blog se agregaron estos errores. Son instrucciones . Podrías ayudarme por favor?

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s