如何让 Unity 插件支持旧版本的 Unity?
Posted
技术标签:
【中文标题】如何让 Unity 插件支持旧版本的 Unity?【英文标题】:How to make a Unity plugin support old versions of Unity? 【发布时间】:2019-11-15 09:33:45 【问题描述】:我正在为 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 年左右)能够正确导入和使用它,对吧?
【问题讨论】:
【参考方案1】:在您的代码中,您可以使用c# pre-processors 来使代码编译或根据某些全局定义有条件地注释掉。
Unity 提供Version and Platform specific pre-processors
从
Unity 2.6.0
开始,您可以选择性地编译代码。可用选项取决于您正在使用的编辑器版本。给定版本号 X.Y.Z(例如 2.6.0),Unity 以下列格式公开三个全局 #define 指令:UNITY_X
、UNITY_X_Y
和UNITY_X_Y_Z
。
和
从
Unity 5.3.4
开始,您可以根据编译或执行给定代码部分所需的最早版本的 Unity 有选择地编译代码。给定与上述相同的版本格式 (X.Y.Z
),Unity 以UNITY_X_Y_OR_NEWER
的格式公开一个全局#define
,可用于此目的。
因此您可以准确控制哪个代码版本应用于哪个特定目标平台、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 版本创建一个项目,并将旧版本的代码复制粘贴到最新版本的预处理器包装部分中。
为了让我尽可能简单,我可能会使用类似的文件夹结构
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 就足够了,而不是使插件向后兼容到 Unity 2.6 ......无论如何,谁仍然会使用那些旧的东西?
目前在 HUB 中,提供安装的最新版本是 2017.1.5f1
,所以我认为在那个版本之前提供向后支持就足够了。
关于版本控制的问题:Github 提供了一个相当完整的.gitignore
for Unity。在那里你可以看到除了Temp
文件夹之外,你应该 忽略的文件夹还有很多......尤其是Library
。
在this post 中,我还描述了一种使用单个git
命令删除所有生成文件的快速且安全的方法。就我个人而言,我喜欢将所有Library/*.asset
文件从忽略中排除(因此它们是版本控制的),因为这里有一些东西,例如自定义布局,当前构建目标等被存储。
【讨论】:
为了测试插件在不同Unity版本中的实际运行情况,我需要安装多个编辑器版本,并依次打开这个包含多个版本的大项目。由于不同的版本可能会创建自己的(冲突的)临时文件,因此我不仅需要忽略版本控制中的临时文件,还需要在旧编辑器版本中打开项目之前手动删除临时文件。对吗? 查看添加的最后一节以上是关于如何让 Unity 插件支持旧版本的 Unity?的主要内容,如果未能解决你的问题,请参考以下文章
旧版本金庸群侠传3D新Unity重置修复版入门-lua”脚本“