Icono del sitio Profile Software Services

Patrones de diseño en los videojuegos: Object Pooling

Object Pooling

El uso de patrones de diseño, como el Object Pooling, es una práctica muy recomendable cuando se quieren realizar desarrollos de software escalables, robustos y que tengan un buen rendimiento. Además, nos puede ayudar a mantener una estructuración de todo el código fuente para ayudar con su mantenibilidad; estos patrones no son instrucciones a seguir propiamente dichos, sino más bien una serie de pautas y recomendaciones que debemos de analizar correctamente para saber si las podemos aplicar en nuestros proyectos y, lo que es más importante, saber dónde y cómo hacerlo.

Antes de comenzar a describir sobre el Object Pooling, quería hacer referencia a un post de una compañera que explica de manera extensa qué es un Patrón de Diseño. Ahora, ¡entremos en materia!

¿Qué es el Object Pooling?

Como os he adelantado anteriormente, se trata de un patrón de diseño, el cual se suele aplicar cuando lo que prima en la solución de software es que haya un alto rendimiento; pero, ¿de qué trata el patrón Object Pooling exactamente? La base de los desarrollos de software implementando este patrón es la instanciación de una determinada cantidad de objetos para su posterior utilización; crearíamos estos objetos en el momento en el que se inicia la aplicación, aprovechando que es uno de los momentos de menos impacto en el rendimiento, pues aún “no se está utilizando la aplicación”.

Otro asunto a tener en cuenta al aplicar este patrón es que, si el tipo de objeto en cuestión no va a volver a ser utilizado, podríamos deshacernos de ellos simplemente eliminando nuestra Object Pool, liberando así una “gran cantidad” de memoria para que sea utilizada por nuestro sistema.

¿Qué beneficios nos aporta utilizar el patrón Object Pooling?

Uno de los beneficios de aplicar este patrón es que nos permitirá tener tiempos de respuesta más rápidos en el momento de la ejecución de los procesos en los cuales intervengan estos objetos, puesto que nos ahorramos el coste procedural de la creación (y de la posterior destrucción) de dichos objetos.

Sumado al beneficio de no tener que gastar recursos en crear y destruir estos objetos, como ya presupondréis, estos objetos también son reutilizables, pero, ¿En qué nos beneficia que esto sea así? Sin adentrarnos mucho en la teoría que rodea la gestión de memoria que se produce en el software, el beneficio principal es, que al instanciar todos estos objetos “en orden”, estos ocupan una serie de espacios de memoria seguidos y concretos, sin dejar huecos libres que puedan dar lugar a “fragmentaciones de memoria”, que se tratarían de pequeños huecos que no pueden ser rellenos por datos completos, por lo que “perderíamos” ese hueco, haciendo más ineficiente nuestra aplicación.

¿Cuáles son los inconvenientes de implementarlo en nuestro proyecto?

Los inconvenientes más destacables del uso de este patrón de diseño serían 2.

  1. Incluir este patrón de diseño, aumenta la complejidad del manejo de estos objetos, teniendo que tener en cuenta que hay que “pedir” un objeto a nuestra object pool antes de usarlo y “devolverlo” cuando ya no se necesita más. Para este caso solo hay una cosa que se puede hacer, ¡Practicar!
  2. Cuando vamos a pedir un objeto y no quedan más, ¿Qué hacemos? La causa ha sido que hemos creado pocos inicialmente, o bien que hay una situación que usa muchos más objetos que otros. Una de las estrategias a seguir para subsanar este problema sería configurar la object pool para que, cuando se quede sin objetos disponibles, cree algunos más, para así aumentar la cantidad de objetos disponibles, ajustando su funcionamiento a las necesidades puntuales.

El patrón Object Pooling en el mundo de los videojuegos

Adentrándonos en el mundo de los videojuegos, seguro que a alguien ya le ha venido a la mente algún ejemplo en el que este patrón pueda ser utilizado, pero, si no es tu caso, podríamos señalar como ejemplo, cada uno de los proyectiles dentro de un juego de disparos, las cuales son el ejemplo preferido por divulgadoras y divulgadores para explicar de manera sencilla este patrón de diseño.

Otros ejemplos donde podemos observar aplicada esta técnica también pueden ser coleccionables, enemigos, … Incluso, alejándonos de ejemplos que pueden verse bien a simple vista, este patrón es bastante utilizado en sistemas de partículas y otros efectos que pueden ser necesarios más de una vez.

También cabe destacar que el motor de videojuegos Unity ya implementa este patrón de diseño de manera nativa, contando además con un apartado de aprendizaje para poder utilizarlo en tu próximo proyecto.

Conclusion

Como conclusión podríamos decir que el concepto de Object Pooling es una estrategia inteligente para optimizar el rendimiento de tu juego, al evitar el consumo excesivo de CPU y memoria, al crear y destruir numerosos objetos. Consiste en reutilizar los objetos existentes en lugar de crear nuevos cada vez que se necesitan.

Mediante el uso del «Object Pooling», puedes aliviar la carga de trabajo de la CPU y la memoria, mejorando así la diversión y la capacidad de respuesta de tu juego, y evitando posibles interrupciones causadas por problemas de memoria.

No obstante, esta técnica también introduce mayor complejidad en el ciclo de vida y la gestión de objetos, lo que añade más complejidad y sobrecarga al código. Además, si los objetos no se reinician o limpian adecuadamente al devolverlos al grupo, pueden surgir errores.

Por lo tanto, es importante utilizar el Object Pooling con prudencia y cuidado, teniendo en cuenta las necesidades y situaciones específicas de tu juego.

Enlaces de interés:

https://reactiveprogramming.io/blog/es/patrones-de-diseno/object-pool

https://sourcemaking.com/design_patterns/object_pool

https://docs.unity3d.com/ScriptReference/Pool.ObjectPool_1.html

Salir de la versión móvil