Why does co-editing Unity scene files always cause conflicts? How do we solve this? We take an in-depth look into the file format and toolchain to find a solution.
3. The scene file is the place that integrates the work
of all people working on a project
- Programmers add logic
- Artists add assets and control lighting
- Level designers build levels
- Game designers control balance
For a team member to be able to complete a loop
on their own, they often need to modify the scene
file
Why collaborate?
4. Whats the problem?
Two team members start working on the
scene at the same time, make different
changes and try to commit.
What is the resulting scene file? How do we
get there?
5. Previous Work
Some popular workarounds :
- Lock scenes when working on them
- Separate the scenes into several prefabs,
lock prefabs when working on them
Both methods work, but they come with their
problems (hard to scale, need to decide
prefab split, unable to use prefabs for what
they were meant to be)
6. Related Unity Milestones
Why were those workarounds created?
Unity 1.0 - Scenes are binary, can’t merge
Unity 3.0 - Textual version in Pro
Unity 3.5 - Textual version in Free
Unity 4.6.1 - Random IDs for documents
Unity 5 - UnityYAMLMerge
7. Tools required for collaboration
A. Version Control
B. Conflict merging tool
C. Understanding of scene file conflicts
8. Tools required for collaboration
A. Version Control
git, SourceTree
B. Conflict merging tool
P4Merge, UnityYAMLMerge
C. Understanding of scene file conflicts
Today =)
12. Unity scene files
In order to read, understand and solve
conflicts, we should first understand how
Unity stores scene files.
The files are based on the YAML format
13. YAML
--- !invoice
receipt: Oz-Ware Purchase Invoice
date: 2012-08-06
customer:
given: Dorothy
family: Gale
Document separator + identifier
(Multiple documents can exist in
one file)
Key value based storage
Indentation for hierarchy
14. Unity scene YAML
--- !u!1 &1280541007
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1280541011}
- 33: {fileID: 1280541010}
- 65: {fileID: 1280541009}
- 23: {fileID: 1280541008}
m_Layer: 0
m_Name: Box1
Object type (1 = GameObject), ID
Links to component types +
document IDs (they are also linked
back to it via m_GameObject field)
15. Unity scene properties
- The file is just a flat list of Component /
GameObject documents
- Order of documents is irrelevant (!)
- Hierarchy is maintained by two sided
connections (parent points to children,
child points to parent).
--- !u!4 &1280541011
Transform:
m_GameObject: {fileID: 1280541007}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 2, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1949811455}
m_Father: {fileID: 0}
m_RootOrder: 3
16. Understanding .unity conflicts
The common tool to solve conflicts is a “3
way merge” tool, where you see the Base
file, and two conflicting changesets made to
it.
18. Simple test case 3-way-merge
Both changesets tried to insert new lines in
the same position in the file
BaseChange 1 Change 2
19. Simple test case 3-way-merge
In this case, the solution is simple :
Just put one of them after the other
20. Simple test case 3-way-merge
Success!
(But why is Box1 before Box2?)
21. Why does auto-merge fail?
It does not know what we know :
- That a “---” line with different IDs means
that they are two different objects. It
suspects that the lines are the same
change with slightly different values.
- That the order of the documents in the .
scene file is irrelevant. Who should be
before who in the text file?
22. Smart auto-merge
A suggestion for an algorithm to smartly
merge .scene files :
- Break down the scene file into separate
objects (based on the document
identifiers)
- Merge each document separately
- Dump back into .scene file
23. (Inside .gitconfig)
[merge]
tool = unityyamlmerge
[mergetool "unityyamlmerge"]
trustExitCode = false
cmd = ' <path to UnityYAMLMerge> ' merge -p "$BASE" "$REMOTE" "$LOCAL" "$MERGED"
UnityYAMLMerge
In Unity 5, a tool called “UnityYAMLMerge”
was introduced.
It can be integrated as a pre-merge step in
source control tools :
25. Related Unity Milestones
Why were those workarounds created?
Unity 1.0 - Scenes are binary, can’t merge
Unity 3.0 - Textual version in Pro
Unity 3.5 - Textual version in Free
Unity 4.6.1 - Random IDs for documents
Unity 5 - UnityYAMLMerge
26. Not 100% automatic
In some cases, conflicts are real:
- Different changes are made to same
components
- Child ordering is not always resolved in
the diff. Manual fixups may be necessary.
- One changeset deletes an object, the
other modifies it
These are real conflicts, and need to be
solved like code conflicts.
27. Summary
- Unity .scene conflicts are scary if not
understood
- Understanding the file format allows
technical conflicts to be easily resolved
(UnityYAMLMerge)
- Once they are solved, the real conflicts
are easier to read and manage