En esta página se explican conceptos de programación de juegos en Unreal Engine (UE) para usuarios de Unity. Las siguientes explicaciones asumen que conoces Unity en C# y que quieres obtener más información sobre UE en C++ y Blueprint.
Los siguientes ejemplos abarcan algunos casos de uso comunes en la programación de juegos en Unity en C# y cómo implementar la misma función en UE.
Cómo instanciar el GameObject o actor de aparición
En Unity, se utiliza la función Instantiate 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 instanciar objetos:
NewObjectcrea nuevos tipos deUObject.SpawnActorgenera tipos deAActor.
UObjects y NewObject
Subclasificar UObject en UE es similar a subclasificar ScriptableObject en Unity. Son útiles para las clases de jugabilidad que no necesitan aparecer en el mundo o tener componentes adjuntos como los actores.
En Unity, si creas tu propia subclase de ScriptableObject, puedes instanciarla de la siguiente manera:
MyScriptableObject NewSO = ScriptableObject.CreateInstance<MyScriptableObject>();En UE, si creas tu propia subclase de UObject, puedes instanciarla de la siguiente manera:
UMyObject* NewObj = NewObject<UMyObject>();AActors y SpawnActor
Puedes generar actores con el uso del método SpawnActor en un objeto de entorno (UWorld en C++). Algunos UObjects y todos los actores proveen un método GetWorld para obtener el objeto de entorno.
En el ejemplo que se encuentra a continuación, utilizamos esos métodos con los parámetros de aparición de un actor existente para emular la función del método Instanciar de Unity.
Ejemplo
A continuación, está el ejemplo de la subclase AActor, AMyActor. El constructor por defecto inicializa el int32 y el USphereComponent*.
Observe 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, que incluye todas las variables miembro, UPROPERTY, y Componentes.
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);
}Proyección de un tipo a otro
En este caso, obtenemos un componente que sabemos que tenemos, luego lo proyectamos a un tipo específico y hacemos algo de forma condicional.
Unity
Collider collider = gameObject.GetComponent<Collider>;
SphereCollider sphereCollider = collider as SphereCollider;
if (sphereCollider != null)
{
// ...
}UE en C++
UPrimitiveComponent* Primitive = MyActor->GetComponentByClass(UPrimitiveComponent::StaticClass());
USphereComponent* SphereCollider = Cast<USphereComponent>(Primitive);
if (SphereCollider != nullptr)
{
// ...
}blueprint
Puedes proyectar en Blueprint mediante un nodo Cast to. Para obtener información más detallada, consulta la Casting Quick Start Guide (Guía de inicio rápido de proyección).
Cómo destruir un GameObject/Actor
Cómo destruir un GameObject/Actor (con retraso de 1 segundo)
Cómo deshabilitar GameObjects/Actores
Unity en C# C# | UE en C++ C++ | Blueprint |
Cómo acceder al GameObject/Actor desde un componente
Unity en C# C++ | UE en C++ C++ | Blueprint |
Cómo acceder a un componente desde el GameObject/Actor
Unity
MyComponent MyComp = gameObject.GetComponent<MyComponent>();UE en C++
UMyComponent* MyComp = MyActor->FindComponentByClass<UMyComponent>();blueprint
Cómo 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 en 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 los GameObjects/Actores
Unity
MyGameObject.tag = "MyTag";UE en C++
// Actors can have multiple tags
MyActor.Tags.AddUnique(TEXT("MyTag"));blueprint
Cómo añadir etiquetas a los MonoBehaviours/ActorComponents
Unity
// This changes the tag on the GameObject it is attached to
MyComponent.tag = "MyTag";UE en C++
// Components have their own array of tags
MyComponent.ComponentTags.AddUnique(TEXT("MyTag"));Comparación de las etiquetas de GameObjects/Actores y MonoBehaviours/ActorComponents
Unity
if (MyGameObject.CompareTag("MyTag"))
{
// ...
}
// Checks the tag on the GameObject it is attached to
if (MyComponent.CompareTag("MyTag"))
{
// ...
}UE en C++
// Checks if an Actor has this tag
if (MyActor->ActorHasTag(FName(TEXT("MyTag"))))
{
// ...
}blueprint
UE en C++
// Checks if an ActorComponent has this tag
if (MyComponent->ComponentHasTag(FName(TEXT("MyTag"))))
{
// ...
}blueprint
Física: RigidBody contra Primitive Component
En Unity, para darle características físicas a cualquier GameObject, primero había que darle un componente RigidBody.
En UE, cualquier componente primitivo (UPrimitiveComponent en C++) puede representar un objeto físico. Algunos componentes primitivos comunes son los siguientes:
Shape Components (
USphereComponent,UCapsuleComponent, etc.)Static Mesh Components
Skeletal Mesh Components
A diferencia de Unity, que separa las responsabilidades de colisión y visualizaciones en componentes diferentes, UE combina los conceptos de "potencialmente físico" y "potencialmente visible" en un único componente primitivo. Todo componente con geometría en el entorno que se pueda renderizar o con el que se pueda interactuar físicamente es una subclase de UPrimitiveComponent.
Los canales de colisión son el equivalente en UE de las capas en Unity. Para obtener más información, consulta Collision Filtering (Filtrado de colisión).
Proyección de rayos contra rastro de rayos
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 en 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 en 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 de colisión, consulta 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 en 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 en 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 de proyecto:
Para obtener más información sobre cómo configurar la entrada para tu proyecto de UE, consulta Input (entrada).
Leer más
Para obtener más información relacionada con los conceptos anteriores, te recomendamos que consultes las siguientes secciones:
Gameplay Framework (Marco de jugabilidad): abarca los sistemas centrales del juego, como el modo de juego, el estado del jugador, los controladores, los peones, las cámaras, etc.
Gameplay Architecture (Arquitectura de juego): referencia para crear e implementar clases de jugabilidad.
Gameplay Tutorials (Tutoriales de jugabilidad): tutoriales para recrear elementos comunes de jugabilidad.