COMPARTE ESTE ARTÍCULO

Parte 1 – Preguntas teóricas cortas (10 × 1 punto)

Responde de forma breve y clara.

  1. Explica con tus palabras qué es el patrón Singleton y pon un ejemplo de caso de uso típico en videojuegos.
  2. Indica dos problemas o riesgos de abusar del patrón Singleton en un proyecto grande.
  3. ¿Qué es una máquina de estados (State Machine) y por qué es útil en el desarrollo de videojuegos?
  4. Diferencia entre implementar una máquina de estados con enum y con interfaces.
  5. ¿Qué ventaja tiene usar interfaces en Unity para estructurar el comportamiento de los objetos del juego?
  6. Define brevemente qué es la localización (Localization) en un videojuego.
  7. ¿Por qué es importante separar la lógica del juego de los textos mostrados en pantalla cuando hablamos de localización?
  8. En el contexto de UI en Unity, explica qué es y para qué sirve un Manager o GameManager.
  9. ¿Qué es un Prefab en Unity y por qué es tan importante en un editor de objetos como el de la práctica?
  10. Explica qué es el Raycasting y pon un ejemplo de cómo se usaría en el editor de objetos descrito en la práctica.

Parte 2 – Preguntas de desarrollo / código (5 × 2 puntos)

Escribe el código o pseudocódigo en C# que se pide. No es necesario que sea perfecto, pero sí legible y coherente.

  1. Implementa un Singleton básico en Unity para un AudioManager que solo permita una instancia en la escena.
public class AudioManager : MonoBehaviour
{
    public static AudioManager Instance { get; private set; }

    private void Awake()
    {
        // Completar para que solo exista una instancia
    }
}

Completa el método Awake.

  1. Define un enum llamado EditorState con los estados: Neutral, Create, Move, Rotate, Delete. Escribe un fragmento de código dentro de un EditorManager que cambie de estado cuando pulsemos los botones de la UI.
  2. Diseña una interfaz IEditorState para una máquina de estados basada en interfaces. Debe tener al menos estos métodos: EnterState(), UpdateState(), ExitState(). Escribe la interfaz y la cabecera de una clase concreta MoveState que la implemente.
  3. Escribe un pequeño ejemplo de interfaz en C# llamada ISelectable que obligue a los objetos a implementar un método OnSelect() y OnDeselect(). Después, muestra cómo la usarías en un objeto del escenario.
  4. En el sistema de localización, explica (con pseudocódigo o esquema) cómo cargarías un texto localizado a partir de una clave, usando un LocalizationManager y un diccionario de claves/valores.

Parte 3 – Caso práctico: Editor Multimedia Interactivo (5 × 3 puntos)

Lee el enunciado de la práctica “Realización de un Editor Multimedia Interactivo” y responde.

  1. Diseña el diagrama básico de la máquina de estados del editor (texto): indica los estados y las transiciones principales entre ellos, incluyendo cómo se vuelve al estado neutro.
  2. Explica paso a paso el flujo de creación de un objeto desde que el usuario pulsa el botón “Crear” en la UI hasta que el objeto queda fijado en el suelo.
  3. Explica paso a paso el flujo de movimiento de un objeto (herramienta “Mover”), indicando qué ocurre cuando se hace click en un objeto, mientras se mantiene pulsado y cuando se suelta el botón del ratón.
  4. Describe cómo implementarías el sistema de eliminación con confirmación (popup) usando estados o subestados (por ejemplo: Delete_SelectObject, Delete_ConfirmPopup).
  5. Propón al menos tres ejemplos concretos de feedback (sonoro y visual) que añadirías al editor para mejorar la usabilidad, indicando en qué momento se ejecutan (por ejemplo: al seleccionar modo, al colocar objeto, al eliminarlo, etc.).

Soluciones orientativas / Guía paso a paso

Parte 1 – Teoría

  1. Singleton: Patrón que garantiza que solo exista una instancia de una clase y que sea accesible globalmente. En videojuegos se usa, por ejemplo, para un GameManager, AudioManager o UIManager.
  2. Riesgos: (a) Acoplamiento global fuerte (difícil de testear y mantener). (b) Puede convertirse en un “God Object” con demasiadas responsabilidades. (c) Problemas en escenas de pruebas y carga/unload si no se controla bien.
  3. Máquina de estados: Modelo que define un conjunto finito de estados y las transiciones entre ellos. Útil para controlar lógicamente qué puede hacer el juego/personaje/UI en cada momento (menús, IA de enemigos, herramientas del editor, etc.).
  4. Con enum tenemos un único switch grande dentro de una clase (más simple, pero puede crecer mucho). Con interfaces creamos una jerarquía de clases State que implementan una interfaz y encapsulan su comportamiento, lo que favorece la extensibilidad y el código limpio.
  5. Una interfaz permite definir un contrato de métodos que distintas clases pueden implementar. Facilita el polimorfismo, reduce acoplamiento y permite cambiar implementaciones sin cambiar el código que los usa.
  6. Localización: Proceso de adaptar el juego a distintos idiomas y regiones, separando textos, formatos de fecha, etc., para que el jugador vea el contenido en su idioma.
  7. Porque si los textos están embebidos en el código ("Pulsa START"), es muy difícil cambiarlos y traducirlos. Separarlos en ficheros o tablas permite cambiar idioma sin tocar la lógica.
  8. GameManager/EditorManager: Objeto central que coordina la lógica global: estado actual, comunicación con la UI, instanciación de objetos, etc.
  9. Prefab: Plantilla de un objeto que se puede instanciar en tiempo de ejecución. Es esencial para crear mesas, sillas, lámparas, etc., en un editor.
  10. Raycasting: Lanzar un rayo desde un punto (por ejemplo la cámara) en una dirección y comprobar qué colisiona. En el editor se usa para saber en qué punto del suelo está el ratón para colocar/mover objetos.

