Esta página explica los conceptos de programación de jugabilidad en Unreal Engine (UE) para usuarios de Unity. Las explicaciones a continuación asumen que estás familiarizado con C# de Unity y quieres más información acerca de cómo utilizar C++ de Unreal Engine y Blueprint.
Los siguientes ejemplos cubren algunos casos de uso comunes de programación de jugabilidad en Unity y cómo implementar la misma funcionalidad en UE.
Instanciar GameObject/generar actor
En Unity, se utiliza la función Crear instancia para crear nuevas instancias de objetos. Esta función toma cualquier tipo de UnityEngine.Object (GameObject, MonoBehaviour, etc.) y hace una copia de él.
public GameObject EnemyPrefab;
public Vector3 SpawnPosition;
public Quaternion SpawnRotation;
void Start()
{
GameObject NewGO = (GameObject)Instantiate(EnemyPrefab, SpawnPosition, SpawnRotation);
NewGO.name = "MyNewGameObject";
}UE tiene dos funciones diferentes para crear instancias de objetos:
NewObjectcrea tipos nuevos deUObject.SpawnActorgenera tipos deAActor.
UObjects y NewObject
Crear subclases de UObject en UE es muy parecido a hacerlo con ScriptableObject en Unity. Son útiles para las clases de jugabilidad que no necesitan aparecer en el mundo o tener componentes asociados como los actores.
En Unity, si crearas una subclase de criptableObject, podrías instanciarla de la siguiente manera:
MyScriptableObject NewSO = ScriptableObject.CreateInstance<MyScriptableObject>();En UE, si crearas una subclase de UObject, podrías instanciarla de la siguiente manera:
UMyObject* NewObj = NewObject<UMyObject>();Actores y cómo generarlos
Puedes generar actores utilizando el método SpawnActor en un objeto World (UWorld en C++). Algunos UObjects y todos los Actors proporcionan un método llamado GetWorld para obtener el objeto World.
En el siguiente ejemplo, usamos esos métodos junto con los parámetros de aparición de un actor existente para emular la funcionalidad del método Instanciar de Unity.
Ejemplo
A continuación se muestra el ejemplo de una subclase de AActor, AMyActor. El constructor por defecto inicializa Int32 y USferefComponent*.
Observa el uso de la función CreateDefaultSubobject. Esta función crea componentes y les asigna propiedades por defecto. Los subobjetos creados con esta función actúan como plantilla por defecto, por lo que puedes modificarlos en una subclase o blueprint.
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
UPROPERTY()
int32 MyIntProp;
UPROPERTY()
USphereComponent* MyCollisionComp;
Esto crea un clon de AMyActor, incluidos todos los componentes, los UPROPERTY y las variables de miembro.
AMyActor* CreateCloneOfMyActor(AMyActor* ExistingActor, FVector SpawnLocation, FRotator SpawnRotation)
{
UWorld* World = ExistingActor->GetWorld();
FActorSpawnParameters SpawnParams;
SpawnParams.Template = ExistingActor;
World->SpawnActor<AMyActor>(ExistingActor->GetClass(), SpawnLocation, SpawnRotation, SpawnParams);
}Hacer proyección de un tipo a otro
En este caso, obtenemos un componente que sabemos que ya tenemos, lo convertimos a un tipo específico y hacemos algo condicionalmente.
Unity
Collider collider = gameObject.GetComponent<Collider>;
SphereCollider sphereCollider = collider as SphereCollider;
if (sphereCollider != null)
{
// ...
}UE C++
UPrimitiveComponent* Primitive = MyActor->GetComponentByClass(UPrimitiveComponent::StaticClass());
USphereComponent* SphereCollider = Cast<USphereComponent>(Primitive);
if (SphereCollider != nullptr)
{
// ...
}Blueprint
En Blueprint, puedes proyectar utilizando un nodo Proyectar a. Si quieres información más detallada, consulta la Casting Quick Start Guide (guía de inicio rápido de proyección).
Destruir GameObject/actor
Destruir GameObject/actor (con 1 segundo de retraso)
Desactivar GameObjects/actores
C# de Unity C# | UE C++ C++ | Blueprint |
Acceder al GameObject/actor desde un componente
C# de Unity C++ | UE C++ C++ | Blueprint |
Acceder a un componente desde el GameObject/actor
Unity
MyComponent MyComp = gameObject.GetComponent<MyComponent>();UE C++
UMyComponent* MyComp = MyActor->FindComponentByClass<UMyComponent>();Blueprint
Buscar GameObjects/actores
Unity
// Find GameObject by name
GameObject MyGO = GameObject.Find("MyNamedGameObject");
// Find Objects by type
MyComponent[] Components = Object.FindObjectsOfType(typeof(MyComponent)) as MyComponent[];
foreach (MyComponent Component in Components)
{
// ...
}
UE C++
// Find UObjects by type
for (TObjectIterator<UMyObject> It; It; ++it)
{
UMyObject* MyObject = *It;
// ...
}
// Find Actor by name (also works on UObjects)
AActor* MyActor = FindObject<AActor>(nullptr, TEXT("MyNamedActor"));
Blueprint
Cómo añadir etiquetas a elementos GameObject/Actor
Unity
MyGameObject.tag = "MyTag";UE C++
// Actors can have multiple tags
MyActor.Tags.AddUnique(TEXT("MyTag"));Blueprint
Cómo añadir etiquetas a elementos MonoBehaviour/ActorComponent
Unity
// This changes the tag on the GameObject it is attached to
MyComponent.tag = "MyTag";UE C++
// Components have their own array of tags
MyComponent.ComponentTags.AddUnique(TEXT("MyTag"));Cómo comparar etiquetas de elementos GameObject/Actor y MonoBehaviour/ActorComponent
Unity
if (MyGameObject.CompareTag("MyTag"))
{
// ...
}
// Checks the tag on the GameObject it is attached to
if (MyComponent.CompareTag("MyTag"))
{
// ...
}UE C++
// Checks if an Actor has this tag
if (MyActor->ActorHasTag(FName(TEXT("MyTag"))))
{
// ...
}Blueprint
UE C++
// Checks if an ActorComponent has this tag
if (MyComponent->ComponentHasTag(FName(TEXT("MyTag"))))
{
// ...
}Blueprint
Física: componente RigidBody y componente Primitive
En Unity, para dotar a un elemento GameObject de características físicas, tienes que adjuntar un componente RigidBody.
En UE, cualquier componente Primitive (UPrimitiveComponent en C++) puede representar un objeto físico. Algunos de estos componentes primitivos son:
Componentes de forma (
USphereComponent,UCapsuleComponent, etc.).Componentes de malla estática
Componentes de malla esquelética
A diferencia de Unity, que separa las responsabilidades de colisión y visualizaciones en componentes independientes, UE combina los conceptos "potencialmente físico" y "potencialmente visible" en un único componente Primitive. Cualquier componente con geometría en el mundo, que pueda ser renderizado o con el que se pueda interactuar físicamente, es una subclase de PrimitiveComponent.
Los canales de colisión son el equivalente en UE a las capas en Unity. Para más información, consulta Collision Filtering (filtrado de colisiones).
RayCast y RayTrace
Unity
GameObject FindGOCameraIsLookingAt()
{
Vector3 Start = Camera.main.transform.position;
Vector3 Direction = Camera.main.transform.forward;
float Distance = 100.0f;
int LayerBitMask = 1 << LayerMask.NameToLayer("Pawn");
RaycastHit Hit;
bool bHit = Physics.Raycast(Start, Direction, out Hit, Distance, LayerBitMask);
UE C++
APawn* AMyPlayerController::FindPawnCameraIsLookingAt()
{
// You can use this to customize various properties about the trace
FCollisionQueryParams Params;
// Ignore the player's pawn
Params.AddIgnoredActor(GetPawn());
// The hit result gets populated by the line trace
FHitResult Hit;
Blueprint
Volúmenes de activación
Unity
public class MyComponent : MonoBehaviour
{
void Start()
{
collider.isTrigger = true;
}
void OnTriggerEnter(Collider Other)
{
// ...
}
UE C++
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
// My trigger component
UPROPERTY()
UPrimitiveComponent* Trigger;
AMyActor()
Blueprint
Para obtener más información sobre la configuración de las respuestas ante colisiones, consulta la página Collision (colisión).
Cuerpos rígidos cinemáticos
Unity
public class MyComponent : MonoBehaviour
{
void Start()
{
rigidbody.isKinematic = true;
rigidbody.velocity = transform.forward * 10.0f;
}
}UE C++
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
UPROPERTY()
UPrimitiveComponent* PhysicalComp;
AMyActor()
{
Eventos de entrada
Unity
public class MyPlayerController : MonoBehaviour
{
void Update()
{
if (Input.GetButtonDown("Fire"))
{
// ...
}
float Horiz = Input.GetAxis("Horizontal");
float Vert = Input.GetAxis("Vertical");
UE C++
UCLASS()
class AMyPlayerController : public APlayerController
{
GENERATED_BODY()
void SetupInputComponent()
{
Super::SetupInputComponent();
InputComponent->BindAction("Fire", IE_Pressed, this, &AMyPlayerController::HandleFireInputEvent);
Blueprint
Este es el aspecto que podrían tener las propiedades de entrada en la configuración del proyecto:
Si deseas obtener más información sobre cómo configurar la entrada para tu proyecto de UE, consulta la página Input (entrada).
Lecturas adicionales
Si quieres más información relacionada con los conceptos anteriores, te recomendamos que consultes los siguientes apartados:
Marco de juego: cubre los sistemas principales del juego, como el modo de juego, el estado del jugador, los controladores, los peones, las cámaras y otros.
Gameplay Architecture (arquitectura de jugabilidad): Referencias para crear e implementar clases de jugabilidad.
Gameplay Tutorials (tutoriales de juego): tutoriales para recrear los elementos de juego más habituales.