如何将一个Unity项目嵌套到另一个?

我正在Unity中创建一个AI课程。 关于我的问题,这个课程有两个重要的特点:

  1. 每个教程都是一个单独的Unity项目,可以加载,允许学生在课程的任何地方开始,并有一个项目,反映他们正在观看的video中覆盖的项目。
  2. 每个教程都建立在以前的教程之外。 例如,教程一只是提供课程的基础世界。 教程5包括从基本世界开始的教程1-4中介绍的所有代码和资产。

我的问题是, 如何管理Unity项目的嵌套,而不需要大量的手动更新和复制?

比方说,当我为教程5创建内容时,发现在教程2中创建的代码中存在一个错误。我不想更新教程2,3,4和5.我想修复教程2中的错误,并通过所有将来使用该代码或资产的教程进行传播。

从本质上讲,每个教程都是完成项目途中的里程碑。 完成的项目是所有教程的总和,将包含所有的代码,资产,预制等。

你可以把它想象成一个依赖树。 教程5取决于教程4的代码和资产,这取决于教程3的代码和资产等等。 如果这是一个Visual Studio项目,我会创建一个新的项目,并configuration依赖于一个解决scheme。

在这里输入图像描述

在这个例子中,这些行表示相互相同的文件。 源项目中的文件更改应在后续项目中更新文件。 理想情况下,任何项目中的文件更改都会更新所有其他项目,但这不是必需的function

当然,我也使用源代码管理。 所以可能有一两个我可以利用在那里,但我不知道。

有些事情我不认为会奏效:

  1. 将代码导出为DLL,以用于下一个项目。 我不认为这会起作用,因为我不希望学生必须用自己的项目做到这一点。 这意味着一次一个教程的学生将有一个不同的代码结构,而不是开始部分学习的学生。
  2. 创建Unity软件包。 这将维护代码,资产和预制件,但是(据我所知)将要求我为每个项目的后续更改的项目重新导出和重新导入包。 但是我相信,如果有一种方法可以实现stream程的自动化,那么这是最有潜力的。

像这样的嵌套项目在其他情况下也是有用的。 就像一个建立了核心项目的开发人员一样,他们想要开始他们所有的项目。 他们可以有5个游戏,都具有相同的“基础项目”,并且5个游戏中的每一个都将受益于进入基础项目的错误修复或function增加,这意味着改变只是一次。

统一的方式

自动导出和导入包文件。 这可以通过使用Unity的命令行选项和一个批处理脚本文件来完成,就像下面的脚本一样(添加换行符以增加可读性):

Unity -projectPath "C:\Code\AI\Base\BaseWorld" -exportPackage "Assets\Scripts" "C:\Code\AI\BaseWorldPackage.unitypackage" -quit Unity -projectPath "C:\Code\AI\Ch01\Chapter1" -importPackage "C:\Code\AI\BaseWorldPackage.unitypackage" -exportPackage "Assets\Scripts" "C:\Code\AI\Chapter1.unitypackage" -quit 

这对于select您想从之前的项目中结转的资产非常适用。 每个项目都添加自己的资产,加上从前一个项目导入的资产,并生成自己的软件包以供使用。

这里的警告是这是单向的。 在ProjectN + 2中更改文件非常容易,即使该文件来自ProjectN。 在下次脚本运行时,这一更改将被覆盖,因为ProjectN中没有进行更改,并且所有更新仅朝一个方向。

文件系统的方式

硬链接。 为要结转的每个资源文件创建硬链接。 这允许文件内容在两个方向上同步,因为对文件的任何编辑基本上都是编辑同一个文件。 有一些工具可以帮助创建这些链接,从而简化stream程。

这里需要注意的是这些结构不容易被源代码控制。 有些源代码管理系统在硬链接或符号链接上效果不佳。 另外,在克隆存储库时,它们不会重新创建链接结构。 此外,文件重命名在这里不是很好的支持。

源代码管理方式

