Comparación entre el Diseño Orientado a Datos (DOD) y la Programación Orientada a Objetos (OOP): Análisis de Arquitectura y Rendimiento en Unity DOTS y Unreal Engine 5
Unity

Comparación entre el Diseño Orientado a Datos (DOD) y la Programación Orientada a Objetos (OOP): Análisis de Arquitectura y Rendimiento en Unity DOTS y Unreal Engine 5

AutorGameDev Base
Fecha17 de octubre de 2026
25 min de lectura

Mass de Unreal con DOTS: Optimización de la caché de CPU y procesamiento paralelo para juegos AAA fluidos

Este informe compara en profundidad los enfoques de Diseño Orientado a Datos (DOD) y Programación Orientada a Objetos (OOP) tradicional en los motores de juegos Unity y Unreal Engine 5 desde la perspectiva de los desarrolladores de juegos. La investigación pretende analizar los resultados de rendimiento fundamentales de la optimización del diseño de memoria, el uso de la caché de CPU y la compatibilidad con multihilos (multithreading). El informe profundiza en los detalles técnicos mediante ejemplos de código concretos y pasos de integración en las versiones actuales de los motores. Además, inspirándose en títulos como Kena: Bridge of Spirits, se evalúan los efectos estratégicos de estas elecciones arquitectónicas para juegos dirigidos a plataformas de alta gama (AAA), de mundo abierto y móviles. Cada afirmación se demuestra basándose en las fuentes proporcionadas.

Diferencias clave de paradigma: lógica de almacenamiento de datos y resultados de rendimiento

La diferencia fundamental entre el Diseño Orientado a Datos (DOD) y la Programación Orientada a Objetos (OOP) se basa en cómo se agrupan los datos como unidades lógicas y cómo se almacenan en la memoria. Mientras que la OOP se centra en objetos que empaquetan los datos junto con la funcionalidad, el DOD pretende optimizar los patrones de acceso a la memoria manteniendo juntos los datos del mismo tipo. Esta distinción en el paradigma básico es de una importancia crítica en términos de la capacidad para explotar plenamente el potencial de rendimiento de las arquitecturas informáticas modernas .

La Programación Orientada a Objetos (OOP) suele basarse en la lógica de «almacenar los datos dentro del objeto». Si se piensa en un objeto de personaje, este tendrá propiedades que incluyen diferentes tipos de datos como Position (Posición), Health (Salud) y Velocity (Velocidad). Cada objeto de personaje ocupa su propio espacio de dirección único en la memoria. Si hay cientos o miles de caracteres en un juego complejo, estos objetos se distribuyen aleatoriamente por la memoria. Cuando se ejecuta una operación como mover todos los personajes en un bucle Update, la CPU tiene que acceder a los datos de Position de cada personaje por separado. En este caso, es poco probable que la información de Position del objeto CharacterA y su información de Health se encuentren en el bloque de memoria; como son objetos diferentes, están en direcciones distintas. Del mismo modo, la información de Position de CharacterB probablemente esté bastante lejos de los datos de CharacterA. Esto hace que la CPU acceda a bloques de memoria diferentes y no contiguos cada vez que necesita extraer datos de la memoria. Esta situación crea un cuello de botella de rendimiento que contradice la estructura de las CPU modernas . Las repentinas congelaciones y caídas de FPS experimentadas en juegos como Kena: Bridge of Spirits son un indicador típico de los problemas de rendimiento causados por este tipo de patrones de acceso a la memoria basados en OOP y poco amigables con la caché .

El Diseño Orientado a Datos (DOD), por otro lado, invierte esta lógica. El DOD pone en el centro no a los objetos, sino a los datos que componen su contenido, y pretende almacenar los datos del mismo tipo de forma tan compacta y contigua en la memoria como sea posible. La aplicación más común y formal de este enfoque es la arquitectura Entity Component System (ECS). ECS define entidades complejas como "entidades" simples, añade los comportamientos y propiedades de estas entidades mediante "componentes" independientes y los procesa a través de "sistemas" (systems) que utilizan estos componentes. En la base de esta arquitectura se encuentran estructuras de datos como Structure of Arrays (SoA) o similares . A diferencia de la lógica AoS (Array of Structures) en OOP, SoA se refiere a la creación de una matriz separada para cada tipo de datos. Por ejemplo, la información de Position de todos los personajes se almacena de forma contigua en una sola matriz (positions[]), la información de Health de todos los personajes en otra matriz (health[]) y la información de Velocity de todos los personajes en una tercera matriz (velocity[]). Gracias a esta disposición, la tarea de actualizar las posiciones de todos los personajes al mismo tiempo requiere que la CPU cargue un gran bloque de datos solo una vez. El patrón de acceso a la memoria contigua permite a la CPU utilizar de manera eficiente las cachés aceleradas como L1 y L2, ya que cuando se cargan los primeros datos, los datos adyacentes también se almacenan en la caché y estos datos se pueden utilizar una y otra vez . La documentación de ECS de Unity enfatiza que los datos se almacenan en bloques de memoria contiguos de tamaño fijo llamados Chunks y lo bien que esto se alinea con las líneas de caché de la CPU . Este cambio simple pero efectivo mejora drásticamente el rendimiento de los algoritmos que trabajan en conjuntos de datos grandes.

