¿Por qué los juegos de computadora escritos en C ++ son más geniales que los de Java? ¿Cuál es el juego más grande hecho con Java?

Trabajé en Gameloft durante 2 años escribiendo juegos en C ++. La respuesta corta es, porque los desarrolladores de juegos reales codifican en C ++. Lo que significa que los mejores ingenieros escriben C ++. También hicimos algunos juegos con Java para la compatibilidad de teléfonos antiguos, pero fue como una broma.

Todo el motor era C ++, el renderizado, los servicios web, todo y el código era realmente bueno. Dejemos a un lado la velocidad, porque todos hablan de esto, en realidad preferimos C ++, porque mejora nuestra base de código.

Realmente creo que todo el software serio es C ++ hoy. Y con las nuevas características, combinadas con boost y otras bibliotecas, es una bestia.

Creo que Java es una broma para el desarrollo de juegos y uno más si escribes tu juego en C ++ es que se ejecutará en cualquier plataforma. iOS, Android, Windows, Linux, Mac, todos los sistemas operativos modernos admiten C ++. Intenta ejecutar el juego Java en iOS. Aunque debería ser un buen desarrollador para hacerlo multiplataforma con una base de código.

La unidad es buena, porque es fácil. Para hackatones, juegos independientes, etc. Incluso para juegos AAA, pero intenta trabajar con 100 personas más en el proyecto Unity. El control de versiones para Unity apesta mucho.

Empresas como Ubisoft y Gameloft tienen un sistema completo para la generación de escenas con la idea de que varias personas trabajen en una escena. Esto es importante. Súper importante

Necesitas sistemas basados ​​en entidades y componentes para juegos serios. Esto combinado con la generación de escena y la conexión de componentes se verá como una mierda en Java. Unity lo ha implementado, pero es súper básico y, una vez más, no puede fusionar estas cosas en el control de versiones.

No sé por qué la gente todavía usa Java hoy. Tal vez alguna gran corporación que no tiene otra opción. Tiene PHP y Nodo para el servidor, C ++ es más poderoso que nunca. Javascript es un asesino y la interfaz de usuario se realiza principalmente en HTML.

Cuando trabajes varios años en la industria, me entenderás. Si solo quieres hacer un juego, usa Unity. Te enseñará algunos conceptos básicos sobre el desarrollo del juego. Esto no es muy práctico, cuando eres Ubisoft o EA y haces un juego con cientos de personas involucradas, pero funciona y es fácil

Con C y C ++ puedes escribir cosas que están muy cerca del hardware. En materia de procesamiento de gráficos, es muy importante la rapidez con la que procesas una gran cantidad de datos. Estos cálculos a menudo se pasan a procesadores gráficos o una tarjeta gráfica separada si hay una. Por lo tanto, la interacción con el hardware y los cálculos grandes siguen siendo relativamente más rápidos en C y C ++.
Por otro lado, Java está un poco lejos del metal. Agrega un nivel de abstracción para que sea independiente de la plataforma. Las bibliotecas estandarizadas de Java están diseñadas para resolver la mayoría de los problemas generales y no problemas específicos que enfrentan los desarrolladores de juegos y puede tener implicaciones en los tiempos de ejecución.

Por lo tanto, los juegos de Java probablemente podrán ejecutarse en una amplia variedad de plataformas de hardware y sistema operativo, pero no serán tan atractivos gráficamente o exigirán una potencia de procesamiento superior para dar el mismo resultado. Pero los desarrolladores también tendrán menos trabajo ya que no tienen que preocuparse de cómo funcionará su juego en Linux, Windows o Mac o incluso en sistemas más pequeños como Raspberry Pi, Java se encarga de ellos.

Por otro lado, los desarrolladores de juegos C / C ++ tendrán que tomar muchas cosas en sus manos. Pueden proporcionar un rendimiento superior para una potencia de procesamiento relativamente menor, pero admitirán plataformas de hardware y SO limitados. Esta es una de las razones por las que no tenemos tantos juegos para Linux, porque no es fácil de transportar y nadie se esfuerza porque no es comercialmente viable.

