If you've ever worked on a team using Unity3d, somebody has forgotten to commit a .meta file. It's fairly easy to do, and pretty hard to notice you're doing it (things still work for you, just not others who pull your work in). I've been bitten by this mistake plenty, from myself and others.
The .meta file holds GUID for the given asset, which is how the editor associates assets for serialized data (your prefabs and scenes). When you're serialized data references the wrong id, then you get missing references that show up like "Missing Script" in the editor.
Don't let people commit and push assets without metas.
Most version control systems have hooks that you can run your own scripts in, Mercurials no different.
You can make a pre-commit hook that will look at all your assets and make sure none are missing a meta.
I've made one below. It's worked fine for windows and mac machines, and some version of it has been in every unity project I've done since.
1 import os 2 import mercurial.commands 3 4 class HG: 5 def __init__(self,ui,repo): 6 self.ui = ui 7 self.repo = repo 8 self.files = self.getAddedFiles() 9 10 def existsInRepo(self, filename): 11 self.ui.pushbuffer() 12 mercurial.commands.locate(self.ui,self.repo,include=[filename]) 13 files = self.ui.popbuffer().split("\n") 14 15 for repoFile in files: 16 if(pathsEqual(filename,repoFile)): 17 return True 18 19 return False 20 21 def getAddedFiles(self): 22 self.ui.pushbuffer() 23 mercurial.commands.status(self.ui,self.repo,no_status=True, added = True) 24 files = self.ui.popbuffer().split("\n") 25 return files 26 27 def filesExistInDir(self,dirname): 28 self.ui.pushbuffer() 29 mercurial.commands.locate(self.ui,self.repo,include=[dirname]) 30 files = self.ui.popbuffer().split("\n") 31 files = filter(lambda x:x != "", files) 32 return len(files) > 0 33 34 def show(self, message): 35 self.ui.status(message + "\n") 36 37 def precommit(ui,repo, **kwargs): 38 hg = HG(ui,repo) 39 clean = checkFiles(hg) 40 return not clean; 41 42 def pathsEqual(a,b): 43 return os.path.normcase(a) == os.path.normcase(b) 44 45 46 def checkFiles(hg): 47 48 path = os.path.normcase("UnityProject/Assets/") 49 50 result = True 51 files = hg.files 52 for singleFile in files: 53 if singleFile == '': 54 continue 55 56 if not os.path.normcase(singleFile).startswith(path): 57 continue 58 59 isMetaFile = singleFile.endswith(".meta") 60 61 filename = singleFile if not isMetaFile else singleFile.replace(".meta", "") 62 metaFile = singleFile if isMetaFile else singleFile + ".meta" 63 64 isFolder = os.path.isdir(os.path.normcase(filename)) 65 66 if isMetaFile: 67 if isFolder: 68 if not hg.filesExistInDir(filename): 69 hg.show("Commiting a meta file'" + metaFile + 70 "' for a directory which contains no files." ) 71 return False 72 else: 73 if not hg.existsInRepo(filename): 74 hg.show("Commiting a meta file'" + metaFile + 75 "' without adding associated file '" + filename + "'.") 76 return False 77 78 else: 79 if not hg.existsInRepo(metaFile): 80 hg.show("Committing a file '" + filename + 81 "' without adding associated meta file '" + metaFile + "'.") 82 return False 83 84 85 return result 86
This doesn't handle .meta files for directories. I couldn't think of an elegant way To locate directories from the hg API. Mercurial has no concept of them, files are just at paths. This hasn't been a problem and, AFAIK, directories aren't referenced in serialized data.
checkFiles alter the
path variable so that it points to your assets directory.
The current value reflects my projects, which generally have the unity project folder start at the path
The script only checks the files under that path, and it's relative to your repo's root.
Mercurial needs you to register the hook in your hg config. Everyone on the team should register and use this pre-commit hook in order for it to be effective. I keep them in hooks directory for the project for that reason.
For example, Lets say you saved the above script to a file in your repo at
Then you would add these lines to your
1 [hooks] 2 precommit.checkMetas = python:/pathToUnityRepo/hooks/checkMetas.py:precommit 3