CaracterísticaProgramación Orientada a Objetos (OOP)Diseño Orientado a Datos (DOD/ECS)Lógica de agrupación de datos«Almacenar los datos dentro del objeto» (AoS - Struct of Array)«Almacenar los mismos datos juntos» (SoA - Array of Struct)Diseño de memoriaLos datos se encuentran en memoria aleatoria y distribuidaLos datos se almacenan de forma contigua y compacta en la memoriaPatrón de acceso a datosLos accesos dispersos y cruzados son comunesLos accesos contiguos y locales son predominantesEficiencia de cachéGeneralmente baja (alto número de fallos de caché)Generalmente alta (bajo número de aciertos de caché)Composición arquitectónicaCentrada en la herencia (inheritance) y la abstracciónEstructura flexible compuesta de componentesAplicación típicaUnity GameObjects, Unreal ActorsUnity DOTS/Entities, Unreal Mass

Estos paradigmas fundamentales han seguido caminos de desarrollo divergentes para los motores de juegos modernos como Unity y Unreal Engine 5. Mientras que Unity conserva la arquitectura GameObject basada en OOP, ha introducido una pila completamente nueva orientada a datos llamada DOTS (Data-Oriented Technology Stack) . Esto ofrece a los desarrolladores la flexibilidad de utilizar ambos enfoques juntos en diferentes partes de un proyecto. Por ejemplo, mientras que la interfaz de usuario y algunas mecánicas de juego especiales se gestionan con OOP, la simulación de física o el control de una gran cantidad de unidades de IA se pueden realizar con DOD . Dicho esto, la arquitectura principal de Unreal Engine 5 está profundamente orientada a OOP con la herencia de UObject . Sin embargo, Unreal también ha desarrollado soluciones específicas para áreas que requieren un alto rendimiento. La más importante de ellas es Mass Entity Framework. Mass es un marco diseñado específicamente para escenarios en los que cientos o miles de unidades de IA se ejecutan simultáneamente, capaz de realizar cálculos orientados a datos . El propósito de Mass es superar los límites de rendimiento de la arquitectura Actor/Component y ofrece la oportunidad de paralelizar organizando tareas específicas (por ejemplo, gestión de unidades a gran escala) de manera orientada a datos . Además, el sistema de física Chaos también ha evolucionado hacia enfoques orientados a datos e incluye mecanismos de almacenamiento en caché para evitar el recálculo de simulaciones . Por lo tanto, ambos motores avanzan hacia la combinación de la flexibilidad de OOP y el rendimiento de DOD, pero siguen diferentes estrategias derivadas de sus diferentes antecedentes arquitectónicos.

Diseño de memoria y análisis de la eficiencia de la caché de CPU

El rendimiento de los motores de juegos modernos está limitado por el hecho de que la velocidad a la que la CPU extrae datos de la RAM es mucho más lenta que su propia velocidad de procesamiento. La forma de superar este "cuello de botella de von Neumann" es utilizar las cachés L1, L2 y L3 de la CPU, que son extremadamente rápidas pero pequeñas, con la mayor eficiencia posible . Cuando la CPU accede a una dirección de memoria, en lugar de leer solo los datos de esa dirección de la memoria, también introduce en la caché los pocos bytes situados inmediatamente a su lado (generalmente una «línea de caché» de 64 bytes) . Si el siguiente dato necesario está dentro de esta línea de caché, la CPU puede acceder a él rápidamente; esta situación se denomina "acierto de caché" (cache hit). De lo contrario, tiene que cargar un nuevo bloque de datos de la RAM lenta, lo que se denomina "fallo de caché" (cache miss), un importante cuello de botella en el rendimiento. El Diseño Orientado a Datos (DOD) ofrece una solución arquitectónica que pretende aumentar la tasa de aciertos de caché evitando los patrones de acceso a la memoria dispersos aportados por la OOP .

El enfoque de la Programación Orientada a Objetos (OOP) conduce naturalmente a un diseño de memoria disperso. Un objeto Character alberga miembros que contienen diferentes tipos de datos, como position, health y rotation. Cada objeto Character comienza con su propia dirección única en la memoria. Cuando se desea llamar a la función update de todos los personajes en un bucle, la CPU tiene que ir al principio de cada objeto Character en la memoria. Los miembros (datos) de estos objetos no tienen por qué estar cerca unos de otros. Por ejemplo, el miembro position de CharacterA y el miembro health de CharacterB quizás no se encuentren dentro de la misma línea de caché de 64 bytes. Esto hace que, cuando queremos procesar los datos de manera secuencial, la CPU se vea obligada a saltar constantemente a direcciones de memoria diferentes y distantes. Cambiar a una nueva dirección cada vez significa descartar la línea de caché anterior, lo que a su vez provoca una alta tasa de fallos de caché. Para las plataformas móviles, esta situación es aún más crítica; hacer más trabajo consumiendo menos energía es una ventaja fundamental para los dispositivos móviles .

El Diseño Orientado a Datos (DOD) ofrece una solución directa a este problema. La arquitectura DOTS en Unity almacena los datos en bloques de memoria de tamaño fijo y totalmente contiguos llamados "Chunks" . Cada Chunk contiene una matriz "Structure of Arrays" (SoA) compuesta de componentes del mismo tipo. Por ejemplo, todos los datos relacionados con un componente llamado Translation (Posición) se almacenan en un único bloque de memoria continuo. Del mismo modo, los datos de Rotation (Rotación) residen secuencialmente en otro chunk o en una matriz SoA separada dentro del mismo chunk. Esta disposición permite que un sistema (por ejemplo, MovementSystem) procese todos los datos de Translation dentro de un único bucle for. Al ejecutar este bucle, la CPU carga un gran bloque de datos de la memoria solo una vez y reutiliza estos datos una y otra vez, ya que todos los datos relacionados están muy cerca unos de otros. Esto permite un uso eficiente de las cachés de la CPU y reduce drásticamente la tasa de fallos de caché . El hecho de que las entidades de la arquitectura ECS de Unity reúnan todos los datos de sus componentes en un solo bloque de memoria maximiza esta eficiencia . Y lo que es más importante, la disposición de los datos en la memoria en la arquitectura DOTS de Unity coincide perfectamente con la propia organización de la memoria de la CPU (por ejemplo, las líneas de 64 bytes de la caché de datos L1) . Los tamaños y las alineaciones de los campos de datos se optimizan según los requisitos de las líneas de caché. Esto se convierte en una ventaja significativa, especialmente en CPU móviles modernas como Arm Cortex-X4, ya que el rendimiento de estas arquitecturas está