Parte 2 – Código

  1. Singleton básico:
public class AudioManager : MonoBehaviour
{
    public static AudioManager Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
}
  1. Máquina de estados con enum:
public enum EditorState
{
    Neutral,
    Create,
    Move,
    Rotate,
    Delete
}

public class EditorManager : MonoBehaviour
{
    public EditorState currentState = EditorState.Neutral;

    public void OnCreateButton()
    {
        currentState = EditorState.Create;
        // actualizar UI, mensajes, etc.
    }

    public void OnMoveButton()
    {
        currentState = EditorState.Move;
    }

    public void OnRotateButton()
    {
        currentState = EditorState.Rotate;
    }

    public void OnDeleteButton()
    {
        currentState = EditorState.Delete;
    }

    public void OnCancel()
    {
        currentState = EditorState.Neutral;
    }
}
  1. Máquina de estados con interfaz:
public interface IEditorState
{
    void EnterState(EditorManager manager);
    void UpdateState(EditorManager manager);
    void ExitState(EditorManager manager);
}

public class MoveState : IEditorState
{
    public void EnterState(EditorManager manager)
    {
        // Mostrar mensaje: "Haz clic en un objeto para moverlo"
    }

    public void UpdateState(EditorManager manager)
    {
        // Lógica de selección de objeto y arrastre
    }

    public void ExitState(EditorManager manager)
    {
        // Limpiar selección, ocultar mensajes
    }
}
  1. Interfaz ISelectable:
public interface ISelectable
{
    void OnSelect();
    void OnDeselect();
}

public class SelectableObject : MonoBehaviour, ISelectable
{
    public void OnSelect()
    {
        // Cambiar color, activar outline, etc.
    }

    public void OnDeselect()
    {
        // Volver al color normal, desactivar outline
    }
}

// Uso desde un raycast
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
    ISelectable selectable = hit.collider.GetComponent<ISelectable>();
    if (selectable != null)
    {
        selectable.OnSelect();
    }
}
  1. Localización básica:
public class LocalizationManager : MonoBehaviour
{
    public static LocalizationManager Instance { get; private set; }

    private Dictionary<string, string> currentLanguageTable;

    private void Awake()
    {
        Instance = this;
        // Cargar idioma por defecto
        LoadLanguage("es");
    }

    public void LoadLanguage(string code)
    {
        // Aquí se cargaría un JSON o similar
        currentLanguageTable = new Dictionary<string, string>();
        currentLanguageTable["ui_create"] = "Crear";
        currentLanguageTable["ui_move"] = "Mover";
        // etc.
    }

    public string GetText(string key)
    {
        if (currentLanguageTable.TryGetValue(key, out string value))
            return value;
        return key; // fallback
    }
}

// Uso:
// textComponent.text = LocalizationManager.Instance.GetText("ui_create");

