OK, so I don’t use Perforce or Plastic… but I have used Git, SVN, Vault, and Team Foundation Server for projects through out my career (both in and out of Unity).
So the general way most version control systems work is that you perform commits. You change a whole bunch of files on your computer, save them, and then tell the server you want to ‘commit’ or ‘merge’ those new changes into the current “version” of the project that is on the server.
When it commits the server determines all the differencing information. What’s different about this version with your commits and the last version on the server. A new file was added, an old file was deleted, another file had text added, another file had text removed. And all this information is stored away (usually in a database) and the current files stored. (note - differencing information works best on ‘text-only’ data, this is why it’s suggested to make sure unity has its settings to perform all serialization in text mode, rather than binary).
That “version” on the server is that latest version.
If another user pulls from the server (gets latest) they’ll receive the current version of the project as it is on the server. It’ll bring down the differencing information deleting files that were called to be deleted, adding files that need to be added, and getting the latest versions of files that were changed.
Here’s the thing… what if you’ve changed files locally before calling to get latest. Or what if when I commit, you had previously committed a file that I’m committing as well, but our changes are different.
This is called a ‘conflict’ and it must be resolved. Most version controls will stop the commit or the pull and inform the user that there are conflicts with which ever files. Usually there is some gui that’ll show you the differences between them, and you can decide what to do with them. Of course this usually can also be restricted to specific users in the team… so that only the lead gets to pick which code remains.
Conflicts can be annoying, especially on large teams. Version control does not resolve this issue. And it’s usually up to a project manager to delegate who works on what to avoid overlap of work.
When you’re on a team where ones and artist and the other a programmer, conflicts seldom occur, as you both usually work on different files. The only conflicts we usually have on our team (where I’m the sole programmer) is with some common prefabs, and scenes. And how I deal with that is I just work in my own “DEBUG” scenes where I do my testing, and let the designer move them to the regular in game scenes once we determine the stuff to work.
But when you’re on a larger team, you can have issues. You might have one person working day to day on part of the code, and another going on a week long design process on another part of code. In these situations you’ll probably use things like branching. Where the person going on the exploritory design process will branch off the main project, do there design, and once they confirm it works they’ll go through the long process of merging that branch back into the main code source. While branched any commits they perform to their branch only effects their branch. And any commits on the main code source doesn’t conflict with their branch. They work with whatever version of the code that it was in when the performed the branch.
When you have people working together on the same exact section of code, some version control systems offer ‘locking’ which allows you to flag a file as locked, and if another person attempts to modify it, they get blocked. Unfortunately unity ignores these locks usually and will force files read-write if they’re made read-only. Unity will then screw up data, or worse crash, so I just avoid locks.