Veo un montón de FUD (aparentemente no intencional) y mucha verdad, todo confundido en las respuestas. Para el registro y soy un campeón de Java reconocido por mi trabajo en el ajuste del rendimiento. Aunque trabajo principalmente en back-end, donde Java es una opción obvia. También he trabajado en sistemas de video escritos en Java.

En mi experiencia, las diferencias de rendimiento en bruto en C ++ a Java no son significativas en la mayoría de las situaciones. Lo que a menudo es más molesto es la recolección de basura. Aunque puede hacer que un recolector de basura se comporte en una aplicación con presupuestos estrictos, generalmente no es tan fácil de hacer. Tiene que saber mucho sobre cómo funciona el recolector de basura y, aunque algunas de las publicaciones mostraron una comprensión mejor que el promedio de GC, no vi una que me diera la sensación de que el autor tenía experiencia en la optimización de GC. La administración de memoria en C ++ es en realidad más costosa que la administración de memoria en Java. Dicho esto, el costo se distribuye de manera más uniforme durante el tiempo de ejecución, lo que resulta en una interrupción mucho menor. Si puede adaptarse a todo el trabajo necesario para renderizar un marco, incluida la recolección de basura comprimida entre las señales vsync (16.7 ms para el ciclo de 60 Hz), sugeriría que la elección entre Java y C ++ es una preferencia personal.

Existe soporte para Java a GPU, simplemente no es tan natural como lo es en C ++. Dicho esto, lo he usado y funcionó lo suficientemente bien para lo que necesitaba hacer.

Hay una publicación ligeramente confusa aquí que habló sobre problemas al usar buffers de bytes directos en Java que resultan en OutOfMemoryErrors. Sospecho que hubo una pérdida de memoria en la aplicación de esa persona y que los búferes de bytes directos * pueden * haber estado involucrados, pero como se señaló correctamente, solo se asigna una pequeña cantidad de espacio en el montón de Java, es más probable que algo más fue responsable de la OOME. Los OOME ocurren cuando te quedas sin espacio en Java Heap, Permspace (pre Java 8) y stack space. Por lo tanto, tener una estructura de datos pequeña en el montón de Java para mantener grandes buffers en el montón de C causará problemas, pero no un OOME. Por otro lado, puede tener los mismos problemas en una aplicación C ++ con la misma facilidad, es solo que se expresarán de manera diferente.

Otros comentarios al azar … comenzando con los comentarios sobre los motores de juego en C ++. Esta es probablemente la razón más importante para usar C ++. Si hay un marco que me ayudará a hacer algo con menos esfuerzo, necesitaré una gran razón para ignorarlo. Alguien mencionó el control sobre los diseños de memoria y su efecto en el rendimiento. Los diseños de memoria de Java fomentan la búsqueda de punteros, lo que puede ser un problema real. Sin embargo, puede mitigar esta elección de estructuras de datos que, naturalmente, permanecerán juntas en la memoria. Por ejemplo, una matriz asignada en una matriz de un tipo primitivo tendrá un acceso igual de rápido en C ++ que en Java. La programación en matrices primitivas en Java no es natural para la mayoría de los desarrolladores de Java. Y, solo funciona para primitivas ya que no hay equivalente de tener una matriz de estructura.

Con todo esto pensarías, ok, ¿por qué alguien elegiría Java para escribir un juego (o cualquier otra cosa)? La respuesta es que usar un sistema gestionado por memoria redujo la carga cognitiva en los desarrolladores. Elimina clases enteras de errores de su aplicación. Ambas cualidades tienden a hacer que el desarrollo en Java sea más rápido que en C ++. Además, como alguien señaló correctamente, cuando las cosas fallan, tienden a fallar de una manera más suave y expresiva. Además, la JVM se adaptará al hardware subyacente, mientras que una aplicación C ++ debe compilarse en una plataforma específica para poder aprovechar esa plataforma.

Cuando juntas la imagen completa, es mi opinión que C ++ gana en el mundo de los juegos porque los juegos tienden a escribirse cerca del hardware y eso es simplemente más fácil y más natural de lograr en C ++. Además, los motores de juego están escritos en C ++. Java se abstrae del hardware, por lo que si bien es posible escribir en el hardware, no es tan natural.

