miércoles, 20 de noviembre de 2013

6) Colisiones básicas: Recolectando cosillas, ¡Hazte con todas!

¡Muy buenas!

Llegados a este punto, es el momento de explicar las bases de las colisiones en UDK para poder crear nuestros objetos recolectables. Algunos sabréis que existen clases PickUp y demás, importantes para recoger objetos con un inventario. No entraremos en ello todavía, si no en la manera de colisionar con cosas, basándonos en el ejemplo del apartado anterior de recolección de monedas.

Procedo a traducir mi antigua entrada en http://theudknown.wordpress.com/2013/03/02/6-lets-pickup-something/ ya que allí se cubre en inglés lo necesario para este punto.

Procedemos pues a crear un pickup simple para nuestro Pawn. Con respecto al ejercicio anterior, de recolección de monedas, podréis aplicar al final el informar a GameInfo de las monedas que recolectamos y de la posibilidad de terminar la partida. En esta explicación nos centramos en las colisiones.

Lo más importante para la tarea que nos atañe es la colocación de las "flags" de colisión correctamente. Si utilizamos StaticMeshComponents con colisiones, tendremos que asegurarnos que sus flags de colisión sean correctas. Nuestro pickup va a heredar de la clase base Actor.uc

Las dos variables bool (esas flags de las que hablo) más importantes para la colisión tanto en Actor.uc como en los componentes de malla que utilicemos son las siguientes:

bCollideActors : Si es false, el actor no reacciona a ningún tipo de colisión (independientemente de los valores de sus componentes, claro, por tanto, deben estar correctamente indicadas en ambos).
bBlockActors: Si es true, el motor Unreal no permitirá que se solapen dos actores con este valor en dicha flag.

Los eventos que utiliza Unreal para indicar que se ha realizado una colisión son los siguientes:

event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal):
Este evento se llama cuando dos actores se solapan, pero sólo ocurre si uno de ellos tiene el flag
bBlockActors con valor false.
event Bump(Actor Other, PrimitiveComponent OtherComp, Vector HitNormal)
Este evento se llama cuando dos actores colisionan con movimiento uno con otro, y sólo si los dos tienen el flag bBlockActors con valor true.

Esta información se ha extraído de Romero UnrealScript blog

Contando que nuestro pickup queremos que sea más un "trigger" deberemos configurar sus flags como
bCollideActors=true y bBlockActors=false.

Del mismo modo, nos aseguramos que su StaticMeshComponent es ignorado (Quizá prefieras detectar la colisión con el componente de malla en lugar de un componente de primitiva geométrica. En tal caso, hay que configurarlo acorde a lo explicado anteriormente):

begin object Class=StaticMeshComponent Name=MyStaticMesh
StaticMesh=StaticMesh’NodeBuddies.3D_Icons.NodeBuddy__BASE_SHORT’
LightEnvironment=MyLightEnvironment
bCastDynamicShadow=true
CollideActors=false
BlockActors=false
//BlockRigidBody=true
//BlockNonZeroExtent=true
//CanBlockCamera=true
end object
Components.Add(MyStaticMesh)
Si no hemos aplicado las flags de colisión con el componente de malla, lo hacemos por tanto con un componente de primitiva geométrica, en este caso un cilindro (Cyllinder):


Begin Object Class=CylinderComponent Name=CylinderComp
CollisionRadius=32
CollisionHeight=48
CollideActors=true
BlockActors=false
End Object
Components.Add( CylinderComp )
CollisionComponent=CylinderComp
Como he explicado, dependiendo del comportamiento que desees, hay que jugar con la combinación de estas flags en el actor y en sus componentes attachados. La clase Actor indica en su variable CollisionComponent qué ActorComponent es el que utiliza para las colisiones. Al parecer los Actores sólo pueden tener una colisión, pero puedes hacer que extienda su bounding box a varios componentes si en ellos le colocas la variable CheckAlwaysCollision=true. No he hecho muchas pruebas con esto, pero si al iniciar vuestro juego pulsáis Tab os aparecerá la consola de comandos. Desde allí podéis teclear Show Collisions o Show Bounds si hacéis pruebas para activar y desactivar que se vean los mismos con malla alámbrica.

Coloco ahora un ejemplo de pickup:


Here it is a really simple example:
//Placeable is necessary if you want to put this actor from the editor!
class NULLPickUp extends Actor ClassGroup(NULLGame) placeable;
event Touch( Actor Other, PrimitiveComponent OtherComp, Vector HitLocation, Vector HitNormal )
{
`log(“Touched by “@ Other.Name@”!”);
}
DefaultProperties
{
//*****************COLLISIONS*************************************
// If false, the actor does not respond to any type of collision.
bCollideActors=true
// If true, the Unreal engine will not allow the two Actors to overlap.
bBlockActors=false
Begin Object Name=MyLightEnvironment
bEnabled=TRUE
End Object
Components.Add(MyLightEnvironment)
begin object Class=StaticMeshComponent Name=MyStaticMesh
StaticMesh=StaticMesh’NodeBuddies.3D_Icons.NodeBuddy__BASE_SHORT’
LightEnvironment=MyLightEnvironment
bCastDynamicShadow=true
//Scale=0.25
CollideActors=true
BlockActors=false
//BlockRigidBody=true
//BlockNonZeroExtent=true
//CanBlockCamera=true
end object
Components.Add(MyStaticMesh)
//Use in the console command the command Show Collision and check if this component collisions thanks to BlockNonZeroExtent
//If you put that flag to false then no collision happens. In that case, you can put CollideActors from the static mesh = true
Begin Object Class=CylinderComponent Name=CollisionCylinder
CollisionRadius=+0020.000000
CollisionHeight=+0200.000000
CollideActors=false
BlockActors=false
BlockRigidBody=false
//BlockNonZeroExtent – A non zero extent trace is an axis aligned bounding box check, which is commonly used for player movement. If this is true, then the Actor will block non zero extent traces used in Unrealscript.
BlockNonZeroExtent=true
End Object
Components.Add(CollisionCylinder)
CollisionComponent=CollisionCylinder
}
Como ejercicio, es interesante crearos vuestra clase PickUp y que experimentéis con `log() en las funciones de Touch y Bump y cambiéis las flags de vuestro Pawn y de vuestro PickUp para ver qué llama a qué y cuando. Dentro de `log() podéis colocar valores de variables concatenadas con texto utilizando @. Por ejemplo: `log("[MyPickUp] He tocado "@other@" y concretamente su ActorComponent " @ otherComp);
Si colocamos esa línea en Touch o Bump de la clase PickUp, nos indicará con qué ha tocado o chocado y el componente en concreto con el que lo ha hecho.

No hay comentarios:

Publicar un comentario