包必须遵循
语义版本控制
(SemVer)。语义版本控制是一种策略,让包创作者能够以一种自动化工具可以使用的格式来提供有关给定版本中与先前版本相比的更改类型的信息。
语义版本控制将版本表示为
MAJOR.MINOR.PATCH
,MAJOR 表示引入了一个或多个重大更改,MINOR 表示引入了一个或多个向后兼容的 API 更改,而 PATCH 表示仅引入了错误修正,API 无任何变化。
开始开发包时,版本号从
0.1.0
开始。MAJOR 版本号
0
保留给包的初始开发阶段。在最初的开发过程中,包 API 经常频繁进行重大更改,因此,在您认为包足够稳定并可以在实际生产中使用之前,请将 MAJOR 版本号保持为
0
。
在包正式准备好可用于生产后,应将 MAJOR 版本递增到
1
,并在后续更改时遵循以下准则:
MAJOR
至少有一个重大更改,而该包的任何一个版本都不能替代另一个版本。重大更改包括:
• 更改 API 表面(API 的公开部分)或功能,可能导致编译或运行时错误。
• 删除非 API 功能,包括删除资源或更改资源的 GUID。
• 删除或重命名程序集和资源(因为编译器可能无法找到它们)。
注意
:将主要版本递增时,请务必将
PATCH
和
MINOR
值重置为
0
。
版本 1.2.3 和 2.0.0 不兼容,不能安全地互换使用。
MINOR
(
MAJOR
值相同)
最高的
MINOR
以向后兼容方式引入功能。向后兼容(或非重大)的 API 更改包括:
• 更改 API 表面或功能,但不存在导致编译或运行时错误的风险。
• 添加非 API 功能。
• 添加程序集和资源(因为新项没有预先存在的引用)。
注意
:将次要版本递增时,请务必将
PATCH
版本重置为
0
。
可以使用 1.3.0 版来实现对 1.2.0 的依赖,因为 1.3.0 向后兼容。
不能使用 1.2.0 来实现对 1.3.0 的依赖。
PATCH
(
MAJOR.MINOR
值相同)
最高的
PATCH
以向后兼容的方式引入了错误修复,但不更改任何 API。如果满足以下条件,表示 API 没有更改:
• API 表面相同,并且功能保持不变。
• 所做的更改不会更改公共 API。
版本 1.3.0 和 1.3.1 应该可以互换,因为它们具有相同的 API,即使 1.3.1 包含 1.3.0 中不存在的错误修复。
您可以为
程序集定义
设置的其中一个属性是
Auto Referenced
,该属性控制 Unity 在编译过程中是否自动引用文件。启用此属性后,某些通常只需要增加 MINOR 或 PATCH 版本的更改现在将成为重大更改。
禁用
自动引用时,如果进行的任何更改导致有新的程序集可用,则会引入向后兼容的 API 更改。向后兼容的 API 更改(比如
添加平台
、
禁用 Unity 测试引用
、
添加新的
.asmdef
或
删除定义约束
)只需要增加
MINOR
版本。
但在
启用
自动引用时,新添加的程序集将隐式添加到其他各种程序集的引用中。由于这些情况可能导致这些其他程序集中出现编译错误,因此需要增加
MAJOR
版本。
另一种常见情况是在因为包依赖关系而添加或更改版本时。在大部分情况下,
更改包依赖关系
仅需要增加
PATCH
版本。但是,新的包版本可能包含
启用
了
Auto Referenced
属性的程序集,这就会成为一个重大更改,因此需要增加
MAJOR
版本。
为避免此类问题,请始终避免将第三方 DLL 文件放入不相关的包中(例如,在 SaveGameManager 包中包含
Newtonsoft.Json.dll
)。
项目可以引用资源数据库可见的任何资源。资源数据库使用在
.meta
文件中定义的 GUID 来唯一跟踪这些资源。
将以下某一个更改引入公共 API 中时,需要新的
MAJOR
版本,因为它们属于
重大更改
:
程序集定义
(
.asmdef
) 定义一组脚本,Unity 编辑器的编译管线会将这些脚本转换成单独的托管程序集 (
.dll
)。这些
.asmdef
资源包含的属性可驱动生成的程序集的属性。这些方法包括:
导入器设置,例如包含的平台和排除的平台
与编译相关的属性,例如输出程序集名称和引用(提供给编译器以构建程序集)。
大多数属性都会影响程序集的使用者,因此更改其中任何一个属性都将更改包的公共 API。其他属性对程序集的使用者没有影响,因此更改其中任何一个都不会被视为更改包 API。
警告
:
Auto Referenced
属性是一种特殊情况,因为很多通常
完全不会更改 API
或
以向后兼容方式更改 API
的更改都可能会导致编译错误,具体取决于是否启用了此属性。有关更多信息,请参阅
自动引用
。
Unity 既可以预编译程序集,也可以通过脚本和程序集定义来编译程序集。因此,适用于程序集定义的所有内容通常也适用于预编译的程序集。
本节详细介绍了程序集定义和预编译程序集的更改,以及对包版本的影响:
重大更改
(仅在新的 MAJOR 版本中允许)
向后兼容的 API 更改
(在新的 MAJOR 或 MINOR 版本中允许)
不会改变 API 的
向后兼容更改
(在新的 MAJOR、MINOR 或 PATCH 版本中允许)
仅限 MAJOR 版本:重大更改
在引入公共 API 的
重大更改
时,这需要新的
MAJOR
版本,因为这可能会导致编译错误和运行时错误。所有这些情况下都会从引用某个程序集的所有其他程序集中删除或隐藏该程序集。如果编译的程序集使用了在引用的程序集中定义的类型,则在编译器找不到另一个程序集的情况下,会导致编译错误。有关使用程序集和程序集定义的更多信息,请参阅
程序集定义
。
请注意,以下内容适用于包使用的运行时程序集和 Editor 程序集。这些内容不适用于测试程序集,因为包通常不使用它们,所以它们不是包 API 的一部分。
删除程序集定义或预编译的程序集
删除程序集定义文件会阻止编译管线生成对应的程序集。
注意
:从 2019.1 开始,允许缺失的引用,目的是支持“可选引用”用例,但如果重命名 Unity 在编译程序集定义时所需要的程序集,则会导致编译错误。同样,如果编译后的代码需要程序集中的某个类型,则重命名该程序集可能会导致运行时错误,例如
TypeLoadException
。
更改程序集名称(在
.asmdef
文件中更改,或者重命名
.dll
文件)
更改程序集名称等同于先删除程序集,然后又添加不同名称的新程序集。这意味着虽然 API 仍包含相同的程序集代码,只不过名称不同,但 Unity 也会认为缺少原始程序集。
在
.asmdef
中添加
定义约束
如果添加定义约束,那么只要不满足定义约束,Unity 就会跳过程序集的编译。这将导致程序集丢失的情况,即使程序集以前可用。
如果删除对特定平台的支持,则 Unity 不再在该平台上导入程序集,这相当于删除程序集。
您可以通过启用以下属性之一来删除平台:
•
includePlatforms
,这将破坏与所有未列出平台的兼容性
•
excludePlatforms
,这会向其中添加条目
将公共 API 从一个程序集移动到另一个程序集
当您将可公开访问的代码从程序集 A 移到程序集 B 时,任何引用 A 但未引用 B 的程序集都将编译失败。
对于程序集定义,如果移动脚本,则可能会将公共 API 移至其他程序集。
更改
Auto Referenced
属性
禁用
Auto Referenced
属性时,如果不显式引用,那么您将无法再使用该程序集的公共 API:
• 对于预编译的程序集,禁用此属性会阻止 Unity 隐式添加预编译的程序集作为对程序集定义和项目编译的程序集的引用。
• 对于程序集定义,禁用此属性会阻止 Unity 隐式添加生成的程序集作为对项目编译的程序集的引用。
启用
Auto Referenced
属性时,可能会与 API、属性或依赖关系的其他更改产生冲突。有关更多信息,请参阅
自动引用
部分。
在程序集定义中启用
Unity References → Test Assemblies
属性
启用
Unity References → Test Assemblies
属性会将此程序集标记为测试程序集,而 Unity 通常不会将测试程序集包含在构建中(也不会在某些情况下进行编译)。发生这种情况时,任何引用缺失程序集的程序集都无法找到该程序集,除非它也是测试程序集。
MAJOR、MINOR:非重大 API 更改
下列更改属于
向后兼容
的、非重大的 API 更改。这些情况都添加了程序集,这与删除程序集的重大更改不同。由于添加程序集会增加 API 表面(API 的公开部分),因此被认为是 API 更改。但是,由于没有现有引用,因此添加新程序集不会影响使用更低版本 API 创建的其他程序集。
向后兼容的更改至少需要新的
MINOR
版本。如果您要包含属于重大更改的其他更新,则这些更新也可以成为新的
MAJOR
版本的一部分。
警告
:仅当禁用
Auto Referenced
属性时,这些更改才向后兼容。启用
Auto Referenced
属性后,此表中列出的更改可能会导致重大更改。有关更多信息,请参阅
自动引用
部分。
MAJOR、MINOR、PATCH:无 API 更改
以下更改不会影响公共 API,并且在
PATCH
版本中允许。这些情况下的更改不会改变公共 API,因为它们不会影响 API 表面(API 的公开部分),并且不会对其他使用者产生任何影响。
不会改变公共 API 的更改至少需要新的
PATCH
版本。如果您要包含引入了重大更改或非重大更改的其他更新,那么也可以将这些更新包含在
MAJOR
或
MINOR
版本中。
在
.asmdef
文件中更改引用的程序集和程序集定义的列表
引用另一个程序集的程序集不会自动引用另一个程序集自身的引用,而必须显式列出这些引用。因此,更改程序集定义或程序集内的引用不会影响其他使用者。
更改程序集定义中的
Allow unsafe code
属性
此属性控制是否允许编译器编译具有
unsafe
修饰符的代码。仅更改该标志并不会改变公共 API。
更改程序集定义中的
Override References
属性
此属性控制 Unity 如何为该程序集调用编译器,并且对生成的程序集的使用者没有影响。仅更改该标志并不会改变公共 API。
• 使用修改后的包以非向后兼容的方式更改现有行为,但不修改 API 表面。
• 以一种非向后兼容的方式更改现有的 API,以公开修改后的包中定义的类型。
• 公开 API 中的某些类型,这些类型在修改后的包中以非向后兼容的方式更改。
• 公开 API 中的某些类型,这些类型在修改后的包中不再定义。
MAJOR
MAJOR、MINOR 或 PATCH:其他更改
您可以更改对任何发行版中的 Package Manager、构建管线、脚本管线或资源数据库没有特殊影响的包清单属性。这包括更改
description
、
category
、
keywords
或
displayName
。
如果更改了这些字段,可能表明您所做的更改不仅仅涉及错误修复。请务必考虑新版本中的其他更改是否实际上需要新的 MINOR 或 MAJOR 版本,而不是 PATCH 版本。
注意
:对包清单中的
unity
或者
unityRelease
属性进行更改,始终需要 MINOR 或 MAJOR 版本。尽管这些属性不会影响包 API 本身,但递增 Unity 版本肯定会使包版本不能在以前的 Unity 编辑器上使用,并且可能会破坏依赖项目或包,而递减 Unity 版本会使包可用于较旧的 Unity 编辑器。
已弃用和过时的 API
需要从 API 中删除某些功能时,请首先发布至少一个包含弃用功能的 MINOR 版本。这会提醒用户即将删除功能,让他们能够顺利过渡到新的 API。然后,您可以在新的 MAJOR 版本中删除该功能。
如果另一个开发者通过警告将一个包标记为弃用,并且您在项目中启用了
Warnings as Errors
属性,则从技术上来讲,弃用的包可能会破坏您的项目,但这不是真正的破坏,因为代码仍然可以像之前一样正常工作。
在这种情况下,您可以选择如何修复警告型错误(按照常规的合理性降序排列):
更改您的代码,以便不再使用该 API。
在
#pragma warning
指令中包裹使用该 API 的代码,以便不再显示该警告。
禁用
CS0612 (Obsolete)
和
CS0618 (Obsolete with a message)
警告。
在项目中禁用
Warnings as Errors
属性。