Desarrollo completo de un juego backrooms en Unity
Los juegos del tipo backrooms se basan en escenarios laberínticos y atmósferas tensas donde el jugador es perseguido constantemente.
Vamos a hacer un desarrollo completo de un Juego Backrooms en Unity e Implementar esta experiencia inmersiva requiere sistemas robustos de generación procedural, navegación con IA, y controles de jugador refinados. Este artículo abarca en detalle cada componente crítico, apuntando a una comprensión profunda de la arquitectura del juego, basado en Unity y C#.
1. Generación Procedural de Mapas con CreadorEscenarios
La generación procedural de mapas es el núcleo para crear espacios dinámicos e infinitos. La clase CreadorEscenarios se encarga de crear nuevos escenarios alrededor del actual en las direcciones arriba, abajo, izquierda y derecha, empleando tamaños que detecta automáticamente mediante el MeshRenderer, o usa valores predeterminados si no se encuentra.
Lógica de Generación y Posicionamiento
Mediante un enum Posiciones, el sistema enumera las direcciones disponibles:
public enum Posiciones { Arriba, Abajo, Izquierda, Derecha }

Luego, con BuclePosiciones(), se iteran las direcciones para crear los nuevos mapas:
public void BuclePosiciones()
{
foreach (Posiciones posicion in Enum.GetValues(typeof(Posiciones)))
{
GenerarEscenario(posicion);
}
}
Cada escenario se instancia en un offset de la posición actual en la dirección correspondiente usando las dimensiones calculadas para mantener continuidad.

Manejo de Trigger para Generación Dinámica
Al entrar el jugador en un mapa, el trigger gestiona actualizar el índice de mapa que tocará generarse, limpiar mapas anteriores para optimización, y crear nuevos mapas alrededor:
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
borrarEsteMapa = false;
var gm = GameManager.instancia;
gm.CambiaIndiceMapa(siguienteMapa);
gm.BorrarMapasAlrededor();
BuclePosiciones();
}
Este enfoque permite un mundo en expansión que se siente vivo y sin límites definidos.
2. Inteligencia Artificial del Enemigo (EnemyAI)
El enemigo que persigue al jugador ofrece la tensión principal del juego. Su IA combina navegación usando NavMeshAgent, detección visual, animación, y audio ambiental.

Componentes Clave
- NavMeshAgent: Permite movimiento inteligente y navegación en el escenario generado, manejando rutas y obstáculos.
- Animador: Controla animaciones fluidas de caminar y correr con interpolaciones suaves (
Blend Tree). - AudioSource: Reproduce sonidos de detección, proximidad y pasos sincronizados con la velocidad.

Patrullaje y Persecución
El sistema alterna entre patrullar puntos específicos y perseguir al jugador si este entra en su rango de visión definido por un ángulo y distancia:
public float visionRange = 50f;
public float visionAngle = 90f;
public LayerMask obstacleMask;
La función CanSeePlayer() usa raycasting para confirmar línea de vista directa:
bool CanSeePlayer()
{
Vector3 dir = (player.position - transform.position).normalized;
if (Vector3.Angle(transform.forward, dir) > visionAngle * 0.5f) return false;
float distance = Vector3.Distance(transform.position, player.position);
if (distance > visionRange) return false;
if (Physics.Raycast(transform.position, dir, out var hit, distance, obstacleMask))
{
if (!hit.collider.CompareTag("Player")) return false;
}
return true;
}

Transición de Estados
Cuando detecta al jugador, inicia persecución:
void StartChase()
{
if (isChasing) return;
alertMessageTimer = alertMessageDuration;
if (audioSource != null)
{
AudioClip clip = GetDetectionClip();
audioSource?.PlayOneShot(clip);
}
isPatrolling = false;
isChasing = true;
agent.ResetPath();
agent.speed = chaseSpeed;
agent.acceleration = chaseAcceleration;
agent.stoppingDistance = 0.5f;
agent.isStopped = false;
currentAnimationSpeed = Mathf.InverseLerp(0f, chaseSpeed, agent.speed);
animator.SetFloat("Speed", currentAnimationSpeed);
}
Al perder de vista al jugador, vuelve a patrullar:
void StopChase()
{
if (!isChasing) return;
isChasing = false;
agent.ResetPath();
agent.acceleration = 8f;
if (patrolPoints != null && patrolPoints.Count > 0)
{
isPatrolling = true;
currentPatrolTimer = 0f;
SetNewPatrolDestination();
}
else
{
isPatrolling = false;
agent.speed = idleSpeed;
agent.isStopped = true;
}
currentAnimationSpeed = Mathf.InverseLerp(0f, chaseSpeed, agent.speed);
animator.SetFloat("Speed", currentAnimationSpeed);
}

