Una biblioteca para permitir escribir scripts de unidad en código nativo: c, c ++, ensamblaje.
Este proyecto tiene como objetivo brindarle una alternativa viable a C#. Las secuencias de comandos en C ++ no son adecuadas para todas las partes de cada proyecto, pero ahora es una opción.
Cambiar una línea de código C# requiere que haga una nueva compilación del juego. Los tiempos de construcción típicos de Android tienden a ser al menos 10 minutos porque IL2CPP tiene que funcionar y luego se debe compilar una gran cantidad de C ++.
Al usar C ++, podemos compilar el juego como un complemento C ++ en aproximadamente 1 segundo, intercambiar el complemento al APK y luego instalar y ejecutar inmediatamente el juego. ¡Ese es un gran impulso de productividad!
C ++ se compila mucho más rápidamente que C#. Las compilaciones incrementales cuando solo cambia un archivo, las construcciones más comunes, pueden ser 15 veces más rápidas que con C#. La compilación más rápida se suma con el tiempo a las ganancias de productividad. Los tiempos de iteración más rápidos hacen que sea más fácil permanecer en el "flujo" de la programación.
El recolector de basura de Unity es obligatorio y tiene muchos problemas. Es lento, corre en el hilo principal, recoge toda la basura a la vez, fragmenta el montón y nunca encoge el montón. Entonces, tu juego experimentará "enganche de fotogramas" y eventualmente te quedarás sin memoria y se bloqueará.
Se requiere una cantidad significativa de esfuerzo para trabajar en torno al GC y el código resultante es difícil de mantener y disminuir. Esto incluye técnicas como grupos de objetos, que esencialmente hacen que la gestión de la memoria sea manual. También debe evitar los tipos de valor de boxeo como int para tipos administrados como object , no usar bucles foreach en algunas situaciones y varios otros Gotchas.
C ++ no tiene un recolector de basura requerido y presenta una gestión de memoria automática opcional a través de tipos de "puntero inteligente" como shared_ptr. Ofrece excelentes alternativas al primitivo recolector de basura de Unity.
Si bien el uso de algunas API .NET aún implicará la creación de basura, el problema está contenido solo para aquellas API en lugar de ser un problema generalizado para todo su código.
Al usar C ++ directamente, obtiene un control completo sobre el código que la CPU ejecutará. Es mucho más fácil generar un código óptimo con un compilador C ++ que con un compilador C#, IL2CPP y finalmente un compilador C ++. Corta el Middle Man y puedes aprovechar las intrínsecs o ensamblaje del compilador para escribir directamente el código de la máquina utilizando características de CPU potentes como el cifrado SIMD y AES de hardware para obtener ganancias de rendimiento masivas.
C ++ es un lenguaje mucho más grande que C# y algunos desarrolladores preferirán tener más herramientas a su disposición. Aquí hay algunas diferencias:
Mientras que IL2CPP transforma C# en C ++ ya, genera mucha sobrecarga. Hay muchas sorpresas si lee el C ++ generado. Por ejemplo, hay una sobrecarga para cualquier función utilizando una variable estática y se almacenan dos punteros adicionales al comienzo de cada clase. Lo mismo ocurre con todo tipo de características como sizeof() , cheques nulos obligatorios, etc. En cambio, puede escribir C ++ directamente y no necesitar trabajar alrededor de IL2CPP.
C ++ es el idioma estándar para los videojuegos, así como muchos otros campos. Al programar en C ++, puede transferir más fácilmente sus habilidades y código hacia y desde proyectos no sin unidad. Por ejemplo, puede evitar el bloqueo usando el mismo idioma (C ++) que usaría en los motores Unreal o Lumberyard.
GameObject go;
Transform transform = go.GetTransform();
Vector3 position(1.0f, 2.0f, 3.0f);
transform.SetPosition(position);
MonoBehaviour en C ++ void MyScript::Start()
{
String message("MyScript has started");
Debug::Log(message);
}
#if TARGET_OS_ANDROID )El núcleo de este proyecto es un generador de código. Genera el código C# y C ++ llamado "enlaces" que hacen que las API de C# estén disponibles para el código de juego C ++. Admite una amplia gama de características del lenguaje:
classstructenumAction )decimalget y set como obj.x )get and set como obj[x] )add y remove delegados)int to object and Visa Versa)out y refTenga en cuenta que el generador de código aún no es compatible:
Array , string y object (por ejemplo, GetHashCode )params implícitos (también conocido como "var args") pase Para configurar el generador de código, abra Unity/Assets/NativeScriptTypes.json y observe los ejemplos existentes. Agregue a este archivo para exponer más API de C# de Unity, .NET o DLLS personalizados a su código C ++.
Para ejecutar el generador de código, elija NativeScript > Generate Bindings del editor Unity.
Casi todos los proyectos obtendrán una victoria en el rendimiento neto reduciendo la recolección de basura, eliminando la sobrecarga de IL2CPP y el acceso a la intrínseca y la ensamblaje del compilador. Las llamadas de C ++ a C# incurren solo en una penalización de rendimiento menor. En el raro caso de que casi todo su código sea llamado a las API .NET, entonces puede experimentar una pérdida de rendimiento neta.
Artículo de pruebas y puntos de referencia
Artículo de optimizaciones
Al secar las secuencias de comandos en C ++, C# se usa solo como una capa "vinculante" para que la unidad pueda llamar a las funciones de C ++ y las funciones de C ++ pueden llamar a la API de Unity. Se utiliza un generador de código para generar la mayoría de estos enlaces de acuerdo con las necesidades de su proyecto.
Todo su código, además de algunos enlaces, existirá en un solo complemento C ++ "nativo". Cuando cambie su código C ++, construirá este complemento y luego jugará el juego en el editor o en una compilación implementada (por ejemplo, a un dispositivo Android). No habrá ningún código C# para que Unity compile a menos que ejecute el generador de código, que es poco frecuente.
El flujo de trabajo de C# estándar se ve así:
Con C ++, el flujo de trabajo se ve así:
Unity/Assets al directorio de Assets de su proyecto UnityNativeScriptTypes.json y especifique qué partes de las API de Unity, .NET y DLL personalizadas a las que desea acceder desde C ++.Unity/Assets/CppSource/Game/Game.cpp y Unity/Assets/CppSource/Game/Game.h para crear su juego. Se proporciona algún código de ejemplo, pero no dude en eliminarlo. Puede agregar más archivos de fuente C ++ ( .cpp ) y encabezado ( .h ) aquí a medida que su juego crece./Applications/Utilitiescd /path/to/your/build/directorycmake -G MyGenerator -DCMAKE_TOOLCHAIN_FILE=/path/to/your/project/CppSource/iOS.cmake /path/to/your/project/CppSource . Reemplace MyGenerator con el generador de su elección. Para ver las opciones, ejecute cmake --help y mire la lista en la parte inferior. Las opciones comunes incluyen "Unix Makefiles" para construir desde la línea de comandos o "Xcode" para usar el IDE de Apple.make si elige Unix Makefiles como su generador o abre NativeScript.xcodeproj y haga clic en Product > Build si elige XCode. /Applications/Utilitiescd /path/to/your/build/directorycmake -G "MyGenerator" -DEDITOR=TRUE /path/to/your/project/CppSource . Reemplace MyGenerator con el generador de su elección. Para ver las opciones, ejecute cmake --help y mire la lista en la parte inferior. Las opciones comunes incluyen "Unix Makefiles" para construir desde la línea de comandos o "Xcode" para usar el IDE de Apple. Eliminar -DEDITOR=TRUE para construcciones independientes.make si elige Unix Makefiles como su generador o abre NativeScript.xcodeproj y haga clic en Product > Build si elige XCode. cd /path/to/your/build/directorycmake -G "Visual Studio VERSION YEAR Win64" -DEDITOR=TRUE /path/to/your/project/CppSource . Reemplace VERSION y YEAR con la versión de Visual Studio que desea usar. Para ver las opciones, ejecute cmake --help y mire la lista en la parte inferior. Por ejemplo, use "Visual Studio 15 2017 Win64" para Visual Studio 2017. Cualquier versión, incluida la comunidad, funciona bien. Eliminar -DEDITOR=TRUE para construcciones independientes. Si está utilizando Visual Studio 2019, ejecute cmake -G "Visual Studio 16" -A "x64" -DEDITOR=TRUE /path/to/your/project/CppSource en su lugar.NativeScript.sln y haga clic en Build > Build Solution . cd /path/to/your/build/directorycmake -G "MyGenerator" -DEDITOR=TRUE /path/to/your/project/CppSource . Reemplace MyGenerator con el generador de su elección. Para ver las opciones, ejecute cmake --help y mire la lista en la parte inferior. La opción más común es "Unix Makefiles" para construir desde la línea de comandos, pero también hay opciones IDE. Eliminar -DEDITOR=TRUE para construcciones independientes.make si elige Unix Makefiles como su generador. cd /path/to/your/build/directorycmake -G MyGenerator -DANDROID_NDK=/path/to/android/ndk /path/to/your/project/CppSource . Reemplace MyGenerator con el generador de su elección. Para ver las opciones, ejecute cmake --help y mire la lista en la parte inferior. Para hacer una compilación para cualquier plataforma que no sea Android, omita la parte -DANDROID_NDK=/path/to/android/ndk .make si elige Unix Makefiles como su generador. Para actualizar una nueva versión de este proyecto, sobrescribe el directorio de Assets/NativeScript de su proyecto Unity con el directorio Unity/Assets/NativeScript de este proyecto y vuelva a ejecutar el generador de código.
Artículos del autor que describe el desarrollo de este proyecto.
Jackson Dunstan
No dude en tener las solicitudes de extracción y simplemente enviar un problema para características o correcciones de errores.
Todo el código es un MIT con licencia, lo que significa que generalmente se puede usar fácilmente en aplicaciones comerciales y no comerciales.
Toda la escritura tiene licencia CC por 4.0, lo que significa que se puede usar mientras se otorgue la atribución.