directamente relacionado con que el ancho de banda de la memoria y la eficiencia de la caché estén al nivel más alto.

Una filosofía similar existe en Unreal Engine 5. Mass Entity Framework permite un almacenamiento de datos más eficiente en la memoria al agrupar las entidades y sus componentes según estructuras de datos complejas llamadas Archetype. Un Archetype define un conjunto específico de componentes. Por ejemplo, puedes crear un Archetype que sea "capaz de moverse y tenga un arma". Luego, todas las entidades que poseen este tipo de componentes (por ejemplo, 500 soldados) se almacenan automáticamente en los chunks pertenecientes a este Archetype. Esto permite que las consultas se ejecuten de forma más eficiente y que se desperdicie menos caché de la CPU. El hecho de que se realicen optimizaciones de bajo nivel orientadas a Mass en versiones más nuevas como UE 5.7 es una prueba clara de que este marco está enfocado en el rendimiento. Además, el sistema de física Chaos también ha evolucionado hacia enfoques orientados a datos e incluye mecanismos de almacenamiento en caché para evitar el recálculo de simulaciones. Herramientas como Chaos Cache Manager garantizan que una simulación se calcule una vez y se reproduzca más de una vez, evitando que la CPU realice la misma operación una y otra vez. Esto proporciona una ganancia de rendimiento significativa en operaciones intensivas para la CPU, especialmente en destrucción dinámica o simulaciones de fluidos.

En conclusión, la optimización del diseño de memoria y la eficiencia de la caché de la CPU son uno de los factores más críticos que determinan el rendimiento de los motores de juegos modernos. Mientras que el enfoque OOP desperdicia el potencial de las cachés de la CPU al hacer que los patrones de acceso a los datos sean naturalmente dispersos, el DOD ofrece una solución directa a este problema. DOTS de Unity y el framework Mass de Unreal Engine 5 están diseñados para aumentar el rendimiento mediante el uso eficiente de las cachés de la CPU, evitando los patrones de acceso a la memoria dispersos en ambos motores. Este cambio arquitectónico es de vital importancia para proporcionar la experiencia fluida deseada, especialmente en juegos que ofrecen un mundo rico y vivo como Kena: Bridge of Spirits. Para las plataformas móviles, estas optimizaciones proporcionan ahorro de energía al ofrecer la oportunidad de hacer más trabajo con un menor consumo de energía.

Integración de multiproceso y capacidad de procesamiento paralelo

Los procesadores modernos cuentan con múltiples núcleos de procesamiento, y cada uno de estos núcleos puede funcionar de forma independiente. El multiproceso es la capacidad de utilizar esta potencia de procesamiento paralelo en la lógica real del juego. Sin embargo, la estructura de código basada en OOP requiere mecanismos de sincronización complejos para evitar conflictos de datos, lo que puede provocar tirones inesperados y la inactividad de los núcleos de la CPU. El diseño orientado a datos (DOD) ofrece una solución arquitectónica a estos problemas, facilitando de forma natural la ejecución paralela del código.

En el enfoque de la programación orientada a objetos (OOP), el código suele ejecutarse de forma sincrónica en un único hilo principal (por ejemplo, GameThread en Unreal o Main Thread en Unity). Este hilo procesa gran parte de la lógica del juego, como la entrada del jugador, la lógica de la inteligencia artificial y las actualizaciones físicas. Aunque otros subsistemas (renderizado, audio, física) suelen ejecutarse en hilos separados, estos hilos suelen funcionar independientemente del hilo principal. Dado que la mayor parte de su código se ejecuta en un solo hilo, los demás núcleos de la CPU suelen permanecer inactivos. Si un desarrollador desea añadir paralelismo en un proyecto basado en OOP, debe utilizar mecanismos de sincronización como lock, mutex o semaphore para evitar conflictos de datos. Estos mecanismos pueden hacer que otros hilos esperen a que un hilo termine la sección crítica (por ejemplo, una operación de escritura en una lista). El tiempo de espera significa que un núcleo de la CPU se queda sin trabajar, lo que provoca tirones inesperados (hitch) y una caída general del rendimiento. Unreal Engine 5 incluye compatibilidad nativa con multiproceso, pero a veces el motor se atasca en un único hilo y los desarrolladores tienen una capacidad limitada para aprovecharlo al máximo. Esto significa que una gran parte de la potencia potencial de la CPU se desperdicia.