Audio Ambiental y Feedback Visual
El enemigo reproduce sonidos de terror aleatorios cuando está cerca, así como sonidos específicos al detectar al jugador, aumentando la inmersión:
private void TryPlayProximitySound()
{
if (player == null || audioSource == null || proximitySounds == null || proximitySounds.Count == 0) return;
if (proximitySoundTimer > 0f) return;
float dist = Vector3.Distance(transform.position, player.position);
if (dist > proximitySoundRange) return;
AudioClip clip = proximitySounds[Random.Range(0, proximitySounds.Count)];
audioSource.PlayOneShot(clip);
proximitySoundTimer = proximitySoundCooldown;
}
También sincroniza sonidos de pasos con la velocidad real del enemigo.
Colisiones y Fin del Juego
Cuando colisiona con el jugador se activa el fin del juego, pausando la IA y mostrando mensaje visual.

3. Gestión Dinámica del Enemigo con EnemyTeleportManager
Cada vez que se genera un nuevo mapa, el enemigo se teletransporta a un punto de spawn valido o a uno aleatorio de los waypoints del mapa, asegurando que esté siempre cerca para mantener la presión sobre el jugador.
public void HandleMapaCreado(GameObject nuevoMapa)
{
if (enemy == null || nuevoMapa == null) return;
List<Transform> waypoints = ObtenerWaypoints(nuevoMapa);
Vector3 destino = CalcularDestino(nuevoMapa, waypoints);
var navAgent = enemy.GetComponent<NavMeshAgent>();
if (navAgent != null)
{
navAgent.Warp(destino + Vector3.up * warpYOffset);
}
else
{
enemy.transform.position = destino;
}
if (waypoints.Count > 0)
{
enemy.SetPatrolRoute(waypoints);
}
}

4. Control del Jugador con PlayerMovement
El jugador se mueve usando un CharacterController que facilita el manejo de colisiones y gravedad. La cámara principal influye en la dirección del movimiento para una experiencia natural e intuitiva.
Movimiento y Rotación
Las entradas horizontales y verticales se traducen a un vector de movimiento relativo a la orientación de la cámara, lo que permite que el jugador se mueva en la dirección hacia la que mira.
Vector3 forward = cam.forward;
Vector3 right = cam.right;
forward.y = 0f; right.y = 0f;
forward.Normalize(); right.Normalize();
Vector3 move = forward * z + right * x;
controller.Move(move * speed * Time.deltaTime);
La rotación suave del modelo 3D del jugador se ajusta para que mire en la dirección que camina.

Animaciones y Sonido de Pasos
Un Animator con blend trees ajusta animaciones para que la marcha y la carrera se vean fluidas. Se emiten sonidos de pasos aleatorios en intervalos sincronizados con la velocidad y estado de movimiento.

Salto y Gravedad
El salto se calcula con una fórmula física básica para altura y la gravedad se aplica manualmente, actualizando la velocidad vertical cada frame.

Derrota
Cuando el jugador entra en un trigger de derrota, se muestra un mensaje en pantalla y se reproduce un sonido para aumentar la inmersión en la experiencia.

5. Cámara con SimpleCameraFollow
La cámara sigue al jugador desde atrás con un offset configurable y permite rotación alrededor del jugador usando movimiento del ratón.
float mouseX = Input.GetAxis("Mouse X");
rotationY += mouseX * mouseSensitivity * Time.deltaTime;
Quaternion rotation = Quaternion.Euler(0, rotationY, 0);
Vector3 desiredPos = target.position - rotation * Vector3.forward * distance + Vector3.up * height;
transform.position = desiredPos;
transform.LookAt(target.position + Vector3.up * (height * 0.5f));
Esta configuración garantiza que la cámara ofrezca buena visibilidad con una sensación natural de control.
6. Gestión de Mapas y Ciclo de Juego con GameManager
GameManager actúa como coordinador maestro para creación y destrucción de mapas, manteniendo un número controlado para no saturar los recursos.
Almacenamiento y Selección de Mapas
Mantiene una lista de mapas alrededor del jugador, y elimina aquellos que no se están usando para liberar memoria.
Selección de Prefabs y Generación
Decide si generar un mapa final especial o un mapa aleatorio o forzado según condiciones como cantidad ya generada.
Comunicación entre Componentes
Notifica al teletransportador para adaptar rutas del enemigo al nuevo mapa generado.
7. Menú Principal para Control de Escena
Un menú sencillo permite iniciar el juego o salir, con validación para evitar errores como no definir la escena destino correctamente.
8. Modelado y Creación del Personaje Principal
El desarrollo visual y la fidelidad del personaje principal es fundamental para crear una experiencia inmersiva en juegos como este tipo backrooms. Para este proyecto, el modelado y diseño del personaje reutiliza y adapta recursos del segundo corte anteriores, integrando creativamente diversas herramientas y librerías especializadas en modelado 3D, texturizado facial, y animación.

