Browse Source

Typo Fixes

Steffen Cole Blake 2 years ago
parent
commit
a5170f0169
1 changed files with 19 additions and 19 deletions
  1. 19 19
      content/post/unity/building-a-gamestate-with-zenject-in-unity.md

+ 19 - 19
content/post/unity/building-a-gamestate-with-zenject-in-unity.md

@@ -17,9 +17,9 @@ series = ["Unity"]
 aliases = ["building-a-gamestate-with-zenject-in-unity"]
 +++
 
-Unity provides countless mechanisms by which one can shoot themself in the foot. It's a common and popular entrypoint to picking up C# for newcomers to the language. However, there's a common gotcha individuals will quickly begin to encounter as they familiarize themselfs with the basics of the language via Unity's `MonoBehavior` classes.
+Unity provides countless mechanisms by which one can shoot themself in the foot. It's a common and popular entrypoint to picking up C# for newcomers to the language. However, there's a common gotcha individuals will quickly begin to encounter as they familiarize themselves with the basics of the language via Unity's `MonoBehavior` classes.
 
-Unfortunately this comes with a common and harsh pitfall: By default, Unity really encourages individuals to produce countless individual batches of code that they tightly couple to their game objects, which results in sooner than usual confronting the big bad wold that is the Byzantine Generals Problem.
+Unfortunately this comes with a common and harsh pitfall: By default, Unity really encourages individuals to produce countless individual batches of code that they tightly couple to their game objects, which results in sooner than usual confronting the big bad wolf that is the Byzantine Generals Problem.
 
 For those not in the know, the crux of the issue is the fact that by breaking up their game state into numerous individual "shards", where every individual entity in their game has its own pool of statefulness, it produces a very easy pile of spaghetti one can find themself tripping and falling into.
 
@@ -45,7 +45,7 @@ We will need to do some initial bootstrapping of the project to get all the basi
 
 3. While we are at it, add a new script and call it `GameEngine` (Add Component > New Script)
 