Dinero. Estás comparando juegos AAA con un presupuesto extremadamente alto con juegos pequeños con ni siquiera 1/100 del presupuesto para gráficos.

Una pregunta mucho más interesante es por qué esos títulos AAA están escritos principalmente en C ++ y hay una respuesta muy simple a eso. La mayoría de los motores de juegos existentes están escritos en C ++. Ahora, la mayoría de los motores existentes están escritos en C ++ porque su primera iteración de ellos se escribió cuando no había una alternativa real a C ++. Luego hubo consolas. C ++ bienvenido de nuevo. Por qué las consolas usaban principalmente C ++ no lo sé. Pregunta a los arquitectos de consolas.

Y una nota al margen: la mayoría de los desarrolladores ni siquiera conocen a esos programadores prodigios místicos con mucho talento porque fueron secuestrados por industrias / empresas que pagan mucho mejor;). La programación del juego no es tan lucrativa, y pagas por lo que tienes. El lenguaje que evita que esos mediocres cometan errores comunes significa menos errores (y un código más rápido; P). Con los juegos de hoy, los errores son un problema horrible 😉

Una nota al margen más: ¿Quieres rendimiento? Lea esto: Programación para la eficiencia y C ++ y C # nativos: ¿cuál es el más rápido? (Parte 1) eso. Verá que mucho depende de quién y cómo está escribiendo el código (sin incluir Java porque no sé nada al respecto), no en qué idioma está.

Primero, diré que mi definición de un juego genial no va de la mano con la resolución y la calidad fotográfica, sino con el contenido real del juego. Teniendo eso fuera del camino, mi respuesta.

La razón de esto es que para reducir el rendimiento (y, por lo tanto, poder aumentar el procesamiento que realiza entre cuadro y cuadro) necesitará control sobre lo que está sucediendo. No estamos hablando de eficiencia bruta aquí (que se define principalmente por la elección del algoritmo), sino de hacer lo más cercano posible al rendimiento. Java viene con varios recubrimientos de azúcar muy costosos para los programadores. El más caro de ellos es probablemente el recolector de basura. En Java, en general no te importa la memoria (bueno, los buenos programadores de Java probablemente se preocupan y conocen trucos para aprovecharla mejor). No puedes permitirte esto cuando escribes un juego AAA. El recolector de basura se bloqueará y congelará periódicamente cuando su uso de memoria sea alto para limpiar su desorden. El enfoque canónico en C ++ es no hacer un desastre en primer lugar, pero es un poco más difícil (sin embargo, es más fácil con las revisiones más recientes del estándar). C ++ no requiere un recolector de basura, y aunque AFAIK hay algunas bibliotecas para conectar uno al código C ++, el estándar no le da uno.
Aunque C ++ es más adecuado para los juegos, requiere algunas técnicas que no son tan comunes (principalmente porque no las necesita en cada nicho), por ejemplo, generalmente no pierde el tiempo asignando y desasignando todos sus recursos En cambio, es bastante común tener una piscina. Asigna solo una gran parte, suficiente para varios recursos del mismo tipo, y luego su asignación y desasignación se personaliza para pedir solo uno de esos y darle una referencia a ellos, marcar el recurso como en uso y cuando esté hecho, la desasignación lo marca como liberado. Todo esto con una sola llamada al sistema (la que asigna la gran parte). Si siempre trabaja con ese recurso de una forma que comienza primero, puede incluso reducir las operaciones a aumentar y disminuir una variable, lo que indica cuántos de sus recursos disponibles están en uso (esto es lo que hacen la mayoría de las implementaciones de JVM con su memoria, en realidad). No sé si Java permite este tipo de cosas (de manera personalizada, por supuesto, como mencioné, el concepto general de memoria generalmente se maneja de esta manera), pero ciertamente agregaría más trabajo para el GC, y nosotros quiero que haga lo menos posible.