El diseño orientado a datos (DOD) es un paradigma arquitectónico diseñado para el procesamiento paralelo. El DOD adopta principios que eliminan los conflictos de datos entre los hilos que leen los datos de un solo lugar y los escriben en un solo lugar. La arquitectura DOTS de Unity es el ejemplo más claro de esta filosofía y combina dos tecnologías clave: Job System y Burst Compiler. Job System divide su código en partes y le permite ejecutarlas en paralelo en diferentes núcleos de la CPU. Un bucle Entities.ForEach dentro de un SystemBase se compila en realidad como un trabajo (job). Este trabajo elimina las condiciones de carrera (data races) al evitar que los datos se modifiquen en un solo hilo. Cada trabajo se puede ejecutar de forma segura en diferentes núcleos de la CPU. Esto permite lograr la paralelización sin necesidad de complejos códigos de sincronización para evitar conflictos de datos. Burst Compiler es una optimización del compilador que traduce el código de C# en código nativo de C++ altamente optimizado. Burst utiliza el backend de LLVM para compilar el código al nivel de C/C++, lo que le permite alcanzar el rendimiento que se obtendría con C++. Es extremadamente eficiente, especialmente para bucles, cálculos matemáticos y operaciones de conversión de datos. Cada SystemBase de su sistema (por ejemplo, MovementSystem) funciona en realidad como un trabajo y puede ser optimizado por Burst para ejecutarse en paralelo en diferentes núcleos de la CPU. Esto elimina las condiciones de carrera al evitar que los datos se modifiquen en un solo hilo y garantiza la seguridad de la paralelización.

En Unreal Engine 5, Mass Entity Framework también adopta principios similares que facilitan el uso de multiproceso. Mass simplifica el uso del multiproceso al organizar una tarea específica (por ejemplo, ejecutar la lógica de búsqueda de caminos de cientos de inteligencias artificiales) de forma orientada a datos y ejecutarla en paralelo en varios hilos. Mass también está diseñado para integrarse con otros modelos de hilos de Unreal, como el grafo de renderizado. Esto aumenta el rendimiento global al permitir que diferentes partes del motor se ejecuten en paralelo en diferentes hilos. A partir de la versión 5.0 de Unreal Engine, el propio motor también ha realizado mejoras para aumentar el uso del multiproceso; por ejemplo, las actualizaciones de estabilidad y rendimiento realizadas en Vulkan RHI han permitido un mejor uso del multiproceso tanto en plataformas de escritorio como móviles.

Ejemplo de código concreto (Unity DOTS):


public class CharacterController_OOP : MonoBehaviour
{
    public float moveSpeed = 5f;
    void Update()
    {
        
        foreach(var character in allCharacters)
        {
            character.Move(); 
        }
    }
}

using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
public class MovementSystem_DOD : SystemBase
{
    protected override void OnUpdate()
    {
        float deltaTime = Time.DeltaTime;
       
        Entities.ForEach((ref Translation translation, in Rotation rotation, in MoveSpeed speed) =>
        {
            translation.Value += speed.value * deltaTime * math.rotate(rotation.Value, new float3(0, 0, 1)).normalize();
        }).Schedule();
    }
}

En este ejemplo, mientras que el enfoque de OOP se ejecuta de forma sincrónica en el hilo principal, el enfoque de DOD programa el bucle Entities.ForEach dentro de OnUpdate como un trabajo que el Job System puede procesar en paralelo. Este trabajo puede ser optimizado por Burst y ejecutarse simultáneamente en diferentes núcleos de la CPU. Esto elimina las condiciones de carrera al evitar que los datos se modifiquen en un único hilo y garantiza la seguridad de la paralelización.

En conclusión, el DOD facilita de forma natural el uso del multiproceso al eliminar las dificultades de sincronización y los tirones inesperados que conlleva el OOP. Tanto DOTS de Unity como el framework Mass de Unreal Engine 5 están diseñados para mejorar el rendimiento utilizando de manera eficiente las cachés de la CPU y evitando los patrones de acceso a memoria dispersos. Este cambio arquitectónico es de vital importancia para garantizar la experiencia fluida deseada, especialmente en juegos que ofrecen un mundo rico y vivo como Kena: Bridge of Spirits. Para las plataformas móviles, estas optimizaciones ofrecen la oportunidad de realizar más trabajo consumiendo menos energía, lo que proporciona un ahorro energético.

Pila de tecnología orientada a datos (DOTS) dentro del ecosistema de Unity

Unity mantiene la arquitectura GameObject basada en OOP, al tiempo que ofrece una pila tecnológica completamente nueva llamada Pila de tecnología orientada a datos (DOTS) para aplicaciones que requieren un alto rendimiento. DOTS optimiza la disposición de la memoria basándose en los principios del diseño orientado a datos, mejora la eficiencia de la caché de la CPU y ofrece compatibilidad con el multiproceso de forma nativa. Esta sección analiza los componentes básicos de DOTS, ejemplos de código concretos y el proceso de integración.

La base de DOTS la forma el paquete de Entidades. Este paquete proporciona elementos de ECS (Entity Component System) como Entidades, Datos de componentes y Sistemas de forma fundamental. La filosofía básica aquí es separar los datos de la funcionalidad y almacenarlos de manera más eficiente en la memoria. 1. Entidades: Las entidades son contenedores vacíos con identificadores únicos que no transportan ningún dato. Una entidad no es un objeto; es solo un EntityId. Esto hace que sea muy ligera en la memoria y permite crearlas y destruirlas rápidamente. 2. Datos de componentes: Son estructuras (structs) que transportan datos. Deben ser una estructura y no se debe utilizar la herencia. Por ejemplo, se definen estructuras simples de transporte de datos como Translation { public float3 Value; } o Health { public int Value; }. Estas estructuras implementan la interfaz IComponentData. 3. Sistemas: Es la lógica que procesa estos datos. Las clases que derivan de la clase SystemBase utilizan consultas (queries) para seleccionar tipos de datos específicos (componentes) y realizan operaciones sobre dichos datos. El método OnUpdate se programa como un trabajo y suele contener el bucle Entities.ForEach.