使用subrepositories或svn:外部 。 这些本质上是一个嵌套在另一个内的存储库。 这可能会变得棘手,因为这些结构通常在目录级别。 这意味着您不能将其他文件添加到嵌套的目录中。 这使得一些分裂的项目。 另外,为了获得最新的更新,源代码需要被检入然后出到嵌套的回购站。

robocopy的方式

创建一个脚本来复制文件。 Robocopy有许多选项。 下面的脚本具有以下属性:1.将BaseWorld中的所有文件和目录复制到Chapter1 2.同步BaseWorld和Chapter1之间文件内容的内容(取决于哪个更新)3.允许其他文件在Chapter1和不要复制回BaseWorld

 robocopy "C:\Code\AI\Base\BaseWorld\Assets\Resources" "C:\Code\AI\Ch01\Chapter1\Assets\Resources" /E /XO /XF *.meta robocopy "C:\Code\AI\Base\BaseWorld\Assets\Scripts" "C:\Code\AI\Ch01\Chapter1\Assets\Scripts" /E /XO /XF *.meta robocopy "C:\Code\AI\Ch01\Chapter1\Assets\Resources" "C:\Code\AI\Base\BaseWorld\Assets\Resources" /XO /E /XX /XL robocopy "C:\Code\AI\Ch01\Chapter1\Assets\Scripts" "C:\Code\AI\Base\BaseWorld\Assets\Scripts" /XO /E /XX /XL 

这里的警告是,它并不真正支持文件重命名。 重命名文件或目录将导致文件的旧副本和重命名的文件存在于后续目录中。

目前,似乎没有一个解决scheme,使过程简单和透明。


最终解决scheme

我最终使用了robocopy的方式。 这是两个步骤,副本和副本转发。

复制回来 。 我开始复制项目N中修改的任何文件到项目N-1。 只有项目N-1中存在的文件才从项目N复制。这意味着稍后项目中存在的文件和目录不会被复制回以前的项目。 这意味着我可以对目前正在使用的任何项目中的文件进行更改,并且它会一直更新到它所起源的项目中。元文件在副本中被忽略。

向前复制 。 复制后,我通过项目复制一切。 这是一个更为宽松的方式,如果项目N-1中存在一个文件,它将被复制到N中。这样可以确保在项目链中间从项目中复制的所有更改,现在复制到最新的项目。 元文件被向前复制。 此外,.asset文件也被向前复制。 这包括项目设置,图层,sorting图层和标签。

这两个步骤的方法可以确保在文件发生变化的任何时候,整个项目链都会更新。 提炼哪些文件types包含哪些文件types以及哪些文件types需要排除时,有一些成长的痛苦。 项目设置应该使元文件可见和纯文本。

我发现这种方法是最无缝的。 即使在打开Unity项目时,我也可以运行此脚本(与使用Unity软件包不同)。 而且比使用Unity导出和导入软件包要快得多。 我不必检入代码或花费大量时间来创建新的链接文件。 到目前为止,我一直很满意。 我现在有大约10个这样连接的项目(还有几十个)。 脚本需要大约8秒钟才能完成。

实施细节

我创建了一个C#项目来处理robocopy调用的执行。 我尝试使用批处理脚本来做,但是这比工作更值得:)。 我传入我的项目的根目录。 他们是这样组织的:

 Root Ch01 01 Project 02 Project 03 Project Ch02 01 Project 02 Project Ch03 Etc. 

我parsing这个结构来创建一个迭代项目列表。

对于每个项目,从小费开始复制并移动到基地:

 for(int i = projects.Count-1; i > 0; i--) robocopy projects[i] projects[i-1] /XD "Library" /XO /E /XX /XL *.cs *.shader /XD Library /XF *.asset *.unity 

向前复制,为每个项目,从基地开始,转移到提示:

 for(int i = 0; i < projects.Count - 1; i++) robocopy projects[i] projects[i + 1] /E *.cs *.prefab *.controller *.anim *.png *.mat *.shader *.meta /XD Library robocopy projects[i]\ProjectSettings\ projects[i + 1]\ProjectSettings\ *.asset