如何使 Unity 插件支持旧版本的 Unity?
How to make a Unity plugin support old versions of Unity?
我正在为 Unity 开发一个插件。比如说,在我的机器上安装了最新版本的 Unity(现在是 2019.1.8)。但是,我也希望插件支持旧版本的 Unity,最好是非常旧的版本(如 4.x 或 5.x)。这应该如何实现?
我想我需要在我的机器上安装不同版本的 Unity。例如。使用 Unity Hub 或每次我想在安装新版本之前保留一个版本时手动重命名 Unity 的安装文件夹(如此处所述:https://support.unity3d.com/hc/en-us/articles/210001066-Can-I-activate-more-than-one-version-of-Unity-on-the-same-machine-)。
在 Unity Asset Store 上发布插件时,我还必须上传多个 *.unitypackage
文件,Unity Asset Store 会根据安装的 Unity 版本向每个买家提供适当的文件买家机器上的编辑器。
由于 Unity 版本可能存在显着差异,因此我基本上必须同时开发多个项目。并且(尤其是在开发后期)必须手动将代码中的单个更改复制到项目的所有其他版本中。这是有道理的,因为在某些情况下,它不会简单地复制和粘贴,而是调整代码以解决旧版本中未存在、已重命名、已弃用等问题。
对我来说,这看起来是不可思议的开销。 Unity 插件的开发人员是否真正做到了这一切,还是有更简单的方法?如果我简单地使用最新版本的 Unity 构建并只上传一个 *.unitypackage
文件,那么只有一些最新版本的 Unity(通常最多大约 1 年)才能正确导入和使用它,对吧?
通常在您的代码中,您可以使用 c# pre-processors 以使代码编译或在某些全局定义上有条件地注释掉。
Unity 提供 Version and Platform specific pre-processors
From Unity 2.6.0
onwards, you can compile code selectively. The options available depend on the version of the Editor that you are working on. Given a version number X.Y.Z (for example, 2.6.0), Unity exposes three global #define directives in the following formats: UNITY_X
, UNITY_X_Y
and UNITY_X_Y_Z
.
和
Starting from Unity 5.3.4
, you can compile code selectively based on the earliest version of Unity required to compile or execute a given portion of code. Given the same version format as above (X.Y.Z
), Unity exposes one global #define
in the format UNITY_X_Y_OR_NEWER
, that can be used for this purpose.
因此您可以准确控制哪个代码版本应用于哪个特定目标平台、Unity 版本、.Net 版本等
您可以包装您的代码,例如在
#if UNITY_2017_1_OR_NEWER
/* Code that only compiles under newer version */
#elif UNITY_5
/* Code that compiles for Unity 5.x.y */
#elif UNITY_4
/* Code that compiles for Unity 4.x.y */
#else
/* apparently some older stuff */
#endif
然后您可以将其全部打包到一个 *.unitypackage
中,用户甚至不会注意到。由于在构建的应用程序中删除了注释掉的内容,因此不会增加构建大小。
然而,发展结构是另一个问题。我认为,为了确保支持有效,您不会为每个 Unity 版本准备一个项目,然后将旧版本的代码复制粘贴到最新版本的 pre-processor 包装部分。
为了尽可能简单,我可能会使用像
这样的文件夹结构
YourPlugIn
|-- General
|-- Unity4
|-- Unity5
|-- Unity2017
并使用 partial
关键字来实现完整的行为,而不是启用和禁用单个代码块,例如
General/MyBehaviour.cs
public partial class MyBehaviour : MonoBehaviour
{
// this is the script users should be dragging onto objects
}
Unity4/MyBehaviour_4.cs
#if UNITY_4
// Extends the general MyBehaviour for Unity 4.x.y
public partial class MyBehaviour
{
public string InitialValue;
private void Start()
{
Debug.Log(InitialValue);
}
}
#endif
Unity5/MyBehaviour_5.cs
#if UNITY_5
// Extends the general MyBehaviour for Unity 5.x.y
public partial class MyBehaviour
{
public int InitialValue;
private void Start()
{
Debug.Log(InitialValue.ToString());
}
}
#endif
Unity2017/MyBehaviour_2017.cs
#if UNITY_2017
// Extends the general MyBehaviour for Unity 2017.x.y
public partial class MyBehaviour
{
public Vector3 InitialValue;
private void Start()
{
Debug.Log(InitialValue.ToString());
}
}
#endif
但是那么你不能使用任何例如UNITY_X_Y_OR_NEWER
定义是因为你会得到重复的 ;)
当然还有很多问题区域,例如之后重命名您的 类 或在较新的版本中将它们包装在接口等中..但我希望我的想法很清楚。
我还冒着风险声称只支持“最新”版本的 Unity 就足够了,而不是 Plug-In 向后兼容到 Unity 2.6 ...谁还会使用还是那些老东西?
目前在 HUB 中,提供安装的最新版本是 2017.1.5f1
,所以我认为在那个版本之前提供向后支持就足够了,不再有任何进一步的支持。
关于版本控制的问题:Github 提供了一个相当完整的 .gitignore
for Unity。在那里你可以看到你 应该 忽略的 Temp
文件夹还有很多.. 特别是 Library
.
在 中,我还描述了一种快速且安全的方法,可以使用一个 git
命令删除所有生成的文件。就我个人而言,我喜欢 exclude 所有 Library/*.asset
文件从忽略(因此它们 是 版本控制)因为这里有些东西,例如存储自定义布局、当前构建目标等。
我正在为 Unity 开发一个插件。比如说,在我的机器上安装了最新版本的 Unity(现在是 2019.1.8)。但是,我也希望插件支持旧版本的 Unity,最好是非常旧的版本(如 4.x 或 5.x)。这应该如何实现?
我想我需要在我的机器上安装不同版本的 Unity。例如。使用 Unity Hub 或每次我想在安装新版本之前保留一个版本时手动重命名 Unity 的安装文件夹(如此处所述:https://support.unity3d.com/hc/en-us/articles/210001066-Can-I-activate-more-than-one-version-of-Unity-on-the-same-machine-)。
在 Unity Asset Store 上发布插件时,我还必须上传多个 *.unitypackage
文件,Unity Asset Store 会根据安装的 Unity 版本向每个买家提供适当的文件买家机器上的编辑器。
由于 Unity 版本可能存在显着差异,因此我基本上必须同时开发多个项目。并且(尤其是在开发后期)必须手动将代码中的单个更改复制到项目的所有其他版本中。这是有道理的,因为在某些情况下,它不会简单地复制和粘贴,而是调整代码以解决旧版本中未存在、已重命名、已弃用等问题。
对我来说,这看起来是不可思议的开销。 Unity 插件的开发人员是否真正做到了这一切,还是有更简单的方法?如果我简单地使用最新版本的 Unity 构建并只上传一个 *.unitypackage
文件,那么只有一些最新版本的 Unity(通常最多大约 1 年)才能正确导入和使用它,对吧?
通常在您的代码中,您可以使用 c# pre-processors 以使代码编译或在某些全局定义上有条件地注释掉。
Unity 提供 Version and Platform specific pre-processors
From
Unity 2.6.0
onwards, you can compile code selectively. The options available depend on the version of the Editor that you are working on. Given a version number X.Y.Z (for example, 2.6.0), Unity exposes three global #define directives in the following formats:UNITY_X
,UNITY_X_Y
andUNITY_X_Y_Z
.
和
Starting from
Unity 5.3.4
, you can compile code selectively based on the earliest version of Unity required to compile or execute a given portion of code. Given the same version format as above (X.Y.Z
), Unity exposes one global#define
in the formatUNITY_X_Y_OR_NEWER
, that can be used for this purpose.
因此您可以准确控制哪个代码版本应用于哪个特定目标平台、Unity 版本、.Net 版本等
您可以包装您的代码,例如在
#if UNITY_2017_1_OR_NEWER
/* Code that only compiles under newer version */
#elif UNITY_5
/* Code that compiles for Unity 5.x.y */
#elif UNITY_4
/* Code that compiles for Unity 4.x.y */
#else
/* apparently some older stuff */
#endif
然后您可以将其全部打包到一个 *.unitypackage
中,用户甚至不会注意到。由于在构建的应用程序中删除了注释掉的内容,因此不会增加构建大小。
然而,发展结构是另一个问题。我认为,为了确保支持有效,您不会为每个 Unity 版本准备一个项目,然后将旧版本的代码复制粘贴到最新版本的 pre-processor 包装部分。
为了尽可能简单,我可能会使用像
这样的文件夹结构YourPlugIn
|-- General
|-- Unity4
|-- Unity5
|-- Unity2017
并使用 partial
关键字来实现完整的行为,而不是启用和禁用单个代码块,例如
General/MyBehaviour.cs
public partial class MyBehaviour : MonoBehaviour
{
// this is the script users should be dragging onto objects
}
Unity4/MyBehaviour_4.cs
#if UNITY_4
// Extends the general MyBehaviour for Unity 4.x.y
public partial class MyBehaviour
{
public string InitialValue;
private void Start()
{
Debug.Log(InitialValue);
}
}
#endif
Unity5/MyBehaviour_5.cs
#if UNITY_5
// Extends the general MyBehaviour for Unity 5.x.y
public partial class MyBehaviour
{
public int InitialValue;
private void Start()
{
Debug.Log(InitialValue.ToString());
}
}
#endif
Unity2017/MyBehaviour_2017.cs
#if UNITY_2017
// Extends the general MyBehaviour for Unity 2017.x.y
public partial class MyBehaviour
{
public Vector3 InitialValue;
private void Start()
{
Debug.Log(InitialValue.ToString());
}
}
#endif
但是那么你不能使用任何例如UNITY_X_Y_OR_NEWER
定义是因为你会得到重复的 ;)
当然还有很多问题区域,例如之后重命名您的 类 或在较新的版本中将它们包装在接口等中..但我希望我的想法很清楚。
我还冒着风险声称只支持“最新”版本的 Unity 就足够了,而不是 Plug-In 向后兼容到 Unity 2.6 ...谁还会使用还是那些老东西?
目前在 HUB 中,提供安装的最新版本是 2017.1.5f1
,所以我认为在那个版本之前提供向后支持就足够了,不再有任何进一步的支持。
关于版本控制的问题:Github 提供了一个相当完整的 .gitignore
for Unity。在那里你可以看到你 应该 忽略的 Temp
文件夹还有很多.. 特别是 Library
.
在 git
命令删除所有生成的文件。就我个人而言,我喜欢 exclude 所有 Library/*.asset
文件从忽略(因此它们 是 版本控制)因为这里有些东西,例如存储自定义布局、当前构建目标等。