It's difficult to share code between multiple projects if the shared code is still under rapid development. Two different teams will eventually be in different stages of development because it is unlikely they both will have the same project schedule. Eventually, one team will need to make a change to the shared code that no one else wants.
There are a couple of different cases you should consider:
One team needs to put a "hack" in the shared code to make a milestone quickly, and the other team wants to code the "real" solution.
One team is close to shipping and has started a total code lockdown. No one can change anything. The other team needs to make modifications to the shared code to continue development.
How do you deal with this sticky problem? Branching, of course.
In the case of the scenario where two project teams need to share a common game engine, the game engine has three branches:
Main: The normal development branch
Publish_Project_A: The Publish branch for the first project
Publish_Project_B: The Publish branch for the second project
The branching scripts for opening and closing the publish phases for the shared code work because the target branch is a macro: %BRANCHNAME%.
While both projects are in normal development, they both make changes to the shared engine code in the Main branch. If either project goes into a milestone approval phase, they fix milestone blockers in the Publish branch for their project. This allows both projects to be in a milestone acceptance phase at exactly the same time. After their milestone has been approved, the changes get merged back into the main line. When either project hits code lockdown, meaning that only a few high priority changes are being made to the code, the project stays in the Publish branch until it ships.
All this work assumes the two teams are motivated to share the game engine, and continually contribute to its improvement. There might be a case for one project permanently branching the shared code, in which case it should get its own code line apart from the Main branch of the original shared code. It's trivial to merge any two arbitrary code lines as long as they originated from an original source.