You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/tutorials/advanced/2d_shaders/02_hot_reload/index.md
+57-4Lines changed: 57 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -78,7 +78,7 @@ The following command uses the existing target provided by the `MonoGame.Content
78
78
Now, when you change a _`.fx`_ file, all of the content files are rebuilt into `.xnb` files.
79
79
80
80
> [!note]
81
-
> When you run `dotnet watch`, that is actually short hand for `dotnet watch run`. The `run` command _runs_ your game, but the `build` only _builds_ your program. Going forward, the `dotnet watch build` commands will not start your game, just build the content. To learn more, read the official documentation for [`dotnet watch`](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-watch)
81
+
> When you run `dotnet watch`, that is actually short hand for `dotnet watch run`. The `run` command _runs_ your game, but the `build` only _builds_ your program. Going forward, the `dotnet watch build` commands will not start your game, they will just build the content. To learn more, read the official documentation for [`dotnet watch`](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-watch).
82
82
83
83
However, the `.xnb` files are still not being copied from the `Content/bin` folder to _DungeonSlime_'s runtime folder, the `.xnb` files are only copied during the full MSBuild of the game. The `IncludeContent` target on its own does not have all the context it needs to know how to copy the files in the final game project. To solve this, we need to introduce a new `<Target>` that copies the final `.xnb` files into _DungeonSlime_'s runtime folder.
84
84
@@ -119,6 +119,15 @@ And now from the terminal, run the following `dotnet build` command:
119
119
120
120
[!code-sh[](./snippets/snippet-2-12.sh)]
121
121
122
+
> [!CAUTION]
123
+
> What does `--tl:off` do?
124
+
>
125
+
> This tutorial series assumes you are using `net8.0`, but theoretically there is nothing stopping you from using later version of `dotnet`. However, in `net9.0`, a [breaking change](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/9.0/terminal-logger) was made to the `dotnet build`'s log output. There is special code that tries to optimize the log output from `dotnet build` so it does not feel overwhelming to look at. This system is called the _terminal logger_, and sadly it hides the underlying log output from `dotnet watch`. It was _opt-in_ for `net8.0`, but in `net9.0`, it is is _enabled_ by default.
126
+
>
127
+
> **If you are using `net9.0` or above, you _must_ include this option.**
128
+
>
129
+
> `--tl:off` disables the terminal logger so that the `dotnet watch` log output does not get intercepted by the terminal logger.
130
+
122
131
We now have a way to dynamically recompile shaders on file changes and copy the `.xnb` files into the game folder! There are a few final adjustments to make to the configuration.
123
132
124
133
### DotNet Watch, but smarter
@@ -220,12 +229,25 @@ It is time to extend the `ContentManagerExtensions` extension method that the ga
220
229
221
230
[!code-csharp[](./snippets/snippet-2-23.cs)]
222
231
223
-
2. At the top of the `Update()` method in the `GameScene` class, add the following line to opt into reloading the `_grayscaleEffect` asset:
232
+
2. There are two common ways to run your game as you develop,
233
+
- running the game from a terminal by typing `dotnet run`,
234
+
- running the game from an IDE.
235
+
236
+
When you use `dotnet run`, dotnet itself set the [_working directory_](https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.getcurrentdirectory?view=net-9.0) of the program to the folder that contains your `DungeonSlime.csproj` file. However, many IDEs will set the working directory to be within the `/bin` folder of your project, next to the built `DungeonSlime.dll` file.
237
+
238
+
The working directory is important, because the `ContentManagerExtensions.cs` class we wrote uses the `manager.RootDirectory` to reassemble content `.xnb` file paths. The `manager.RootDirectory` is derived from the working directory, so if the working directory changes based on how we start the game, our `ContentManagerExtensions.cs` code will produce different `.xnb` paths.
239
+
240
+
The actual `.xnb` files are in the `/bin` subfolder, so at the moment, running the game from the terminal will not work unless you _manually_ specify the working directory. To solve, this we can force the working directory by adding the [`<RunWorkingDirectory>`](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#runworkingdirectory) property to the `DungeonSlime.csproj` file:
3. Now, when the `grayscaleEffect.fx` file is modified, the `dotnet watch` system will compile it to an `.xnb` file, copy it to the game's runtime folder, and then in the `Update()` loop, the `TryRefresh()` method will load the new effect and the new shader code will be running live in the game.
228
-
Try it out by adding this temporary line right before the `return` statement in the `grayscaleEffect.fx` file, make sure the `dotnet build -t:WatchContent` is running in the terminal and [start the game in debug](/articles/tutorials/building_2d_games/02_getting_started/index.html?tabs=windows#creating-your-first-monogame-application) as normal:
248
+
4. Now, when the `grayscaleEffect.fx` file is modified, the `dotnet watch` system will compile it to an `.xnb` file, copy it to the game's runtime folder, and then in the `Update()` loop, the `TryRefresh()` method will load the new effect and the new shader code will be running live in the game.
249
+
250
+
Try it out by adding this temporary line right before the `return` statement in the `grayscaleEffect.fx` file, make sure the `dotnet build -t:WatchContent` is running in the terminal and [start the game in debug](/articles/tutorials/building_2d_games/02_getting_started/index.html?tabs=windows#creating-your-first-monogame-application) as normal:
The hot reload system is working, but it has a serious weakness. You need to _remember_ to run the following command before starting your game:
325
+
326
+
[!code-sh[](./snippets/snippet-2-12.sh)]
327
+
328
+
After you run that command in a terminal, you need to start your game normally. If you _only_ started the game, but never started the watcher, then your shaders would never be hot reloadable. This kind of error is dangerous because it can undermine trust in the hot reload system itself. It would be better if the watcher was started automatically when the game is run, so that you only need to do one thing, _run the game_.
329
+
330
+
In the `ContentManagerExtensions.cs` file, add this function to the class:
331
+
332
+
[!code-cs[](./snippets/snippet-2-37.cs)]
333
+
334
+
You will need to add the following `using` statement to the top of the file:
335
+
336
+
```csharp
337
+
usingSystem.Reflection;
338
+
```
339
+
340
+
Then, call the new function from the DungeonSlime's `Program.cs` file before starting the game:
Now, you do not need to start the watcher manually. Instead, you can simply the start the game normally, and the watcher process should appear in the background.
345
+
346
+
> [!tip]
347
+
> If you are running the game via the terminal, and you do _not_ want to start the background content watcher, add the `--no-reload` command line option.
348
+
349
+
|||
Copy file name to clipboardExpand all lines: articles/tutorials/advanced/2d_shaders/03_the_material_class/index.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,9 +13,9 @@ In this chapter, we will create a small wrapper class, called the `Material`, th
13
13
If you are following along with code, here is the code from the end of the [previous chapter](https://github.com/MonoGame/MonoGame.Samples/tree/3.8.4/Tutorials/2dShaders/src/02-Hot-Reload-System/).
14
14
15
15
> [!NOTE]
16
-
> The tutorial assumes you have the `watch` process running in the terminal in VSCode, if it is not, start the process using:
16
+
> The tutorial assumes you have the `watch` process running automatically as you start the _DungeonSlime_ game. Otherwise, make sure to start it manually in the terminal in VSCode:
17
17
>
18
-
> ```dotnet build -t:WatchContent```
18
+
> ```dotnet build -t:WatchContent --tl:off```
19
19
20
20
## The Material Class
21
21
@@ -107,7 +107,7 @@ The `_indexLookup` is a `Dictionary<string, int>` containing a mapping of proper
107
107
108
108
[!code-csharp[](./snippets/snippet-3-11.cs)]
109
109
110
-
4.ANd we MUST not forget to invoke this method during the constructor of the `Material`:
110
+
4.And we must not forget to invoke this method during the constructor of the `Material`:
0 commit comments