Niixer

Afterschool: Cómo creamos un videojuego en Unity con IA, animaciones y escenarios 3D

Afterschool juego Unity es un proyecto que creamos combinando sigilo, aventura y humor ligero. En este artículo explico cómo construimos cada parte del desarrollo.. El proyecto nació como una idea simple: un estudiante que olvidó su teléfono en el colegio debe volver de noche para recuperarlo. Sin embargo, el camino no es fácil. Hay guardias, puertas cerradas y muchos obstáculos. En este artículo te cuento, de manera clara y detallada, cómo desarrollamos el juego desde cero.

Introducción y concepto del juego

Afterschool se basa en una historia cotidiana. Todos hemos olvidado algo importante en el colegio alguna vez. Por eso, el jugador entiende la misión desde el principio. Además, el ambiente nocturno y la presencia de guardias generan tensión. Como resultado, la experiencia combina humor, misterio y sigilo.

El juego incluye un menú principal, un selector de personajes y dos niveles principales. Primero, el jugador debe entrar al colegio. Luego, debe buscar su teléfono dentro de varios salones mientras evita al guardia. Cuando por fin encuentra su celular, el juego termina y aparecen los créditos finales.

  • Título: Afterschool
  • Género: Aventura / Sigilo / Humor ligero
  • Premisa: Olvidaste tu teléfono en el colegio. El profesor lo dejó en la oficina del director. Debes colarte de noche, evitar a los guardias y recuperarlo sin que te atrapen.
  • Estructura del juego: menú principal → selector de personajes → Nivel 1: Entrada (ganzuado)Nivel 2: Interior del colegio (búsqueda por aulas) → final/creditos al recuperar el teléfono.
  • Mecánicas principales: stealth ligero (evitar visión del guardia), interacción con objetos (E para ganzuar/abrir), coleccionables (latas que dan puntos), vida/daño por contacto con guardias, pickup del celular (meta final).
  • Tono: humor ligero que hace las partidas amenas y rejugables.

Proceso de creación del juego

Desarrollamos Afterschool usando Unity, junto con varias herramientas externas. Estas herramientas nos ayudaron a crear modelos, animaciones, escenarios y efectos visuales.

Crear Escena Base

Se inicia con una escena en blanco en 3D en Unity, configurando el entorno de trabajo.

Instalar Assets del Jugador

Se accede a la Asset Store (Window > Asset Store) para buscar e instalar el paquete “Starter Assets – Third Person”, que proporciona el controlador de personaje y las animaciones básicas.

Importar Avatar Personalizado

El modelo del estudiante (Jugador) se importa desde un software de modelado (como Avaturn/Blender) y se exporta en formato FBX.

Integrar Avatar

El PlayerArmature predeterminado en la escena se reemplaza con el avatar personalizado en el apartado de Geometry del Inspector.

1. Modelado y uso de assets

Para los personajes usamos Avaturn, y para los objetos y escenarios empleamos Blender y recursos de Sketchfab. De esta manera logramos tener muchos elementos variados sin perder tiempo en modelar todo desde cero. Entre los modelos usados están:

  • street_asset_pack
  • high_school
  • abandoned_playground
  • trash_can_big
  • abandoned_street_lights_pack
  • stone_path_kotor
  • real_time_grass
  • varios autos y objetos decorativos

Gracias a esto, el mapa tiene vida y se ve más completo.

Estos archivos se importaron en Unity (formato FBX/GLB) y se convirtieron a prefabs para control y reutilización en escenas.

2. Animaciones y personajes

Las animaciones fueron creadas en Mixamo. Después de descargarlas, las adaptamos en Unity a los personajes creados en Avaturn. Además, modificamos varios ajustes del rig para que las animaciones no se vieran forzadas.

También usamos el Third Person Controller de Unity. Sin embargo, tuvimos que adaptarlo para que funcionara con nuestros personajes. Esto incluyó cambios en el esqueleto, el collider y el Animator.

3. Diseño de niveles

Creamos dos niveles principales.
Primero está el mapa exterior del colegio. En este lugar hay lluvia, fog, faroles y objetos que crean ambiente. Además, usamos partículas de lluvia para dar una sensación más realista.

Cuando el jugador llega a la puerta principal puede presionar E para ganzuarla. Luego aparece una animación y pasa al siguiente nivel.

El segundo nivel ocurre dentro del colegio. Hay varios salones, pasillos y objetos. El celular aparece en un punto aleatorio, por lo que el jugador debe buscarlo con cuidado. Además, hay un guardia rondando que puede quitar vida si llega a tocarte.