Parte 3 – Caso práctico

  1. Diagrama de estados (texto):
  • Estado Neutral: estado por defecto. Transiciones:
    • NeutralCreate al pulsar botón Crear.
    • NeutralMove al pulsar botón Mover.
    • NeutralRotate al pulsar botón Rotar.
    • NeutralDelete al pulsar botón Eliminar.
  • Estado Create:
    • Tras seleccionar un prefab se muestra un objeto fantasma que sigue al ratón.
    • Click izquierdo en el suelo: se fija el objeto y se vuelve a Neutral.
    • Click en suelo de cancelación / botón cancelar: CreateNeutral.
  • Estado Move:
    • Click en objeto seleccionable: pasa a subestado “arrastrando” el objeto.
    • Mientras se mantiene pulsado el ratón, el objeto sigue al punto de raycast.
    • Al soltar, el objeto se fija y se puede seleccionar otro o hacer click en suelo para volver a Neutral.
  • Estado Rotate:
    • Click en objeto: se selecciona.
    • Movimiento de ratón izquierda/derecha rota en eje Y.
    • Click para confirmar, posibilidad de seleccionar otro o click en suelo para Neutral.
  • Estado Delete:
    • Click en objeto: muestra popup de confirmación.
    • Confirmar: se elimina y se queda en Delete para borrar otro.
    • Cancelar o click en suelo: vuelve a Neutral.
  1. Flujo de creación de objeto:
  1. Usuario pulsa botón “Crear” en menú inferior.
  2. La UI avisa al EditorManager que cambia el estado a Create.
  3. El menú inferior se oculta parcialmente y aparece el menú lateral con la lista de prefabs.
  4. El usuario hace click en uno de los prefabs del menú lateral.
  5. El EditorManager instancia un objeto “preview” (fantasma) que sigue el ratón usando raycast sobre el suelo.
  6. Mientras el usuario mueve el ratón, el objeto se actualiza a la posición hit.point del raycast.
  7. Cuando el usuario hace click izquierdo en el suelo, se fija la posición del objeto (se desactiva el modo preview) y se cambia el estado a Neutral.
  8. Se actualiza la UI (mensaje, botones) para indicar que se ha salido del modo creación.
  9. Flujo de mover objeto:
  1. Usuario pulsa “Mover” en el menú inferior. EditorManager pasa a estado Move.
  2. Se muestra mensaje: “Haz clic sobre un objeto para moverlo”.
  3. El usuario hace click en un objeto con collider.
  4. Mediante raycast se detecta el objeto y se marca como objetoSeleccionado (se resalta visualmente).
  5. Mientras el usuario mantiene pulsado el botón del ratón, cada frame se lanza un raycast al suelo y se actualiza la posición del objeto al hit.point.
  6. Al soltar el botón del ratón, se fija la nueva posición, se quita el resaltado y el sistema vuelve a esperar otro click sobre un objeto.
  7. Si el usuario hace click en el suelo (sin objeto), se considera que sale del modo mover y se retorna a Neutral.
  8. Eliminación con confirmación:
  • Estado general Delete.
  • Subestado 1: Delete_SelectObject.
    • Mensaje: “Haz clic en un objeto para eliminarlo”.
    • Click en objeto: se guarda en objetoSeleccionado y se abre popup.
  • Subestado 2: Delete_ConfirmPopup.
    • Popup con botones “Eliminar” y “Mejor no”.
    • Si pulsa “Eliminar”: Destroy(objetoSeleccionado) y se vuelve a Delete_SelectObject para poder eliminar otro.
    • Si pulsa “Mejor no”: se cierra el popup, se limpia objetoSeleccionado y sigue en Delete_SelectObject.
    • Si el usuario hace click en el suelo o pulsa un botón de cancelar, se cierra el popup (si está abierto) y se vuelve al estado Neutral.
  1. Ejemplos de feedback:
  • Sonoro:
    • Sonido de click ligero para cada botón de la UI.
    • Sonido distinto al cambiar de herramienta (Create, Move, etc.) para indicar el nuevo modo.
    • Sonido “pop” al colocar definitivamente un objeto y “poof” al eliminarlo.
  • Visual / animación:
    • Menú inferior oculto parcialmente que se desliza hacia arriba al pasar el ratón o al pulsar.
    • Objeto seleccionado con outline o cambio de color cuando está activo en modos Mover/Rotar/Eliminar.
    • Pequeña animación de “squash and stretch” al fijar un objeto, y escala a cero o partículas al eliminar.

Borrador de post para Academia San Roque

Título del post
Simulacro de examen: patrones de diseño, máquinas de estados y editor interactivo en Unity

Contenido
En el módulo de Programación de Videojuegos estamos preparando al alumnado para un examen donde se combinan varios conceptos clave de desarrollo profesional en Unity:

  • Patrón Singleton aplicado a gestores globales (AudioManager, GameManager).
  • Máquinas de estados implementadas con enum e interfaces.
  • Uso de interfaces para estructurar el comportamiento de los objetos del juego.
  • Sistema de localización de textos (Localization) en Unity.
  • Diseño e implementación de un Editor Multimedia Interactivo: creación, movimiento, rotación y eliminación de objetos en un entorno 3D, con una interfaz de usuario completa y feedback sonoro/visual.

Para ayudarles a preparar la prueba, hemos elaborado un simulacro de examen completo que incluye:

  1. Preguntas teóricas sobre patrones de diseño, estados e interfaces.
  2. Ejercicios de código en C# centrados en Singleton, máquinas de estados, interfaces y localización.
  3. Un caso práctico basado en la práctica “Realización de un Editor Multimedia Interactivo”, donde el alumnado debe describir flujos de interacción (crear, mover, rotar y eliminar objetos) y proponer mejoras de usabilidad mediante feedback sonoro y visual.

El simulacro incluye soluciones orientativas y pasos explicados para que el alumnado pueda comparar sus respuestas, detectar fallos habituales y reforzar los conceptos más importantes antes del examen oficial.

Este material está pensado para alumnado de FP de Programación de Videojuegos, pero también puede resultar útil a cualquier persona que esté aprendiendo Unity y quiera practicar patrones de diseño, máquinas de estados y diseño de herramientas internas (editores) dentro del motor.

Contenido restringido

Acceso de usuarios existentes
   
Registro de un nuevo usuario
*Campo necesario

Categories:

Tags:

Comments are closed

Estado de acceso
ESTADO DE ACCESO
TRADUCTORES
COMPARTENOS
Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert
error: CONTENIDO PROTEGIDO