如何让 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_XUNITY_X_YUNITY_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”脚本“

2017年Unity开发环境与插件配置安装(总体介绍)

如何完全卸载unity3d

如何为 Linux (Arch) 手动安装旧版本的 unity (2019)

什么是unity3d?

vs2010上如何调试unity脚本