Los juegos de C ++ no son “más geniales” que los creados con Java, porque ambos pueden usar la GPU de la misma manera. La única diferencia es que la mayoría de los títulos AAA están escritos en C ++, ya que permite un control más completo sobre el manejo de la memoria. En Java, el único problema real es que tienes un recolector de basura que se encarga de mantener limpia tu memoria. Con el software normal, esto funciona bastante bien, pero cuando se trata de buffers nativos, el manejo está lejos de ser óptimo. Este comportamiento resulta del hecho de que el recolector de basura (GC) no ve la cantidad de bytes que contiene un búfer nativo, porque este búfer reside fuera de la memoria del GC. Lo único que ve el GC es un objeto pequeño que tiene una referencia a un (posiblemente) búfer nativo muy grande. Y debido a que los juegos en Java tienen que mantener todos los vértices, coordenadas de textura, etc. en estos búferes nativos, es posible que obtenga una OutOfMemoryException aunque su GC piense que solo tiene una mano llena de pequeños objetos en la memoria, y por lo tanto no recogiéndolos

Pero hay formas de evitar este problema y, para muchas cosas, Java es incluso superior a C ++. Entonces, por ejemplo, si piensa en juegos escritos en C ++ que se bloquean, la mayoría de las veces esto es causado por una Infracción de acceso, esto no puede suceder en Java, porque no hay aritmética de puntero. Y el tiempo de ejecución también es bastante bueno gracias al compilador Just In Time (JIT) integrado que tienen las máquinas virtuales modernas, a veces incluso supera el tiempo de ejecución de un programa C ++, dependiendo de la prueba que consultes [1]. Para todos los efectos, puede suponer que Java es hoy tan rápido como C ++. Si no me cree, revise las pruebas usted mismo o vea algunos juegos más complejos que se han escrito en Java como Minecraft [2]. Además, uno de los motores más utilizados para nuevos juegos, Unity, utiliza C # como su lenguaje de programación principal, y C # es muy comparable a Java (también tiene un GC, sin aritmética de puntero, Bytecode …)

Notas al pie

[1] Rendimiento de C ++ frente a Java / C #

[2] Minecraft

En Java tiene muy poco control sobre el diseño de la memoria, lo cual es un gran problema cuando desea tener muchos objetos (npcs, barcos, tanques, soldados, etc.).

El problema es que desea tener una variedad de digamos tanques. Debe agregar y eliminar tanques de vez en cuando, pero la mayoría de los cuadros que necesita para recorrer esta matriz de cientos de tanques y hacerles cosas. En C ++, todos se almacenan en la memoria uno tras otro. Por lo tanto, su computadora puede predecir qué memoria desea leer y la preparará de antemano (buscar prefetcher de memoria) en caché.

En Java, debe saltar de un punto a otro en un patrón impredecible y causar errores de caché a menudo. Esto es algo que a las CPU modernas no les gusta. Entonces, incluso si Java pudiera producir un código más rápido (lo cual es muy cuestionable), se descartará, ya que debe esperar ~ 150 ciclos para acceder a la memoria que contiene el próximo tanque. Y ni siquiera hablo del concepto completo de Java orientado a objetos, lo que hace que incluso un tanque contenga muchos subobjetos que pueden estar en diferentes partes de la memoria, lo que provocará más errores de caché. Y actualmente no hay forma de evitarlo.

Java puede ser rápido, pero en el desarrollo de juegos a menudo necesitas mucho más control del que Java puede proporcionar, principalmente en el área de diseño de memoria. Puedes hacer un buen juego en Java, pero no todos los juegos amables y con alguna penalización de rendimiento. Vea también Minecraft reescrito en C ++ con un gran impulso de FPS.

Aunque vengo de una formación en ingeniería, diría que esto es en gran medida un fenómeno social: una manifestación de “efectos de red”.

Muchas veces no es el lenguaje de programación mejor diseñado que sobrevive y prospera en una industria específica. Es el lenguaje de programación que tiene la comunidad más efectiva. Un buen ejemplo, COBOL es extremadamente anticuado, pero aún se ve que se usa para bancos todo el tiempo. Javascript también es un ejemplo clásico.

Yo diría que dado que los principales motores 3D, por ejemplo, el motor Unreal, se basan en C ++, entonces tienes un flujo constante de programadores de C ++ para juegos de computadora. Esto garantiza la victoria por cantidad para C ++. Si se escribieron originalmente en otro idioma, probablemente tenga eso en su lugar. Es el impulso social en el trabajo.

Y como otras personas dijeron: Minecraft 🙂