使用git和UnityYAMLMerge解决Unity场景中的冲突

Tulenber 1 May, 2020 ⸱ Intermediate ⸱ 6 min ⸱ 2019.3.11f1 ⸱

由于我没有在同事之前提交代码,现在该兑现有关配置git以与Unity配合使用,并弄清楚如何使用UnityYAMLMerge解决冲突。

在上一篇文章中,” Unity自定义编辑器” 我们简要提到了以分布式方式使用各种可视化编辑器时可能出现的问题,例如Unreal中的蓝图。在Unity中,此问题完全适用于场景和预制件。

UnityYAMLMerge

为了解决与场景和预制件的冲突,Unity提供了使用实用程序UnityYAMLMerge。文档提供了有关使用该工具的所有必要信息。尽管如此,它还是有点简洁,并且不关注其使用的基本方面,我们将对其进行详细分析。

我们可以将Unity中的此类冲突分为两个部分:对象冲突和参数冲突。 他们的解决方案分别分为两个阶段:

  1. 使用UnityYAMLMerge在场景中合并对象,因此您可以使用编辑器来解决它
  2. 参数冲突,在第一阶段后未解决,默认情况下由git工具解决

制备

文章” Unity和git” 提供了启动任何项目所需的初始git配置。为了解决对象冲突,我们还需要将UnityYAMLMerge配置为git mergetool。另外,对于参数冲突,我们需要一个具有三向合并功能的工具,该工具可以通过mergespecfile.txt调用。

所有设置都将在本地存储库上执行,因为它们特定于Unity,并且它们的全局设置可能会影响使用其他类型的项目。

解决冲突后,git创建包含原始数据的文件*.orig,它可以确保过程的安全,但是您绝对不需要进一步存储它。通常,您始终可以回滚合并而无需使用此文件。因此,要禁用其生成,请使用以下设置:

1
2
# 在存储库中禁用*.orig文件的生成
git config --add mergetool.keepBackup false

将UnityYAMLMerge设置为git的合并工具:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 将UnityYAMLMerge添加为合并工具
git config --add merge.tool unityyamlmerge

# 不信任退出UnityYAMLMerge的代码
git config --add mergetool.unityyamlmerge.trustExitCode false

# macOs
# <path_to_unity_app>-Unity编辑器当前位置的路径
git config --add mergetool.unityyamlmerge.cmd '<path_to_unity_app>/Unity.app/Contents/Tools/UnityYAMLMerge merge -p "$BASE" "$REMOTE" "$LOCAL" "$MERGED"'

# Windows
# git config --add mergetool.unityyamlmerge.cmd 'C:\Program Files (x86)\Unity\Editor\Data\Tools\UnityYAMLMerge.exe merge -p "$BASE" "$REMOTE" "$LOCAL" "$MERGED"'

标准合并工具

还必须配置标准合并工具的工作,这是主要困难开始的地方^_^

在UnityYAMLMerge可执行文件附近,您可以找到mergespecfile.txt文件。它负责合并工具,如果存在主工具无法解决的参数冲突,它将用作后备。

本文是在macOs下编写的,我无法正常使用标准的opendiff(FileMerge)合并工具。即使假装一切都很好,实际上,当您更改初始值时,合并也会中断。其他工具,例如VSCode,Atom,Jet Brains的Rider,Sublime Text,Sublime-Merge,KDiff3或Diffusion由于各种原因无法正常工作。有些人拒绝按照UnityYAMLMerge提出的方案工作;有些需要额外的库。最后,最有效的解决方案是DiffMerge,包含在中 默认情况下,mergespecfile.txt。 它立即开箱即用地启动,显然是因为它是经过测试的工具之一。P4Merge(Perforce merge)也可以,但是不太稳定。 因此,如果您在macO上遇到问题,请确保注释掉opendiff并配置替代方案。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# UnityYAMLMerge fallback file


# Modify the next two lines if scene or prefab files should fallback
# on other that the default fallbacks listed below.

# %l is replaced with the path of you local version
# %r is replaced with the path of the incoming remote version
# %b is replaced with the common base version
# %d is replaced with a path where the result should be written to
# On Windows %programs% is replaced with "C:\Program Files" and "C:\Program Files (x86)" there by resulting in two entries to try out
# On OSX %programs% is replaced with "/Applications" and "$HOME/Applications" thereby resulting in two entries to try out

unity use "%programs%\YouFallbackMergeToolForScenesHere.exe" "%l" "%r" "%b" "%d"
prefab use "%programs%\YouFallbackMergeToolForPrefabsHere.exe" "%l" "%r" "%b" "%d"

# Default fallbacks for unknown files. First tool found is used.

# Apple File Merge
# 在撰写本文时,几乎无法使用,因此我建议您评论并使用DiffMerge
#* use "/usr/bin/opendiff" %r %l -ancestor %b -merge %d

# Beyond Compare
* use "%programs%\Beyond Compare 4\bcomp.exe" "%r" "%l" "%b" "%d"
* use "%programs%\Beyond Compare 3\bcomp.exe" "%r" "%l" "%b" "%d"
* use "%programs%/Beyond Compare.app/Contents/MacOS/bcomp" "%r" "%l" "%b" "%d"
* use "/usr/bin/bcompare" "%r" "%l" "%b" "%d"