-4. Drag the our `Startup Installer` script component up to the `Mono Installers` list in the `Scene Context` component. (You may need to hit the + button, and you can just drag and drop the whole `Startup` object onto the field if you like, Unity will figure it out)
+4. Drag the `Startup Installer` script component up to the `Mono Installers` list in the `Scene Context` component. (You may need to hit the + button, and you can just drag and drop the whole `Startup` object onto the field if you like, Unity will figure it out)
 
 5. Open up the `MonoInstaller` script, and add a Serialized private field named `GameEngine` of type `GameEngine` (the class we just made) to it and save. A field for it should show up in the inspector now. Drag and drop our Game Engine component onto that field. (The same trick as #4 works here, you can drag and drop the entire Startup object if you like)
 
@@ -73,7 +73,7 @@ This is now the bare bones basic of registering for Dependency Injection, lets n
 
 # Utility Files
 
-Lets put together a few pieces to demonstrate the Game State system in action. To Begin with, we need a couple cs files that provide handy utility for the purpose of this project. You can download and save them to the following path (you'll need to make the folder for it): `Assets/Scripts/Utilities`
+Let's put together a few pieces to demonstrate the Game State system in action. To Begin with, we need a couple cs files that provide handy utility for the purpose of this project. You can download and save them to the following path (you'll need to make the folder for it): `Assets/Scripts/Utilities`
 
 ## File one: ExpressionExtensions.cs
 
@@ -85,7 +85,7 @@ This file utilizes a handy extension method I have made for Expression trees. At
 
 ## File two: PropertyWatcherBase.cs
 
-This file has a very handy base class that implements the `INotifyPropertyChanged` event, which is going to be the key lynchpin used to apply single source of truth logistics to our project. Our Game State class we make later will make heavy use of this class.
+This file has a very handy base class that implements the `INotifyPropertyChanged` event, which is going to be the key lynchpin used to apply Single Source of Truth logistics to our project. Our Game State class we make later will make heavy use of this class.
 
 {{< rawhtml >}}
 <a href="/scripts/building-a-gamestate-with-zenject-in-unity/PropertyWatcherBase.cs" target="_blank">PropertyWatcherBase.cs</a>
@@ -93,19 +93,19 @@ This file has a very handy base class that implements the `INotifyPropertyChange
 
 There are two methods on this base class, let's dig into how they work. To begin with, the interface `INotifyPropertyChanged` requires the event delegate `PropertyChanged` to exist, which is our Pub/Sub model that our services can publish and subscribe to. This will be our main mechanism for how we inform services that changes have occurred to the Game state.
 
-The first method, `Mutate`, is our "writer" that will automatically invoke the aformentioned event when we write changes. I'll show how we hook that up to Full Properties on an implementing class in a moment below.
+The first method, `Mutate`, is our "writer" that will automatically invoke the aforementioned event when we write changes. I'll show how we hook that up to Full Properties on an implementing class in a moment below.
 
 The second method, `BindChild` is a handy tool to let us nest `PropertyWatcherBase` models, so we can have children of the parent GameState (and further nested down, grandchildren and etc), this method will listen to a child's event and appen the parent's name to it in the form of `Parent.Child`, which gives it a unique signature.
 
 # Building our GameState
 
-Alright, time to show it in action! Create a new script file, lets call it `GameState.cs` to keep it simple, and put it in the folder `Assets/Scripts/PropertyWatchers`. Lets also make a second file called `ChildGameState.cs` and put it in that folder too.
+Alright, time to show it in action! Create a new script file, let's call it `GameState.cs` to keep it simple, and put it in the folder `Assets/Scripts/PropertyWatchers`. Lets also make a second file called `ChildGameState.cs` and put it in that folder too.
 
 Both will inherit from `PropertyWatcherBase`. 
 
 We also want to put a full property on the child, let's make it an int and just call it `Counter` with the backing field `_counter`.
 
-The parent `GameState` class will get its own full property, lets make that one an instead of `ChildGameState` called `Child`, backed by the field `_child`
+The parent `GameState` class will get its own full property, let's make that one an instead of `ChildGameState` called `Child`, backed by the field `_child`
 
 Next, we utilize the `Mutate` method on `Counter`'s `Set` method to hook in the event, and `BindChild` on `Child`'s setter (in GameState) to bubble the event up. We can keep `Child`'s setter `private`, because though we want the properties of our classes to be mutable, we don't want the classes themselves to be.
 
@@ -180,11 +180,11 @@ You can also do the same for the `Text (TMP)` child of the `Button` to make it's
 Theoretically you should have something that sort of looks like this when you run your game:
 ![Game visual example 1](/images/building-a-gamestate-with-zenject-in-unity/startup-step-2.png)
 
-Clicking the button doesnt do anything yet, but lets start wiring up our `MonoBehavior`s to our `GameEngine`!
+Clicking the button doesnt do anything yet, but let's start wiring up our `MonoBehavior`s to our `GameEngine`!
 
 # Event pushing a MonoBehavior
 
-Now, theoretically we could directly try and access the GameState from any given `MonoBehavior`, but that is the way to spaghetti land. Instead, aside from our single `GameEngine` monobehavior, we want to utilize Inversion of Control to keep all of our other `MonoBehavior` objects as incredibly simple, lightweight, and "glass box" as possible. For all intents and purposes, each of our remaining `MonoBehavior` scripts should have no concept of any *other* `MonoBehaviors`,*nor* the Game state or engine or anything else. They should purely have two things they do:
+Now, theoretically we could directly try and access the GameState from any given `MonoBehavior`, but that is the way to spaghetti land. Instead, aside from our single `GameEngine` `MonoBehavior`, we want to utilize Inversion of Control to keep all of our other `MonoBehavior` objects as incredibly simple, lightweight, and "glass box" as possible. For all intents and purposes, each of our remaining `MonoBehavior` scripts should have no concept of any *other* `MonoBehaviors`,*nor* the Game state or engine or anything else. They should purely have two things they do:
 
 1. Expose methods to manipulate their own fields, like transform, sprites, text, etc.
 
@@ -192,13 +192,13 @@ Now, theoretically we could directly try and access the GameState from any given
 
 To distinguish these "simple" `MonoBehavior`'s, I like to refer to them as `Entities`, unlike the `GameEngine`, they represent actual "things" in the scene. Objects, Sprites, Text, Buttons, etc etc.
 
-Lets create two of these as an example, with the `TextMeshPro` we made on the top being a prime example of #1, and the Button we made as an example of #2.
+Let's create two of these as an example, with the `TextMeshPro` we made on the top being a prime example of #1, and the Button we made as an example of #2.
 
 Start off by adding a new script component to both the `Text (TMP)` game object (the big one, not the one inside the button), and name it `TextEntity`. We will also add a new on to the Button and call it `ButtonEntity`
 
 Make sure both of these end up in `Assets/Scripts/Entities`, to stay organized.
 
-`TextEntity` needs a serialized `TMP_Text` field, lets call it `Text`, as well as a public method called `SetText` that takes in a string and assigns the value of it to `Text.text`
+`TextEntity` needs a serialized `TMP_Text` field, let's call it `Text`, as well as a public method called `SetText` that takes in a string and assigns the value of it to `Text.text`
 
 `ButtonEntity` needs a public `event` called `Clicked` (untyped of EventHandler), and a method called `OnClick` that null coalesce invokes it (as per typical event style). If you'd like to read up on C# event delegates, [check this link out!](https://learn.microsoft.com/en-us/dotnet/standard/events/)
 
@@ -227,7 +227,7 @@ Your `Text (TMP)` and `Button` should now look like these, respectively:
 
 ![TMP and Button Component Examples](/images/building-a-gamestate-with-zenject-in-unity/startup-step-3.png)
 
-Finally, lets register both of these on our Dependency Injection Engine, to make sure we can inject references to them for the next step. Our `StartupInstaller` will want them as Field References, ideally.
+Finally, let's register both of these on our Dependency Injection Engine, to make sure we can inject references to them for the next step. Our `StartupInstaller` will want them as Field References, ideally.
 
 ```csharp {linenos=table}
 public class StartupInstaller : MonoInstaller
@@ -258,7 +258,7 @@ public class StartupInstaller : MonoInstaller
 
 ```
 
-IMPORTANT! Dont forget to drag and drop the TMP Pro and the Button onto the two new fields we added to `Startup`'s `StartupInstaller` component!
+IMPORTANT! Don't forget to drag and drop the TMP Pro and the Button onto the two new fields we added to `Startup`'s `StartupInstaller` component!
 
 We are now prepared to wire our Scene up to our `GameEngine`!
 
@@ -268,11 +268,11 @@ To start, let's make ourselves a Service to delegate out the task of handling th
 
 Largely speaking, nearly all of your code should be inside of various `Service`s, and they should act as your way of sorting out your code to different areas that make sense. The `GameEngine` should try its best to hand work off to various `Service`s as fast as possible, keeping it as simple as possible in the `GameEngine` itself. Largely speaking the engine's job should be to simply handle delegating what `Service`s are and are not being fired off during each `Update` tick.
 
-Lets make a folder for these, at `Assets/Scripts/Services`, and make our first service in there. Lets call it `EntityService`, and it will have the job of managing our Entities.
+Let's make a folder for these, at `Assets/Scripts/Services`, and make our first service in there. Lets call it `EntityService`, and it will have the job of managing our Entities.
 
 We will want to inject the `GameState`, `TextEntity`, and `ButtonEntity` into it via Constructor Injection (which is as simple as just using it as a param in the public constructor)
 
-Next, we can have this service wire up to our service which handle delegation of mutating the Text Entity, and listening for the Button entity's click event. At the core of it, the `EntityService` serves the role of delegating information back and forth between Game State <-> Entities. This isn't completely mandatory as you could just inject the Game State directly into the Entities, but in actual practice there likely would be much more complicated logic than what we have here, and the service should act as the space to put all that logic to keep it compartmentalized off.
+Next, we can have this service wired up to handle delegation of mutating the Text Entity, and listening for the Button entity's click event. At the core of it, the `EntityService` serves the role of delegating information back and forth between Game State <-> Entities. This isn't completely mandatory as you could just inject the Game State directly into the Entities, but in actual practice there likely would be much more complicated logic than what we have here, and the service should act as the space to put all that logic to keep it compartmentalized off.
 
 You should end up with something a bit like this:
 
@@ -334,7 +334,7 @@ public class GameEngine : MonoBehaviour
 }
 ```
 
-`MonoBehaviors` cannot use Constructor Injection, and instead utilize a slightly different but similiar form where you need to make a method and tag it with the `Inject` attribute. Typically you name it `Init(...)`. Ideally, we only need to do this once in this single place, as prior mentioned this should be the only `MonoBehavior` we inject anything into.
+`MonoBehaviors` cannot use Constructor Injection, and instead utilize a slightly different but similar form where you need to make a method and tag it with the `Inject` attribute. Typically you name it `Init(...)`. Ideally, we only need to do this once in this single place, as prior mentioned this should be the only `MonoBehavior` we inject anything into.
 
 If you run your program and click the button, you should see the count increase! Congrats, you now have a working single source of truth `GameState`!
 
@@ -345,9 +345,9 @@ If you run your program and click the button, you should see the count increase!
 
 Simple, because now if *any* of your services modifies `GameState.Child.Counter`, it will also update the counter text without any extra effort.
 
-Lets do an example with an `async void` to make a sort of background timer that will also automatically increment the count every 5 seconds, on top of any button clicks you do.
+Let's do an example with an `async void` to make a sort of background timer that will also automatically increment the count every 5 seconds, on top of any button clicks you do.
 
-To start, lets make a new service for this called `BackgroundTimerService`, and this time we only need to inject the `GameState`
+To start, let's make a new service for this called `BackgroundTimerService`, and this time we only need to inject the `GameState`
 
 We will make a background async method via `async void`, and simply just have an infinite loop that increments the counter every 5 seconds via `Task.Delay(...)`