Ejemplo de código concreto (Unity DOTS): El siguiente código compara cómo se aborda de forma diferente el movimiento de un personaje con OOP y con DOTS:


public class PlayerController_OOP : MonoBehaviour
{
    public float moveSpeed = 5f;
    void Update()
    {
      
        float moveInput = Input.GetAxis("Horizontal");
        transform.Translate(Vector3.right * moveInput * moveSpeed * Time.deltaTime);
    }
}

public struct Translation : IComponentData
{
    public float3 Value;
}
public struct Rotation : IComponentData
{
    public quaternion Value;
}
public struct MoveSpeed : IComponentData
{
    public float value;
}
// 2. Sistema que expresa la lógica del juego
public class MovementSystem : SystemBase
{
    protected override void OnUpdate()
    {
       
        float deltaTime = Time.DeltaTime;
     
        Entities
            .WithName("MoveEntities")
            .ForEach((ref Translation translation, in Rotation rotation, in MoveSpeed speed) =>
            {
                translation.Value += speed.value * deltaTime * math.normalize(math.mul(rotation.Value, new float3(0, 0, 1)));
            }).Schedule();

        
        Dependency.Complete();
    }
}

En este ejemplo, el enfoque de DOD demuestra cómo se agrupan y procesan los datos en la memoria. El bucle dentro de Entities.ForEach se compila como un único trabajo que puede ser optimizado por Burst y ejecutado en paralelo en diferentes núcleos de la CPU. Esto elimina las condiciones de carrera al evitar que los datos se modifiquen en un único hilo y garantiza la seguridad de la paralelización.

Pasos de integración (Unity DOTS): Integrar DOTS en un proyecto de Unity comienza con la creación de un proyecto estándar de Unity y, a continuación, la adición de los paquetes necesarios a través del Administrador de paquetes (Package Manager):

  1. Administrador de paquetes: Vaya al menú Edit > Project Settings > Packages o al menú Window > Package Manager dentro del IDE.

  2. Añadir los paquetes necesarios: Se pueden añadir los siguientes paquetes básicos de DOTS para el proyecto:

    • com.unity.entities: Es el paquete que proporciona la arquitectura ECS básica.

    • com.unity.jobs: Es el paquete necesario para ejecutar el sistema de trabajos.

    • com.unity.burst: Es el paquete que traduce el código de C# a código nativo de C++ y lo optimiza.

    • com.unity.mathematics: Proporciona tipos matemáticos básicos como operaciones de vectores y matrices utilizadas para DOTS.

    • com.unity.netcode.entities: Es necesario para aplicaciones DOTS compatibles con red.

  3. Definir la estructura de datos: Se crean estructuras (structs) que implementan la interfaz IComponentData. Estas estructuras transportan datos, pero no pueden contener funciones.

  4. Crear sistemas: Se crean clases que derivan de la clase SystemBase. Estas clases anulan (override) métodos del ciclo de vida como OnUpdate, OnFixedUpdate o OnCreate.

  5. Integración del renderizador: Se necesita un renderizador para mostrar en pantalla las entidades creadas con DOTS. Inicialmente, es práctico utilizar Hybrid Renderer para reflejar los datos de DOTS en los GameObjects existentes. Esto le permite utilizar la arquitectura orientada a datos de DOTS mientras mantiene su canalización de renderizado (rendering pipeline) actual. Posteriormente, se pueden utilizar los paquetes de Entities Graphics que se pueden integrar con URP o HDRP.

Implicaciones estratégicas para mundos abiertos AAA y optimización móvil: Juegos como Kena: Bridge of Spirits requieren tanto un entorno rico y detallado (mundo abierto AA) como un control de personajes fluido y reactivo. Las plataformas móviles añaden una capa adicional de dificultad en términos de potencia limitada de CPU/GPU y duración de la batería.

Rendimiento y fluidez: El DOD es una de las herramientas más potentes para reducir los tirones repentinos y las caídas de FPS, especialmente en proyectos basados en OOP. Los problemas de tirones (stutters) en el juego Kena ponen de manifiesto la diferencia que puede aportar el enfoque de DOD. El DOD proporciona una mayor capacidad de procesamiento de datos utilizando toda la potencia de la CPU, lo que permite aspirar a unos 60 FPS más estables.

Optimización para plataformas móviles:

  • Potencia de la CPU: Las CPU móviles (por ejemplo, Arm Cortex-X4) son cada vez más potentes, pero la eficiencia energética sigue siendo un factor crítico. El DOD puede minimizar el tiempo de inactividad (idle) de la CPU, lo que le permite realizar más trabajo consumiendo menos energía. Las mejoras como la reducción del 33% en el ancho de banda en la arquitectura Cortex-X4 de Arm pueden significar que las aplicaciones que se ejecutan con DOD se beneficiarán aún más de esto.

  • Gestión de memoria: El uso de memoria debe gestionarse meticulosamente en las plataformas móviles. DOTS puede reducir el uso general de memoria trabajando con datos más compactos y asignados en la memoria. Tecnologías como los formatos de compresión AssetBundle de Unity y SVT (Virtual Texturing), cuando se combinan con la organización de datos de DOD, crean una estructura muy eficiente para plataformas móviles.

  • Minificación ProGuard: Las herramientas como la minificación ProGuard para Android, cuando se utilizan junto con el código optimizado generado con DOD, pueden mejorar aún más el tamaño de distribución y el rendimiento.