# Araxis Merge
* use "%programs%\Araxis\Araxis Merge\compare.exe" /3 /a2 /wait /title1:"Other" /title2:"Base" /title3:"Local" "%l" "%b" "%r" "%d"
* use "%programs%/Araxis Merge.app/Contents/Utilities/compare" -3 -a2 -wait -title1:"Other" -title2:"Base" -title3:"Local" "%l" "%b" "%r" "%d"

# Perforce merge
* use "%programs%\Perforce\p4merge.exe" "%b" "%r" "%l" "%d"
* use "%programs%/p4merge.app/Contents/Resources/launchp4merge" "%b" "%r" "%l" "%d"

# PlasticSCM merge
* use "%programs%\PlasticSCM5\client\mergetool.exe" -b=%b -s=%l -d=%r -r=%d
* use "%programs%\PlasticSCM4\client\mergetool.exe" -b=%b -s=%l -d=%r -r=%d
* use "%programs%/PlasticSCM/client/mergetool" -b=%b -s=%l -d=%r -r=%d
* use "/opt/plasticscm/client/mergetool" -b=%b -s=%l -d=%r -r=%d
* use "/opt/plasticscm4/client/mergetool" -b=%b -s=%l -d=%r -r=%d

# SourceGear DiffMerge
* use "%programs%\SourceGear\DiffMerge\DiffMerge.exe" --nosplash -m -t1="Incoming Changes"  -t2="Base" -t3="Working Copy" -r="%d" "%l" "%b" "%r"
* use "%programs%\SourceGear\Common\DiffMerge\sgdm.exe" --nosplash -m -t1="Incoming Changes"  -t2="Base" -t3="Working Copy" -r="%d" "%l" "%b" "%r"
* use "%programs%/DiffMerge.app/Contents/MacOS/DiffMerge" --nosplash -m -t1="Incoming Changes"  -t2="Base" -t3="Working Copy" -r="%d" "%l" "%b" "%r"
* use "%programs%/Utilities/DiffMerge.app/Contents/MacOS/DiffMerge" --nosplash -m -t1="Incoming Changes"  -t2="Base" -t3="Working Copy" -r="%d" "%l" "%b" "%r"

VSCode在其2020年计划中还希望增加对三方合并的全面支持; 我们希望它能与UnityYAMLMerge集成在一起而不会遇到麻烦。

测试项目

我们创建一个带有两个分支的测试项目green_spheres:
Green spheres

red_cubes:
Red cubes

尝试将red_cubes分支合并到green_spheres会导致冲突

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
tulenber@mac-tulenber Merge % git status
On branch red_cubes
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   Assets/Scenes/MergeScene.unity

no changes added to commit (use "git add" and/or "git commit -a")

用法

git mergetool尝试将对象合并到一个场景中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
tulenber@mac-tulenber Merge % git mergetool --tool=unityyamlmerge
Merging:
Merge/Assets/Scenes/MergeScene.unity

Normal merge conflict for 'Merge/Assets/Scenes/MergeScene.unity':
  {local}: modified file
  {remote}: modified file
Conflicts:
Left  705507994.Light.m_Color
    r change to 0
    g change to 0.735849
    b change to 0.01896981
Right 705507994.Light.m_Color
    g change to 0.41037738
    b change to 0.44684783
Conflict handling:

未解决的参数冲突导致调用DiffMerge:
DiffMerge

结果

来自两个分支的对象都是可编辑的,并且参数取决于DiffMerge中的合并:
Merge red

Merge green

Sourcetree

Sourcetree - git客户端,由Atlassian开发,在Windows和macOs上均可正常运行。Bitbucket是必不可少的服务,但是Github具有几乎相同的无缝集成。这是一个常用工具,因此让我们也演示如何设置它。

该设置类似于控制台选项。 将UnityYAMLMerge添加到Extrnal Merge tool中 - Preferences > Diff > External Diff / Merge:

  • Merge command - 〈path_to_unity_app〉/Unity.app/Contents/Tools/UnityYAMLMerge
  • Arguments - merge -p "$BASE" "$REMOTE" "$LOCAL" "$MERGED"

Sourcetree settings

另外,不要忘记在控制台版本中上面提到的mergespecfile.txt中设置与其他编辑器的集成; 没有这个,一切都将无法进行。

用法:
Sourcetree external

在操作过程中以及在使用控制台时,将调用DiffMerge,我们将获得相同的结果。

备择方案

  1. 在Unity中处理冲突的主要方法是防止冲突:
    1. 将场景划分为大量的预制件将导致对象设置在不同级别上的分离。结果,当场景发生变化时,场景将不会受到影响,并且发生冲突的频率将大大降低。
    2. 与场景同时进行的最少工作是避免冲突的最简单,最经济的方式^_^
  2. 对于大型(富裕的)团队,还有其他形式的插件,它们允许同时远程编辑场景,例如,Scene Fusion

结论

合并分支机构和解决冲突本身并不是一件容易的事。Unity设置UnityYAMLMerge,mergespecfile.txt和您喜欢的合并实用程序会增加另一个难度。我希望这篇文章表明冲突在统一中合并不会那么可怕。最主要的是要了解工作原理并设置合适的(和有效的)工具。冲突少。下次见!^_^


如果您喜欢这篇文章,可以为它提供支持



Privacy policyCookie policyTerms of service
Tulenber 2020