4. IA de los guardias

Uno de los elementos más importantes del juego es la IA del guardia. Para lograrlo usamos el sistema de NavMesh de Unity.

La IA funciona así:

  1. El guardia tiene varios puntos de patrulla.
  2. Se mueve entre ellos según un orden.
  3. Si el jugador se acerca demasiado, el guardia cambia de estado y comienza a perseguirlo.
  4. Si pierde al jugador, vuelve a patrullar.

Gracias a este sistema, el guardia actúa de forma natural y crea tensión sin necesidad de usar mecánicas complicadas.

Fragmento de C#

using UnityEngine;
using UnityEngine.AI; // Necesario para usar el NavMeshAgent

public class EnemyAI : MonoBehaviour
{
    [Header("Configuración de Distancia")]
    public Transform player;           // Tu personaje
    public float chaseRange = 10f;     // Distancia a la que empieza a CORRER
    public float walkRange = 18f;      // Distancia a la que se detiene y empieza a CAMINAR (Patrullar)
    public float patrolSpeed = 1.5f;   // Velocidad para caminar
    public float chaseSpeed = 3.5f;    // Velocidad para correr

    [Header("Configuración de Patrulla")]
    public Transform[] patrolPoints;   // Arreglo donde pondrás los puntos A y B
    private int currentPatrolIndex = 0;

    private NavMeshAgent agent;
    private Animator animator;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        animator = GetComponent<Animator>();

        // Asignamos la velocidad de persecución inicial
        agent.speed = chaseSpeed;

        // Configuramos los puntos de patrulla si no se han asignado
        if (patrolPoints == null || patrolPoints.Length == 0)
        {
            patrolPoints = new Transform[1];
            GameObject startPoint = new GameObject("StartPoint_" + gameObject.name);
            startPoint.transform.position = transform.position;
            patrolPoints[0] = startPoint.transform;
        }

        // Forzar al agente a detenerse y empezar en estado IDLE
        StopPatrolling();
    }

    void Update()
    {
        float distanceToPlayer = Vector3.Distance(transform.position, player.position);

        if (distanceToPlayer < chaseRange)
        {
            // 1. CHASE (CORRER)
            ChasePlayer();
        }
        else if (distanceToPlayer < walkRange)
        {
            // 2. PATROL (CAMINAR)
            HandlePatrolState();
        }
        else
        {
            // 3. IDLE (QUIETO)
            StopPatrolling();
        }
    }

    // Lógica principal para mantener el estado de patrulla (Walking)
    void HandlePatrolState()
    {
        // Aseguramos la velocidad y animación de caminar (si viene de correr o idle)
        if (agent.speed != patrolSpeed || !animator.GetBool("isPatrolling"))
        {
            agent.speed = patrolSpeed;
            animator.SetBool("isChasing", false);
            animator.SetBool("isPatrolling", true);

            // Si estaba quieto y empieza a patrullar, le asignamos la primera ruta
            if (!agent.hasPath)
            {
                agent.SetDestination(patrolPoints[currentPatrolIndex].position);
            }
        }

        // Si hemos llegado al punto actual, avanzamos al siguiente punto de patrulla.
        if (!agent.pathPending && agent.remainingDistance < agent.stoppingDistance + 0.5f)
        {
            Patrol();
        }
    }

    void ChasePlayer()
    {
        agent.speed = chaseSpeed;
        agent.SetDestination(player.position);
        animator.SetBool("isChasing", true);
        animator.SetBool("isPatrolling", true); // Para que use la animación de Run
    }

    void Patrol()
    {
        // Avanza al siguiente punto de patrulla de la lista
        currentPatrolIndex = (currentPatrolIndex + 1) % patrolPoints.Length;
        agent.SetDestination(patrolPoints[currentPatrolIndex].position);
    }

    void StopPatrolling()
    {
        // Detiene el movimiento (SetDestination a su propia posición)
        agent.SetDestination(transform.position);
        agent.speed = chaseSpeed; // Restaura la velocidad para que al perseguir no haya delay
        animator.SetBool("isChasing", false);
        animator.SetBool("isPatrolling", false);
    }

    // Dibuja los rangos de detección en la escena (solo visible en el editor)
    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, walkRange);
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, chaseRange);
    }
}

5. Partículas, efectos y ambiente

Para mejorar la atmósfera agregamos:

  • Lluvia en el mapa exterior

Se busca en los menus y se añade sistema de particulas

Se ajustan para que caigan de arriba

