Okay. I think I understand the problem fully now.
In short, it boils down to this:
All of the correct DLLs need to be in the right place at the right time.
There’s actually quite a few weird things that can happen so let me explain in more detail.
I’ll start by explaining how I reproduced the problem as closely as possible to your setup.
- Visual Studio 2017 Community
- New MonoGame Windows Project template (DirectX)
- .NET Framework 4.7.2 (must be changed from the default)
- Installed MonoGame.Extended v3.7.0
Test that MonoGame.Extended is working by drawing a rectangle.
_spriteBatch.Begin();
_spriteBatch.FillRectangle(100, 100, 200, 300, Color.Red);
_spriteBatch.End();
So far so good.
Installing MonoGame.Extended.Content.Pipeline
Next I installed the MonoGame.Extended.Content.Pipeline v3.7.0 NuGet package into the project.
Unfortunately, this is where things start going wrong because it replaces the reference to the MonoGame.Framework.dll
with the bait and switch PCL (a complicated topic). Let’s just say that’s not intended behavior and definitely not what we want to happen.
In previous versions of Extended installing the MonoGame.Extended.Content.Pipeline package it would have downloaded the package without modifying the project. You can see in our installation instructions that installing this NuGet package should behave like this:
This package won’t add any references to your project. Instead it will download a DLL that’s intended to be referenced from the MonoGame Content Pipeline tool.
I think this problem came about due to some changes in the way NuGet installs packages that no longer allows this kind of behavior (at least the way we used to do it).
The workaround
The workaround for the above problem (until we’ve got a better solution) is to install the MonoGame.Framework.WindowsDX or MonoGame.Framework.DesktopGL package after installing the MonoGame.Extended.Content.Pipeline package.
This will effectively replace the MonoGame.Framework.dll
with the correct one again.
Not out of the woods yet
At this point the project is compiling and running again and we want to start adding the content to our game.
I tried adding a reference to the Content.mgcb
file in the Pipeline Tool:
..\..\packages\MonoGame.Extended.Content.Pipeline.3.7.0\lib\netstandard2.0\MonoGame.Extended.Content.Pipeline.dll
In theory, we should but able to build a .tmx
file. Unfortunately, this doesn’t work either. We get the Couldn't find a default importer
error.
The problem now is that the Pipeline Tool can’t find all of the DLL’s in needs. The rest of the DLL’s aren’t in the same folder as the MonoGame.Extended.Content.Pipeline.dll
.
My first thought to workaround this was to change the Pipeline reference to point to the DLL that gets copied to the bin
folder at compile time.
/reference:..\bin\Windows\x86\Debug\MonoGame.Extended.Content.Pipeline.dll
This works, breifly, but it creates a new chicken and egg problem.
The chicken and the egg
If we now run “Clean Solution” (to delete the bin
folder) the DLL referenced by the Pipeline Tool no longer exists.
MonoGame annoyingly tries to automatically build the Content before recompiling the program. This is a problem because the Pipeline now depends on a DLL that doesn’t exist and the DLL can’t be built because the Content can’t be built.
The ideal solution to this would be to have MonoGame build the Content after compiling the program but there’s no easy way to control that.
For reference, I think this a problem in the MonoGame.Content.Builder.targets file but I’m not sure.
Another workaround.
The simple one.
The simplest workaround to this problem is to put all of the DLL’s somewhere else so they don’t get deleted and reference them from there.
The problem with this “solution” is that those DLL’s are no longer version controlled with NuGet. This of course means that updating your package references could result in a mismatch between versions running in your game and those used to build the Content. Maybe that’s not a huge problem most of the time, but it could get very confusing when it is.
The weird one.
Another quite weird workaround is to add another project to your solution kinda like the old XNA Content projects.
The GameContent
project is just a regular Class Library but if you setup your project structure like this:
- Solution
- Game (project)
- References
- MonoGame.Extended (NuGet package)
- GameContent (project reference)
- Content
- GameContent (project)
- References
- MonoGame.Extended.Content.Pipeline (NuGet package)
Then the compiler is forced to build things in the right order.
It will now make sure that the MonoGame.Extended.Content.Pipeline.dll
is copied to the bin
folder of the GameContent
project before trying to build the Content.mgcb
file.
This is truly annoying but it does solve the NuGet versioning problem.