Reutilización y Adaptación del Escenario de Blender
Se partió del escenario base desarrollado en Blender durante el segundo corte del proyecto, adaptando algunos de sus componentes para optimizar tanto el performance como la coherencia visual. Este proceso permitió aprovechar activos ya generados sin necesidad de recrear desde cero, lo que agilizó el flujo productivo.
Blender es popular en la industria debido a su potencia para modelado poligonal, esculpido y creación de texturas, todos aspectos esenciales para crear entornos y personajes detallados. La integración eficiente entre Blender y Unity facilita importar estos modelos 3D de alta calidad.

Obtención de Modelos en Sketchfab
Los modelos de personajes, incluyendo el protagonista y posibles NPCs, provienen de Sketchfab, una plataforma que ofrece tanto modelos gratuitos como de pago listos para uso en tiempo real. La colección usada se seleccionó priorizando características como rigging y compatibilidad con motores de juego.

Sketchfab ofrece descargas en formatos amigables para Unity (.fbx, .obj), lo que facilita la integración directa. Además, muchos modelos están optimizados para animaciones y soporte de morph targets (deformaciones faciales).
Texturizado Facial con FaceBuilder
Para añadir realismo a las expresiones faciales, se utilizó FaceBuilder, una herramienta especializada en reconstrucción facial 3D a partir de fotos. Esto permitió crear rostros con proporciones naturales y alineadas con el concepto artístico, mejorando la conexión emocional del jugador con el personaje.

FaceBuilder es compatible con Blender y exporta modelos con mapas UV listos para rigging, complementando el workflow de personajes.
Animaciones con Mixamo
Finalmente, para dotar de vida al personaje, las animaciones fueron creadas y adaptadas en Mixamo, una plataforma de Adobe que proporciona rigging automático y una gran cantidad de animaciones predefinidas para personajes humanos.

Mixamo permite aplicar animaciones como caminar, correr, saltar y varios ciclos de movimiento con transiciones suaves, exportando datos que Unity puede importar y usar con su sistema de animaciones (Animator Controller y Blend Trees).
Esta combinación de modelos estáticos (de Sketchfab y Blender), ajustes faciales con FaceBuilder, y animaciones en Mixamo constituyen un pipeline eficiente y ampliamente utilizado en la industria para acelerar desarrollo manteniendo alta calidad visual.
Reflexiones Finales
Este sistema representa un desarrollo completo para un juego de laberinto con atmósfera de supervivencia y tensión, incorporando generación procedural de escenarios, inteligencia artificial avanzada, audio ambiental, animaciones y controles finos de jugador y cámara.
Los sistemas están diseñados para ser modulares y extensibles, permitiendo añadir funcionalidades como más tipos de enemigos, eventos ambientales o efectos sonoros sin comprometer la estabilidad del juego.
Este proyecto sirve como base sólida para crear experiencias inmersivas con tecnologías Unity modernas.
Video
Créditos
Autor: Juan Felipe Ramirez Sánchez, Sergio Numael Linares Ducuara
Editor: Mg. Carlos Iván Pinzón Romero
Código: CG-20252
Universidad: Universidad Central
Fuentes:
Adobe. (s. f.). Mixamo: 3D character animation. Adobe Inc. https://www.mixamo.com
Autodesk. (2022). Unity vs Unreal Engine vs otros motores: Guía comparativa para desarrolladores de videojuegos. Autodesk, Inc. https://www.autodesk.com
Brackeys. (2020, 10 de mayo). NavMesh in Unity [Video]. YouTube. https://www.youtube.com
Epic Games. (2023). Introducción a la inteligencia artificial en videojuegos. En Unreal Engine Documentation. Epic Games. https://docs.unrealengine.com
Gamedev Academy. (2023, 31 de octubre). Complete guide to Unity procedural generation. GameDev Academy. https://gamedevacademy.org/complete-guide-to-procedural-level-generation-in-unity-part-1
Gamedev Academy. (2023, 2 de noviembre). Noise generator: Procedural 2D maps Unity tutorial. GameDev Academy. https://gamedevacademy.org/procedural-2d-maps-unity-tutorial
