Parte 1 – Preguntas teóricas cortas (10 × 1 punto)
Responde de forma breve y clara.
- Explica con tus palabras qué es el patrón Singleton y pon un ejemplo de caso de uso típico en videojuegos.
- Indica dos problemas o riesgos de abusar del patrón Singleton en un proyecto grande.
- ¿Qué es una máquina de estados (State Machine) y por qué es útil en el desarrollo de videojuegos?
- Diferencia entre implementar una máquina de estados con
enumy coninterfaces. - ¿Qué ventaja tiene usar interfaces en Unity para estructurar el comportamiento de los objetos del juego?
- Define brevemente qué es la localización (Localization) en un videojuego.
- ¿Por qué es importante separar la lógica del juego de los textos mostrados en pantalla cuando hablamos de localización?
- En el contexto de UI en Unity, explica qué es y para qué sirve un
ManageroGameManager. - ¿Qué es un Prefab en Unity y por qué es tan importante en un editor de objetos como el de la práctica?
- 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.
- Implementa un Singleton básico en Unity para un
AudioManagerque 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.
- Define un
enumllamadoEditorStatecon los estados:Neutral,Create,Move,Rotate,Delete. Escribe un fragmento de código dentro de unEditorManagerque cambie de estado cuando pulsemos los botones de la UI. - Diseña una interfaz
IEditorStatepara 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 concretaMoveStateque la implemente. - Escribe un pequeño ejemplo de interfaz en C# llamada
ISelectableque obligue a los objetos a implementar un métodoOnSelect()yOnDeselect(). Después, muestra cómo la usarías en un objeto del escenario. - 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
LocalizationManagery 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.
- 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.
- 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.
- 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.
- Describe cómo implementarías el sistema de eliminación con confirmación (popup) usando estados o subestados (por ejemplo:
Delete_SelectObject,Delete_ConfirmPopup). - 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
- 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,AudioManageroUIManager. - 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.
- 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.).
- Con
enumtenemos un únicoswitchgrande dentro de una clase (más simple, pero puede crecer mucho). Con interfaces creamos una jerarquía de clasesStateque implementan una interfaz y encapsulan su comportamiento, lo que favorece la extensibilidad y el código limpio. - 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.
- 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.
- 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. GameManager/EditorManager: Objeto central que coordina la lógica global: estado actual, comunicación con la UI, instanciación de objetos, etc.- 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.
- 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
- 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);
}
}
- 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;
}
}
- 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
}
}
- 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();
}
}
- 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
- Diagrama de estados (texto):
- Estado
Neutral: estado por defecto. Transiciones:Neutral→Createal pulsar botón Crear.Neutral→Moveal pulsar botón Mover.Neutral→Rotateal pulsar botón Rotar.Neutral→Deleteal 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:
Create→Neutral.
- 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
Deletepara borrar otro. - Cancelar o click en suelo: vuelve a
Neutral.
- Flujo de creación de objeto:
- Usuario pulsa botón “Crear” en menú inferior.
- La UI avisa al
EditorManagerque cambia el estado aCreate. - El menú inferior se oculta parcialmente y aparece el menú lateral con la lista de prefabs.
- El usuario hace click en uno de los prefabs del menú lateral.
- El
EditorManagerinstancia un objeto “preview” (fantasma) que sigue el ratón usando raycast sobre el suelo. - Mientras el usuario mueve el ratón, el objeto se actualiza a la posición
hit.pointdel raycast. - 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. - Se actualiza la UI (mensaje, botones) para indicar que se ha salido del modo creación.
- Flujo de mover objeto:
- Usuario pulsa “Mover” en el menú inferior.
EditorManagerpasa a estadoMove. - Se muestra mensaje: “Haz clic sobre un objeto para moverlo”.
- El usuario hace click en un objeto con collider.
- Mediante raycast se detecta el objeto y se marca como
objetoSeleccionado(se resalta visualmente). - 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. - 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.
- Si el usuario hace click en el suelo (sin objeto), se considera que sale del modo mover y se retorna a
Neutral. - 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
objetoSeleccionadoy se abre popup.
- Subestado 2:
Delete_ConfirmPopup.- Popup con botones “Eliminar” y “Mejor no”.
- Si pulsa “Eliminar”:
Destroy(objetoSeleccionado)y se vuelve aDelete_SelectObjectpara poder eliminar otro. - Si pulsa “Mejor no”: se cierra el popup, se limpia
objetoSeleccionadoy sigue enDelete_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.
- 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
enume 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:
- Preguntas teóricas sobre patrones de diseño, estados e interfaces.
- Ejercicios de código en C# centrados en Singleton, máquinas de estados, interfaces y localización.
- 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
Comments are closed