Unity 浅析internal修饰符

在 Unity 项目中,使用 internal 修饰符来修饰方法、类或其他成员,虽然从表面上看与使用 publicprivate 等访问修饰符类似,但其实际作用和意义在 Unity 的特定环境中可能显得有些不同。

internal 修饰符在 Unity 中的作用

internal 修饰符限制了成员的访问权限,使得这些成员只能在同一个程序集内访问。以下是 internal 在 Unity 项目中的一些关键点和使用场景:

  1. 程序集范围的访问控制

    • 在 Unity 中,默认情况下,用户脚本会被编译到 Assembly-CSharp.dll 中。如果你使用了 internal 修饰符,这意味着该成员只能在同一个程序集 Assembly-CSharp.dll 中访问。
    • 对于 Unity 项目的大部分脚本,它们都在这个主程序集内,所以 internal 访问级别在此范围内起作用。
  2. 限制非公共 API

    • 你可能希望限制某些类或方法的访问权限,使其仅在特定的上下文或模块内使用,而不公开给整个项目的其他部分。
    • 例如,你可能有一些用于内部逻辑处理的工具类或方法,不希望它们被项目中的其他部分误用。这时可以使用 internal 修饰符来限制它们的访问。
  3. 管理依赖和模块化

    • 虽然大部分用户脚本会被编译到同一个程序集,但有时你可能会将一些代码组织到插件或自定义程序集(例如 Plugins 文件夹或 .asmdef 文件控制的程序集)中。
    • 在这些情况下,internal 可以用来控制不同程序集之间的访问权限,使得代码更加模块化和可维护。
  4. 与第三方库和插件的隔离

    • 如果你的 Unity 项目包含了多个第三方库或插件,这些插件通常会被编译成独立的程序集。在这种情况下,internal 可以用来确保插件的内部实现细节不会泄露到外部。
    • 例如,插件作者可以使用 internal 来保护插件的内部 API,仅暴露出公共接口供用户使用。

Unity 项目中的程序集划分

尽管大多数情况下,Unity 会将脚本编译到 Assembly-CSharp.dll 中,但开发者可以通过一些手段创建多个独立的程序集,从而更好地组织代码:

  1. 使用 PluginsStandard Assets 文件夹

    • Unity 会将 PluginsStandard Assets 文件夹中的脚本编译到单独的程序集中,如 Assembly-CSharp-firstpass.dll
    • 这些文件夹通常用于存放第三方插件和标准资产库。
  2. 使用 asmdef 文件

    • Unity 提供了 .asmdef(Assembly Definition)文件,用于创建自定义程序集。
    • 通过在项目中添加 .asmdef 文件,你可以将脚本划分到多个独立的程序集,以便更好地管理代码依赖和编译时间。
  3. 例如,创建一个 MyCustomAssembly.asmdef 文件:

1
2
3
4
5
6
7
8
9
10
11
{
"name": "MyCustomAssembly",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}
  1. 任何放在这个 .asmdef 文件同一目录下的脚本都会被编译到一个名为 MyCustomAssembly.dll 的程序集。

示例和实际应用

示例 1:使用 internal 限制内部工具类

假设有一个工具类 InternalTool,只希望在当前程序集内部使用:

1
2
3
4
5
6
7
8
9
10
11
// InternalTool.cs
namespace MyGame.Utils
{
internal class InternalTool
{
internal void DoSomething()
{
Debug.Log("Doing something internally...");
}
}
}

在同一个程序集的其他脚本中可以访问 InternalTool

1
2
3
4
5
6
7
8
9
10
11
// Same assembly
using MyGame.Utils;

public class GameLogic : MonoBehaviour
{
void Start()
{
InternalTool tool = new InternalTool();
tool.DoSomething();
}
}

但在其他程序集(例如插件或者其他 asmdef 定义的程序集)中则无法访问 InternalTool

示例 2:隔离第三方库的内部实现

假设你使用了一个第三方插件,并希望限制插件的内部 API,仅暴露公共接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// PluginLibrary.dll
namespace PluginNamespace
{
public class PublicAPI
{
internal void InternalMethod()
{
// Internal logic
}

public void UsePlugin()
{
InternalMethod();
}
}
}

在插件的内部实现中,InternalMethodinternal 的,只有插件内的代码可以调用它,而外部用户只能通过 PublicAPIpublic 方法 UsePlugin 来使用插件。

总结

  • internal** 修饰符在 Unity 中** 主要用于限制成员的访问范围,使得这些成员只能在同一个程序集内使用。
  • 在 Unity 的默认编译环境下,大多数脚本会被编译到 Assembly-CSharp.dll,因此 internal 修饰符的作用主要体现在同一个 Unity 项目内的访问控制。
  • 通过使用 Plugins 文件夹和 .asmdef 文件,开发者可以将代码组织成多个独立的程序集,这时 internal 修饰符可以更有效地控制不同程序集之间的访问权限。

通过合理使用 internal 修饰符和程序集划分,开发者可以更好地组织代码,增强代码的封装性和可维护性。