unity文档翻译 2021.3 Unity architecture->ScriptingUnity architectureOverview of .NET in Unity

https://docs.unity3d.com/Manual/overview-of-dot-net-in-unity.html

Overview of .NET in Unity  (Unity中.Net的OverView)

Unity uses the open-source .NET platform to ensure that applications you make with Unity can run on a wide variety of different hardware configurations. The .NET platform supports a range of languages and API libraries.

(Unity使用open-source .Net platform ,确保多平台运行。)

Scripting backends   脚本后端  脚本运行模式

Unity has two scripting backends; Mono, and IL2CPP   (Intermediate Language To C++), each of which uses a different compilation technique (两种脚本运行模式Mono和IL2CPP):

  • Mono uses just-in-time (JIT) compilation and compiles code on demand at runtime. (Mono  使用JIT编译器,运行时按需编译code )
  • IL2CPP uses ahead-of-time (AOT) compilation and compiles your entire application before it runs.(AOT 在运行application前预编译)

The benefit of using a JIT-based scripting backend is that the compilation time is typically much faster than AOT.(JIT编译器通常编译速度比较快)

By default, Unity uses the Mono backend on platforms that support Mono. When you build a player for your application, you can choose which scripting backend to use. To do this through the Editor, go to Edit > Project Settings > Player, open the Other Settings panel, then click on the Scripting Backend dropdown and select which backend you want. For more information, see Scripting backends . (默认使用Mono方式)
.
 

Managed code stripping  托管代码的剥离

When you build an application, Unity compiles and then searches the assemblies (.DLLs) in your project to detect and remove unused code. This process of stripping code reduces the final binary size of your build, but increases build time.

build 的时候, 当unity编译后,会去检测项目中的 程序集DLLs并且移除无用的代码。此代码剥离流程会减少最后binary的大小。但是增加了build时长。

Code stripping is disabled by default when you use Mono but code stripping can’t be disabled for IL2CPP. You can control how much code Unity strips with the Managed Stripping Level property.

在Mono模式下code striping是禁止的。 在IL2CPP下开启,并且用户可以设置stripping的等级。

As you increase the Managed Stripping Level, Unity removes more code. This increases the risk that Unity might remove code that your application relies on, especially if you use reflection or generate code at runtime.

stripping等级越高,unity会移除更多unused的代码。 不过这也增加了风险:有概率移除 application 可能需要使用到的代码。尤其是在runtime下使用反射或者代码生成。

You can use annotations on certain elements of your code to prevent Unity from stripping it. For more information, see Managed Code Stripping.

stripping详情请看链接

 

Garbage collection   垃圾回收

Unity uses the Boehm garbage collector for both the Mono and IL2CPP backends. Unity uses the Incremental mode by default. You can disable the Incremental mode to use stop-the-world garbage collection, although Unity recommends the Incremental mode.

使用Boehm garbage collector 垃圾回收方式。默认使用增量模式。尽管unity建议使用Incremental mode,我们也可以关闭Incremental mode,使用stop-the-world模式。

To toggle between Incremental mode and stop-the-world, go to Edit > Project Settings > Player, open the Other Settings panel and click on the Use incremental GC checkbox. In Incremental mode, Unity’s garbage collector only runs for a limited period of time and doesn’t necessarily collect all objects in one pass. This spreads the time it takes to collect objects over multiple frames and reduces stuttering and CPU spikes. For more information, see Managed memory.

In Incremental mode,unity垃圾回收只运行有限的时间段,并不需要一次性收集所有对象的信息。这样把垃圾回收分散在多帧,可以减少卡顿和CPU的峰值。详细查看链接

To check the number of allocations and possible CPU spikes in your application, use the Unity Profiler. You can also use the GarbageCollector API to completely disable garbage collection in Players. When the collector is disabled, be careful to avoid allocating excess memory.

Unity Profiler可以进行性能检测。 GarbageCollector API可以控制GC的开启。

 

.NET system libraries     .NET 系统库

Unity supports many platforms and might use different scripting backends depending on the platform. The .NET system libraries require platform-specific implementations to work correctly in some cases. While Unity tries its best to support as much of the .NET ecosystem as possible, there are some exceptions to parts of the .NET system libraries that Unity explicitly doesn’t support.

Unity明确不支持some exceptions

Unity makes no performance or allocation guarantees for the .NET system libraries across Unity versions. Generally, Unity doesn’t fix any performance regressions in the .NET system libraries.

如果.Net system lib 跨Unity版本,Unity不保证性能和内存分配。通常Unity不会修复.NET的性能问题。

Unity doesn’t support the System.Drawing library and it isn’t guaranteed to work on all platforms.

不支持 System.Drawing library 

The JIT compilation that the Mono scripting backend uses enables you to emit dynamic C#/.NET Intermediate Language (IL) code generation during the runtime of your application. The AOT compilation
 that the IL2CPP scripting backend uses doesn’t support dynamic code generation.