Se ajustan para que se vea una mayor cantidad

  • Fog desde la pestaña Lighting

En el menu de Lighting se realizarion los ajustes para configurar la niebla o fog

  • Luces parpadeantes
  • Sonidos ambientales
  • Partículas al recoger latas
  • Materiales con brillo para objetos mojados

Además, añadimos efectos al celular para que sea más fácil encontrarlo. Por eso, se nota visualmente cuando el jugador se acerca.

6. Mecánicas del jugador

El jugador tiene varias acciones básicas:

  • Moverse libremente
  • Interactuar con objetos al presionar E
  • Recoger latas para sumar puntos
  • Perder vida si el guardia lo alcanza
  • Abrir puertas
  • Ganzuar la entrada

Estas acciones permiten crear una experiencia simple pero entretenida. También agregamos una interfaz que muestra vida, puntos y mensajes importantes.

Menus

Selector de personajes

Optimización del proyecto

Durante el desarrollo también tuvimos que optimizar varios aspectos. Por ejemplo:

  • Reducimos el peso de texturas.
  • Usamos materiales PBR bien configurados.
  • Ajustamos el baking de luces.
  • Combinamos objetos estáticos para menor uso de CPU.
  • Adaptamos colisiones y triggers.

Como resultado, el juego corre mejor y se siente más fluido.

Conclusión

Crear Afterschool fue un proceso muy completo. Aprendimos sobre modelado, animación, programación, iluminación y diseño de niveles. Además, logramos unir todos estos elementos para crear una experiencia divertida y con identidad propia.

Aunque el objetivo del juego es simple, el proceso escondía muchos retos. Sin embargo, gracias a la organización y al uso de buenas herramientas, logramos un resultado sólido. Ahora el jugador puede disfrutar una aventura corta, ligera, pero llena de personalidad.

Unity: estructura básica del proyecto

Video final

Créditos Finales

  • Autores: Bratt Camilo Jiménez Bautista, Eduar Rodriguez
  • Editor: Carlos Iván Pinzón Romero
  • Código: UCMV-8
  • Universidad: Universidad Central

Bibliografía

Software y herramientas

Adobe Inc. (2024). Adobe Photoshop. https://www.adobe.com/products/photoshop.html

Adobe. (2024). Mixamo. https://www.mixamo.com

Audacity Team. (2024). Audacity audio editor. https://www.audacityteam.org

Avaturn. (2024). Avaturn 3D avatar creator. https://avaturn.me

Blender Foundation. (2024). Blender (Versión utilizada). https://www.blender.org

Microsoft. (2024). Visual Studio Code. https://code.visualstudio.com

NVIDIA Corporation. (2024). NVIDIA drivers / GPU acceleration. https://www.nvidia.com

OpenAI. (2024). ChatGPT. https://chat.openai.com

Sketchfab. (2024). Sketchfab 3D model platform. https://sketchfab.com

Unity Technologies. (2024). Unity game engine (Versión utilizada). https://unity.com


Modelos 3D y recursos utilizados

Archivo GLB. (s.f.). abandoned_carousel.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). abandoned_playground.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). abandoned_street_lights_pack.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). arbol_descarga.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). barrier13_-_street_kitbash_collection.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). carry_pickup_suzuki_game_ready.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo JPG. (s.f.). depositphotos_191506142-stock-photo-…jpg [Imagen y textura utilizada en el videojuego Afterschool].

Archivo GLB. (s.f.). Eduar_animado.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). fuente_de_agua_water_fountain.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). generic_passenger_car_pack.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). high_school.glb [Modelo 3D utilizado como base del colegio en Afterschool].

Archivo HTML. (s.f.). highresolution-image-rustic-red-brick-6 [Referencia visual utilizada en el videojuego Afterschool].

Archivo JPG. (s.f.). istockphoto-989479536-612×612.jpg [Imagen de referencia utilizada en el videojuego Afterschool].

Archivo JPG. (s.f.). desktop-wallpaper-black-metal-texture.jpg [Textura utilizada en el videojuego Afterschool].

Archivo JPG. (s.f.). photo-1495578942200-c5fd2d137def.jpg [Imagen utilizada como textura en Afterschool].

Archivo GLB. (s.f.). old_car_wreck.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). parking_lot.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). realtime_grass.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). small_price_car.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). stone_path_kotor.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). street_asset_pack.glb [Modelo 3D utilizado en el videojuego Afterschool].

Archivo GLB. (s.f.). trash_can_big.glb [Modelo 3D utilizado en el videojuego Afterschool].