En conclusión, la pila DOTS de Unity es un conjunto de herramientas potente diseñado para superar los límites de escalabilidad de OOP. Los desarrolladores pueden utilizar DOTS en áreas donde el rendimiento del proyecto es crítico (física, inteligencia artificial, sistemas de partículas), adoptando un enfoque híbrido sin alterar la estructura basada en OOP existente.

Enfoques arquitectónicos centrados en el rendimiento en Unreal Engine 5: Mass y Chaos

Unreal Engine 5, en su arquitectura base, está profundamente orientado a la programación orientada a objetos (OOP) debido a su herencia de UObject. Sin embargo, las demandas de alto rendimiento y escalabilidad necesarias para los juegos de calidad AAA han obligado al propio motor a evolucionar y adaptarse a enfoques orientados a datos. Para satisfacer esta necesidad, Unreal Engine 5 ofrece dos enfoques arquitectónicos principales centrados en el rendimiento: Mass Entity Framework y Chaos Physics. Estos dos sistemas van más allá de la estructura basada en OOP de Unreal al adoptar principios de diseño orientados a datos, proporcionando un aumento de rendimiento vital, especialmente para simulaciones a gran escala y simulaciones físicas.

Mass Entity Framework: Gameplay orientado a datos Mass es un marco diseñado para cálculos orientados a datos en Unreal Engine 5, y se ha desarrollado específicamente para escenarios donde cientos o miles de unidades de juego se gestionan simultáneamente. En lugar de reemplazar el Gameplay de Unreal, Mass está diseñado como una capa orientada a datos y apta para el procesamiento en paralelo, construida sobre la arquitectura existente de Actor/Component. Su filosofía principal es mejorar el rendimiento agrupando una gran cantidad de conjuntos de datos similares de manera más eficiente en la memoria y procesándolos en paralelo a través de múltiples hilos.

Los componentes principales de la arquitectura Mass son los siguientes:

  • Entidad: En Mass, una entidad es un contenedor vacío con una identidad única que no transporta ningún dato. Esto la hace extremadamente ligera, al igual que los Entitys en Unity.

  • Componente: Es la estructura de datos que transporta la información. Puede ser un valor float, un vector o una estructura compleja. Los componentes permiten agrupar los datos en la memoria.

  • Sistema: Es la lógica que selecciona entidades con componentes específicos y las procesa. Estos sistemas se pueden paralelizar mientras procesan los datos.

  • Arquetipo: Este es el componente más importante y único de la arquitectura Mass. Un Arquetipo define un conjunto específico de componentes. Por ejemplo, se puede crear un Arquetipo con los componentes "Position", "Velocity" y "AIController". Luego, todas las entidades que poseen este tipo de componentes (por ejemplo, 1000 unidades enemigas) se almacenan automáticamente en los bloques de memoria pertenecientes a este Arquetipo. Esto permite que las consultas se ejecuten de manera más eficiente y que se desperdicie menos caché de la CPU.

Ejemplo de código concreto (Unreal Engine 5 - Mass): Mass se utiliza normalmente con C++ o a través de nodos personalizados en Blueprint. A continuación, se muestra un ejemplo de pseudocódigo que da una idea general de la estructura básica de un sistema Mass:


USTRUCT(BlueprintType)
struct FPositionComponent
{
    GENERATED_BODY()
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
    FVector Location;
};
USTRUCT(BlueprintType)
struct FVelocityComponent
{
    GENERATED_BODY()
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
    FVector Velocity;
};

class FMovementSystem : public FGlobalComponentSystem
{
public:
    virtual void Tick(float DeltaTime) override
    {
      
        Query.ForEach(
            [&](FEntityHandle Entity, FMutableRef<FPositionComponent> PositionComp, FMutableRef<FVelocityComponent> VelocityComp)
            {
               
                PositionComp->Location += VelocityComp->Velocity * DeltaTime;
            });
    }
};
// 3. El sistema se registra y se integra con el motor
IMPLEMENT_MODULE(MyModule, MyModuleName);

En este ejemplo, la llamada Query.ForEach forma la base de la estructura orientada a datos de Mass. El sistema selecciona todas las entidades con los componentes especificados y procesa los datos de estas entidades en un solo bucle. Este bucle puede ser ejecutado en diferentes hilos por los mecanismos internos de procesamiento en paralelo de Unreal. En versiones más recientes como UE 5.7, las optimizaciones

de bajo nivel para Mass continúan, lo que es una clara prueba de que el marco está enfocado en el rendimiento.

Física Chaos y almacenamiento en caché:

Chaos es el motor de física predeterminado en Unreal Engine 5 y está diseñado como parte de la arquitectura OOP. Sin embargo, el propio Chaos también ha adoptado principios orientados a datos y está diseñado para mejorar el rendimiento, especialmente para simulaciones con uso intensivo de CPU. Chaos admite características como juntas rompibles (breakable joints) y restitución de colisiones.

La característica más importante del aspecto enfocado al rendimiento de Chaos es la capacidad de almacenamiento en caché de las simulaciones. Si una simulación física compleja (por ejemplo, la destrucción de un edificio grande) se recalculase en cada fotograma, esta operación sería muy costosa. Chaos Cache Manager está diseñado para resolver este problema. El desarrollador graba una simulación y el motor guarda una copia de esta simulación en la memoria o en el disco. Luego, cuando la simulación se reproduce de nuevo, el motor utiliza los datos guardados sin realizar recálculos, lo que ahorra un tiempo de CPU significativo. Esto es extremadamente efectivo, especialmente para efectos repetitivos u objetos dinámicos. Sin embargo, este sistema debe ajustarse meticulosamente para que funcione correctamente; si se configura incorrectamente, los datos de caché no se sincronizarán y los objetos podrán saltar a sus posiciones originales.