Mono模式下可以runtime生成IL代码。IL2CPP模式下不支持dynamic code generation

This is important to consider when you use third-party libraries, because they might have different code paths for JIT and AOT, or they might use code paths that rely on dynamically generated code. For more information on how to generate code at runtime, see Microsoft’s ModuleBuilder documentation.

使用第三方库的时候需要注意,第三方库对JIT和AOT的支持,以及第三方库是否依赖dynamic generate code?

Although Unity supports multiple .NET API profiles, you should use the .NET Standard API Compatibility Level for all new projects for the following reasons:

最好使用 .NET Standard 原因:

  • .NET Standard is a smaller API surface and so has a smaller implementation. This reduces the size of your final executable file.   小 内存少
  • .NET Standard has better cross-platform support, so your code is more likely to work across all platforms.   跨平台支持好
  • All .NET runtimes support .NET Standard, so your code works across more VM/runtime environments (for example, .NET Framework. .NET Core, Xamarin, Unity) when you use .NET Standard.    .NET都在Net Standard的标准内
  • .NET Standard moves more errors to compile time. A number of APIs in .NET Framework are available at compile time, but have implementations on some platforms that throw an exception at runtime.   编译期报错更明显

Other profiles can be useful if, for example, you need to provide support for an older existing application. To change the Api Compatibility Level setting, go to Edit > Project Settings > Player. Under the Other Settings heading, set the Api Compatibility Level to the desired setting.

For more information, see .NET Profile Support.

 

Using third-party .NET libraries

You should only use third-party .NET libraries that have been extensively tested on a wide range of Unity configurations and platforms.

The performance characteristics of JIT and AOT code paths in third-party libraries might be significantly different. AOT generally reduces startup times and is suited to larger applications for this reason but increases the binary file size to accommodate the compiled code. AOT also takes longer to build during development.

AOT减少启动时间并且适用于大型应用,但是会增大编译后代码二进制文件大小。AOT打包比较慢。

JIT adjusts at runtime based on the platform it’s running on, which can increase running performance at the cost of a potentially longer application startup time. As such, you should profile your application in both the Editor, and on your target platform. For more information, see Profiler overview.

JIT在运行时根据运行的平台进行调整,这可以提高运行性能。 而且会增增加应用的启动时间。

You should profile the usage of your .NET system libraries on all target platforms because their performance characteristics might vary depending on the scripting backends, .NET versions, and profiles you use.

When you review a third-party library, consider the following areas:

  • Compatibility: Third-party libraries might not be compatible with some Unity platforms and scripting backends.   平台支持问题
  • Performance: Third-party libraries might have vastly different performance characteristics in Unity compared to other .NET runtimes.     性能可能有问题
  • AOT binary size: Third-party libraries might increase AOT binary size significantly because of the number of dependencies the library uses. (AOT下二进制大小可能会爆炸是增长

 

C# reflection overhead

Mono and IL2CPP internally cache all C# reflection (System.Reflection) objects and by design, Unity doesn’t garbage collect them. The result of this behavior is that the garbage collector continuously scans the cached C# reflection objects during the lifetime of your application, which causes unnecessary and potentially significant garbage collector overhead.

Mono和IL2CPP内部缓存所有c#反射(System.Reflection)对象,Unity不会对它们进行垃圾收集。垃圾收集器在应用程序的生命周期中不断扫描缓存的c#反射对象,这将导致不必要的和潜在的重大垃圾收集器开销。

To minimize the garbage collector overhead, avoid methods such as Assembly.GetTypes and Type.GetMethods() in your application, which create a lot of C# reflection objects at runtime. Instead, you should scan assemblies in the Editor for the required data and serialize and/or codegen it for use at runtime.

要最大程度减少垃圾回收器开销,请避免使用诸如 Assembly.GetTypes 和 Type.GetMethods() 等方法,这些方法会在运行时创建许多 C# 反射对象。而是应该在编辑器中扫描程序集以获取所需数据,并进行序列化和/或代码生成以在运行时使用

 

UnityEngine.Object special behavior

UnityEngine.Object is a special type of C# object in Unity, because it’s linked to a native C++ counterpart object. For example, when you use a Camera component, Unity stores the state of the object on the object’s native C++ counterpart, not on the C# object itself.

UnityEngine.Object 是一种特殊类型的C#对象。会link到一个原生的C++对象。例如当你使用相机组件时,Unity将对象的状态存储在对象的原生c++对应对象上,而不是在c#对象本身上

 Unity doesn’t currently support the use of the C# WeakReference class with instances of UnityEngine.Object. For this reason, you shouldn’t use a WeakReference to reference a loaded asset. See Microsoft’s WeakReference documentation for more information on the WeakReference class.

Unity目前不支持在UnityEngine的实例中使用c# WeakReference类

 

Unity C# and Unity C++ share UnityEngine Objects

When you use a method such as Object.Destroy or Object.DestroyImmediate to destroy a UnityEngine.Object derived object, Unity destroys (unloads) the native counter object. You can’t destroy the C# object with an explicit call, because the garbage collector manages the memory. Once there are no longer any references to the managed object, the garbage collector collects and destroys it.

使用Object.Destroy or Object.DestroyImmediate 时,Unity unload原生counter 对象,这时候并不是真正的销毁,只是一种标记手段。GC去管理真正的销毁。

If your application tries to access a destroyed UnityEngine.Object again, Unity recreates the native counterpart object for most types. Two exceptions to this recreation behavior are MonoBehaviour and ScriptableObject: Unity never reloads them once they have been destroyed.

当访问被Destroyed的UnityEngine.Object时,Unity会重建 原生C++对象。除了 MonoBehaviour and ScriptableObject

MonoBehaviour and ScriptableObject override the equality (==) and inequality (!=) operators. If you compare a destroyed MonoBehaviour or ScriptableObject against null, the operators return true when the managed object still exists and hasn’t yet been garbage collected.

MonoBehaviour and ScriptableObject的 ==和!=被重写。当这两种类型的对象被destroyed后,被托管的对象实际内存还是存在的,还没有被垃圾回收,但是已经被标记为为“假空”了。所以使用==null会return true。 

Because you can’t overload the ?? and ?. operators, they aren’t compatible with objects that derive from UnityEngine.Object. The operators don’t return the same results as the equality and inequality operators when you use them on a destroyed MonoBehaviour or ScriptableObject while the managed object still exists.

??和?.没有被重写   返回的结果不是我们想要的  因为当前托管对象还在内存里。

 

下面的链接解释了unity doc里(上面标记黄色的 :“Unity会重建 原生C++对象”)的意思:

https://answers.unity.com/questions/1705335/how-can-throw-missing-reference-exception-this-gam.html

 However we have the Destroy method to destroy any objects derived from UnityEngine.Object. What the method does is actually destroying the object on the native side and mark the managed wrapper object as "being destroyed".

UnityEngine.Object会确切的销毁 原生对象,并且把C#端托管对象标记为 “being destory”。 如果没理解错,UnityEngine.Object真正的内存在C++端显示管理,托管C#端只是一个标记object

Limitations of async and await tasks   aysnc和await的局限

The Unity API isn’t thread safe and therefore, you should only use async and await tasks from inside the UnitySynchronizationContext. Async tasks often allocate objects when invoked, which might cause performance issues if you overuse them.

Unity API不是线程安全的。你应该只使用UnitySynchronizationContext中的async和await tasks。异步任务通常在调用时分配对象,如果过度使用,可能会导致性能问题。

Unity overwrites the default SynchronizationContext with a custom UnitySynchronizationContext and runs all the tasks on the main thread in both Edit and Play modes by default. To use async tasks, you must manually create and handle your own threads with the Task.Run API, and use the default SynchronizationContext instead of the Unity version.

Unity用自定义的UnitySynchronizationContext重写默认的SynchronizationContext,并在默认的编辑和播放模式下运行主线程上的所有任务。要使用async tasks,你必须使用Task.Run 手动创建和处理自己的线程 ,并使用默认的SynchronizationContext而不是Unity版本。

Unity doesn’t automatically stop async tasks that run on managed threads when you exit Play mode. To listen for enter and exit Play mode events to stop the tasks manually, use EditorApplication.playModeStateChanged. If you take this approach, most of the Unity scripting APIs aren’t available to use unless you migrate the context back to the UnitySynchronizationContext.

当你退出游戏模式时,Unity不会自动停止在托管线程上运行的异步任务要监听进入和退出播放模式事件以手动停止任务,请使用EditorApplication.playModeStateChanged。如果你采用这种方法,大多数Unity脚本api都无法使用,除非你将context移回UnitySynchronizationContext。

For performance reasons, Unity doesn’t perform checks for multithreaded behavior in non-development builds and doesn’t display this error in live builds. This means that while Unity doesn’t prevent execution of multithreaded code on live builds, random crashes and other unpredictable errors are likely if you do use multiple threads.

出于性能原因,Unity不会在非开发构建中执行多线程行为检查,也不会在实时构建中显示此错误。这意味着虽然Unity不会阻止在实时构建中执行多线程代码,如果你使用多线程,则可能会出现随机崩溃和其他不可预测的错误

For this reason, you shouldn’t use your own multithreading and instead use Unity’s job system. The job system uses multiple threads safely to execute jobs in parallel and achieve the performance benefits of multithreading. For more information, see Job system overview.

出于这个原因,你不应该使用自己的多线程,而是使用Unity’s job system。The job system 使用多线程安全地并行执行作业,实现了多线程的性能优势。有关更多信息

 

posted @ 2023-05-23 00:07  sun_dust_shadow  阅读(43)  评论(0编辑  收藏  举报