Pasos de integración (Unreal Engine 5):

Integrar sistemas como Mass y Chaos en un proyecto de Unreal suele ser más fácil debido a que ya están disponibles de forma predeterminada en la configuración del motor.

  1. Activación de la máscara: Puede activar el plugin de Mass desde la configuración del proyecto (Settings > Plugins > Gameplay > Mass).

  2. Desarrollo con Blueprint o C++: Mass se puede utilizar desde la paleta Mass Entity dentro del editor de Blueprint o escribiendo código C++ directamente. El soporte para Blueprint es ideal para la creación rápida de prototipos.

  3. Creación del sistema: Puede comenzar utilizando controladores prefabricados como MassEntityPlayerController o creando su propio sistema en C++ a través de FMassExecutionContext.

  4. Configuración de Chaos: La configuración de la física Chaos se encuentra en Project Settings > Chaos Physics. En estos ajustes, se pueden habilitar características como la restitución de colisiones. Para el almacenamiento en caché de Chaos, se debe activar la opción bEnableCache dentro de Chaos Solver Settings.

Efectos estratégicos:

Los enfoques orientados a datos de Unreal Engine 5 tienen una importancia estratégica, especialmente para mundos abiertos AAA y plataformas móviles. En los juegos de estilo Kena, hay un vasto mundo frente al jugador donde siempre hay vida presente. Cuando los comportamientos instantáneos de cualquier PNJ u objeto en este mundo se gestionan al estilo OOP, se accede a cientos de direcciones de memoria diferentes en cada fotograma, lo que provoca tirones (delays). El enfoque DOD es de vital importancia para proporcionar la experiencia fluida deseada en este tipo de juegos. Para las plataformas móviles, la eficiencia de la caché de CPU es aún más crítica; realizar más procesamiento consumiendo menos energía es una ventaja fundamental para los dispositivos móviles. El sistema de partículas Niagara de Unreal Engine 5, cuando se utiliza junto con tecnologías como SVT (Virtual Texture), también puede proporcionar importantes mejoras de rendimiento y memoria al almacenar en caché las simulaciones.

En conclusión, mientras mantiene su estructura basada en OOP, Unreal Engine 5 ha desarrollado Mass y Chaos, que son capas orientadas a datos potentes para satisfacer las necesidades centradas en el rendimiento. Estos sistemas ofrecen a los desarrolladores el rendimiento necesario para simulaciones a gran escala y con uso intensivo de datos, al tiempo que funcionan de manera integrada sin alterar la arquitectura fundamental del motor.

Impactos Estratégicos y Coste de Productividad: Una Evaluación para Mundos Abiertos AAA y Plataformas Móviles

La elección entre el Diseño Orientado a Datos (DOD) y la Programación Orientada a Objetos (OOP) va más allá de ser una mera preferencia técnica para convertirse en una decisión estratégica para el éxito de un juego. Especialmente para los juegos de clase AAA con mundos ricos, fluidos y vastos como Kena: Bridge of Spirits, y para las plataformas móviles con recursos limitados, esta decisión genera profundos efectos en el rendimiento, la velocidad de desarrollo y la experiencia de juego. El DOD es un paradigma potente diseñado específicamente para superar los límites de escalabilidad de la OOP, pero estas ventajas deben evaluarse de forma recíproca frente a costes como la curva de aprendizaje y el coste de integración.

Impactos Estratégicos para Mundos Abiertos AAA y Problemas de Fluidez:

Kena: Bridge of Spirits destaca como un juego que ofrece un rico mundo mitológico, un control fluido de los personajes y elementos detallados del entorno. En los debates de los foros de la comunidad de Steam se han mencionado problemas de rendimiento del juego ("stutter" y "FPS drops") . Las razones técnicas subyacentes a este tipo de problemas son probablemente los límites de escalabilidad de una arquitectura basada en OOP. En la OOP, cada entidad de la escena (NPC, objeto, sistema de partículas) tiene su propio GameObject y componentes asociados. Dado que estos GameObjects se almacenan de forma distribuida en la memoria, actualizar todas estas entidades en cada fotograma ordena a la CPU que acceda a cientos de direcciones de memoria diferentes. Esto resulta en un alto número de fallos en la caché de la CPU y obliga al procesador a extraer datos de una RAM lenta, lo que causa tirones notables (microtirones). El DOD ofrece una solución directa a este problema. Marcos como DOTS en Unity o Mass en Unreal Engine 5 almacenan tipos de datos similares (por ejemplo, los datos de posición de todos los NPC) de forma consecutiva en la memoria. Esto significa que un hilo puede recuperar todos estos datos de la memoria y procesarlos de una sola vez, lo que aumenta drásticamente la tasa de aciertos de la caché de la CPU y el rendimiento general. Esta arquitectura es de vital importancia para proporcionar la experiencia fluida deseada en juegos como Kena. El DOD utiliza toda la potencia de la CPU para proporcionar una mayor capacidad de procesamiento de datos, lo que hace posible apuntar a unos 60 FPS más estables.

Impactos Estratégicos para la Optimización de Plataformas Móviles:

Las plataformas móviles tienen recursos más limitados en comparación con los ordenadores de sobremesa o las videoconsolas: menos potencia de CPU, menos memoria RAM y un factor crítico, la duración de la batería. Por lo tanto, para los desarrolladores de juegos móviles, la eficiencia energética y la gestión de memoria se convierten en una de las métricas de éxito del juego.

  • Eficiencia Energética: Los procesadores móviles (por ejemplo, Arm Cortex-X4) son cada vez más potentes, pero la eficiencia energética sigue siendo un factor crítico . El DOD garantiza que la CPU consuma menos energía y realice más trabajo al minimizar su tiempo de inactividad. Mejoras como la reducción del 33% del ancho de banda en la arquitectura Cortex-X4 de Arm pueden significar que las aplicaciones que se ejecutan con DOD se beneficien aún más de esto . Un menor uso de la CPU también ayuda a que el dispositivo se caliente menos y la batería se agote más lentamente.

  • Gestión de Memoria: El uso de la memoria debe gestionarse meticulosamente en las plataformas móviles. El DOD puede reducir el uso general de la memoria al trabajar con datos más compactos y asignados en la memoria. Tecnologías como los formatos de compresión de AssetBundle de Unity () y SVT (Virtual Texturing) (), combinadas con la organización de datos del DOD, pueden crear una estructura muy eficiente para plataformas móviles. Además, las nuevas tecnologías como la compatibilidad con DirectStorage de Unity () y el streaming de shaders también respaldan la visión detrás de la arquitectura basada en la gestión de datos del DOD .

  • Productividad y Tiempo de Desarrollo: Las optimizaciones específicas de las plataformas móviles (por ejemplo, la minificación con ProGuard) () y el uso de API específicas de la plataforma (), cuando se consideran junto con el DOD, permiten crear una base de código más eficiente y hacer que dichas optimizaciones sean más efectivas.

Coste de Productividad y Experiencia del Desarrollador:

Las ventajas de rendimiento que ofrece el DOD deben evaluarse de forma recíproca con una pronunciada curva de aprendizaje y un coste inicial de caída de la productividad.

  • Dificultad de Conversión: Un proyecto existente y grande basado en OOP no se puede convertir completamente a la arquitectura DOD. Por lo general, se sigue un enfoque híbrido: algunas áreas críticas (física, IA, sistemas de partículas) se trasladan al DOD, mientras que otras áreas (interfaz de usuario, algunas mecánicas de juego especiales) se dejan bajo la estructura OOP existente. Aunque el Hybrid Renderer de Unity () facilita tales transiciones, plantea un problema de integración total. Los problemas en el juego Kena están relacionados muy probablemente con la escalabilidad de la estructura basada en OOP existente y sugieren que podrían resolverse con un cambio de arquitectura como el DOD.

  • Nivel de Experiencia: El DOD puede tener una curva de aprendizaje muy pronunciada, especialmente para los desarrolladores con experiencia en OOP. Al mirar el código, pasar de la lógica de "tengo un objeto" a la lógica de "¿qué hago con este conjunto de datos?" resulta difícil. Esto puede ralentizar inicialmente la velocidad de desarrollo.

  • Ecosistema de Herramientas: Unity y Unreal, basados en OOP, tienen un ecosistema de herramientas maduro y desarrollado a lo largo de los años. Los marcos de DOD como DOTS y Mass también están evolucionando, pero aún pueden tener aspectos incompletos y su documentación puede ser más reciente. Por ejemplo, algunos errores relacionados con DOTS (por ejemplo, errores de carga de ensamblajes de ráfaga) ( ) o la integración de sistemas como Chaos Cache Manager en Unreal () todavía pueden plantear desafíos para los desarrolladores.

Evaluación Comparativa:

CriterioProgramación Orientada a Objetos (OOP)Diseño Orientado a Datos (DOD)Curva de AprendizajeBaja, es un paradigma común y popularAlta, requiere una nueva filosofíaProductividad (Inicial)Alta, adecuada para la creación rápida de prototiposBaja, puede ser lenta al principioRendimiento (Escalabilidad)Limitado, se vuelve lento para grandes conjuntos de datosAlto, escala bien con millones de datosEficiencia de la Caché de la CPUBaja (acceso disperso)Alta (acceso consecutivo)Facilidad de Procesamiento ParaleloMedia (requiere sincronización)Alta (paralela por naturaleza)Idoneidad para Plataformas MóvilesRazonable, pero la eficiencia energética es menorAlta, utiliza la CPU de forma más eficienteIntegración (Proyectos Existentes)Fácil, directamente compatible con los proyectos existentesDifícil, requiere un enfoque híbrido

Conclusión y Recomendación Estratégica:

La elección entre OOP y DOD varía en función de factores como la escala del juego, la plataforma de destino y el área de especialización del equipo. Para proyectos pequeños y medianos o para la creación rápida de prototipos, la OOP puede ser ventajosa en términos de velocidad de desarrollo y flexibilidad. Sin embargo, para juegos de clase AAA con mundos fluidos, ricos y vastos como Kena: Bridge of Spirits, el DOD se convierte en una opción indispensable en términos de rendimiento y escalabilidad. Para las plataformas móviles, el DOD ofrece ventajas adicionales como la eficiencia energética y un menor uso de memoria, lo que lo hace aún más atractivo. Los desarrolladores deben analizar cuidadosamente los requisitos del proyecto y considerar la adopción de una estrategia híbrida que combine la flexibilidad de la OOP y el rendimiento del DOD. Esto hará posible aplicar la arquitectura correcta en las diferentes partes del proyecto.

*Nota Informativa: Las imágenes han sido generadas por Google Gemini.

UnityUE5UnityDOTSMultithreadingChaosPhysics
Herramienta de investigación profunda
Qwen (Alibaba Cloud)
Qwen (Alibaba Cloud)
Herramienta de traducción
Google Gemini
Google Gemini

Compartir