Skip to content

Commit edd684c

Browse files
committed
Updated readme
1 parent 46b6d51 commit edd684c

24 files changed

+532
-594
lines changed

Diff for: README.md

+23-591
Large diffs are not rendered by default.

Diff for: _text/bytecode.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# 10. Bytecode
2+
3+
What if other people want to help you with your game, but these people have no coding skillz. A solution is to invent a simpler programming language everyone can learn, and then you integrate it with your game.
4+
5+
**How to implement?**
6+
7+
The programmers with no skillz write their code in a .txt-file. You read that file, loop through each row, and then use a switch statement to translate the code from your programming language to C#.
8+
9+
**When is it useful?**
10+
11+
- If you want to add modding support.
12+
13+
- If you don't want to hard-code behaviour.
14+
15+
16+
## [Back](../)

Diff for: _text/command.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ You have a base class called Command which has a method that a child can impleme
2626

2727
**Related patterns**
2828

29-
- **[Subclass Sandbox](#11-subclass-sandbox).** You may end up with many child-command-classes. To easier handle the code, you can define high-level methods in the parent.
29+
- **Subclass Sandbox.** You may end up with many child-command-classes. To easier handle the code, you can define high-level methods in the parent.
3030

3131
- **Memento.** With this pattern you can also return to a previous state.
3232

Diff for: _text/component.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# 13. Component
2+
3+
When making a big game you should start thinking in components. A component is similar to your computer mouse, which you can attach to whatever computer you want through a USB port and it works fine. So a component is an object that's independent of other objects, making it reusable, and you can attach the component to several other objects if you want those objects to get the behavior described by the component. But in reality, some components have to communicate with each other, so they can't be entirely independent of each other: The mouse is communicating with the computer, but it's not communicating with the printer.
4+
5+
**How to implement?**
6+
7+
In Unity you can attach components to GameObjects, such as colliders, mesh renderers, your own scripts, so it's already built-in. It's up to you to make the custom scripts you attach as reusable as possible.
8+
9+
**When is it useful?**
10+
11+
- Because Unity's FPS counter is not to be trusted, you can have a custom FPS counter that you re-use throughout all projects. Just add the script to the project and attach it to some GameObject and it works fine independently of everything else going on in the game.
12+
13+
- When making a car game you can put physics in one script, such as drag and rolling resistance, becuse physics will always affect the car and the physics calculations are the same for all cars. This component will not be completely independent because it will need some data from the car, such as current speed, but as said before that's fine.
14+
15+
**Related patterns**
16+
17+
- **Type Object.** The difference is that the Component is not always coupled with something else on the game object – it’s living its own life. In Unity you can add colliders, scripts, mesh renderers and they don’t need to know about each other to function. Type Object, however, is about adding a behavior to an existing class, so the type can't live on its own.
18+
19+
20+
## [Back](../)

Diff for: _text/data-locality.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# 16. Data Locality
2+
3+
Have you done all optimizations you can possible do? Is the game still too slow? Then this pattern may help you. It can make your game faster by accelerating memory access.
4+
5+
**How to implement?**
6+
7+
You have to arrange data to take advantage of CPU caching. The basic idea is that you should organize your data structures so that the things you're processing are next to each other in memory. This is a big topic and can't be summarized here, so you should read about it in the book "Game Programming Patterns."
8+
9+
This Unity article suggest that you should use struct instead of class because they are more cache friendly [How to Write Faster Code Than 90% of Programmers](https://jacksondunstan.com/articles/3860).
10+
11+
Unity has implemented this pattern in their [Data-Oriented Technology Stack (DOTS)](https://unity.com/dots).
12+
13+
A good Unity tutorial on the topic is: [Unity Memory Profiler: Where Are You Wasting Your Game's Memory?](https://thegamedev.guru/unity-memory/profiler-part-1/) and [Part 2](https://thegamedev.guru/unity-memory/profiler-part-2/).
14+
15+
**When is it useful?**
16+
17+
- According to the book "Game Programming Patterns," this pattern should be used when everything else has failed. It's a waste of time to optimize code that doesn't need to be optimized - and it may also make the code more complicated to understand. You also have to make sure that cache misses is the reason your code is slow, so you first have to measure it.
18+
19+
20+
## [Back](../)

Diff for: _text/decorator.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# 20. Decorator
2+
3+
You have a class you want to add some behaviors to in a flexible way without modifying the original class.
4+
5+
**How to implement?**
6+
7+
You have a class and now you create several "decorator" classes that modifies some of the behaviors in the class you want to modify. The decorator class should wrap the class it wants to modify. The decorator class can in turn wrap itself to add other behaviors. This might be easier than the alternative to create child classes.
8+
9+
**When is it useful?**
10+
11+
- If you have an order system where people order several products at the same time but pay at a later time. An example of this can be found in the code section where you order Tesla cars with modifications. Yes you could store each order in a list, but a better way is to store them in objects linked to each other. Instead of iterating through each object to find the price, you can just ask the "last" object to get the price of the entire chain.
12+
13+
- If you ever played Pubg you know you have weapons to which you can attach various attachments you find while playing the game. You can find magazines, sights, silenzers, etc, modifying the weapon's properties. You can use the Decorator pattern to implement this in your game.
14+
15+
**Related patterns**
16+
17+
- **Subclass Sandbox.** You may end up with many child-classes. To easier handle the code, you can define high-level methods in the parent.
18+
19+
20+
## [Back](../)

Diff for: _text/dirty-flag.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# 17. Dirty Flag
2+
3+
This pattern is useful if something has changed in your game and if so you have to run a costly operation. A Dirty Flag is used to tell that something has changed but the costly operation hasn't been activated yet. You can often postpone the costly operation until the result is actually needed.
4+
5+
**How to implement?**
6+
7+
The dirty flag is just a bool.
8+
9+
**When is it useful?**
10+
11+
- Saving your game can be a costly operation. If something in your game has changed that also needs to be saved, you set a Dirty Flag in the save game object to true. Now if the player wants to quit the game, you can easily tell the player that there are unsaved changes. An example of this can be found in the code section.
12+
13+
- When doing editor scripting in Unity, you can use SetDirty() to mark an object as dirty or you can even mark the entire scene as dirty. Now Unity will understand that you have changed something and those changes should be saved when you save your scene.
14+
15+
- Unity is using it in the physics system. A RigidBody doesn't have to be updated unless a force is applied to it. If the RigidBody is sleeping (not moving), a Dirty Flag is used so the physics system can ignore it.
16+
17+
- I used this pattern when experimenting with Genetic Algorithms (GA) and the Traveling Salesman Problem (TSP) where you find the shortest path between multiple cities. The GA generates multiple solutions, like 100, to the TSP and then each iteration you evolve 100 better solutions by calculating a cost function, which is the distance between all cities. You can use "tournament selection" to find good solutions from the previous iteration to the next, which is basically picking 3 solutions and returns the solution with the shortest distance between all cities. I realized I didn't have to calculate the cost fuction 100 times each iteration because it's a costly operation. To optimize I only calculate the cost function of the cities being picked by the tournament selection. I kept track of which solution has had its cost fuction calculated by using a bool which is set to false each iteration and then to true if the cost function has been run.
18+
19+
20+
## [Back](../)

Diff for: _text/double-buffer.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 7. Double Buffer
2+
3+
You have two buffers: you update #1 with new data while you are not allowed to modify #2 because #2 is holding old data from previous update, which you might want to display on the screen or use when updating #1. When you have finished updating #1, you swap them, so #2 is now including fresh data and you can start updating #1 which is now including old data.
4+
5+
**How to implement?**
6+
7+
You can have two arrays. You write to one of them, and when the calculations are finished you swap the pointer to the arrays.
8+
9+
**When is it useful?**
10+
11+
- To display stuff on the screen. This is already built-in into you computer which uses two buffers to display stuff on the screen. It reads from #2 while #1 is being updated with new data. When #1 is finished updating, the buffers are switched, so now you will see the newly updated data on the screen. It would look strange if you used just one buffer because then one part of the screen would display old data and one new data in some kind of horrible mix.
12+
13+
- To generate motion blur. The current buffer is blended with a bit of the previous buffer.
14+
15+
- Cellular Automata (CA). In games it's common to store data in a grid (which is a 2d array). To calculate new data you combine data from the cells, such as the maximum value of the current cell and surrounding cells. But where are you storing the data for the cell you just calculated? You can't store it in the cell because that will screw up the calculations for neighboring cells because you always want to use old data when doing the calculations. So you use two grids: #2 holds the old data and #1 is using #2 to update itself. When the calculations are finished, you swap them.
16+
17+
- Cave-generation. This is the example I've included in the code.
18+
19+
- [Water](http://www.jgallant.com/2d-liquid-simulator-with-cellular-automaton-in-unity/). You simulate movement of water on a grid.
20+
21+
- [Forest fire](https://www.youtube.com/watch?v=JtGp9eUugFs). You store in each cell the amount of burning material in that cell, then you simulate heat to ignite the material. When there's no more material to burn, the heat disappears.
22+
23+
24+
## [Back](../)

Diff for: _text/event-queue.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# 14. Event Queue
2+
3+
You have some events but you can wait until later to process each event. This may be useful if you have many events that may be activated at the same time which will freeze the game because this pattern will spread them out over some time period.
4+
5+
**How to implement?**
6+
7+
Combine the Command pattern with C#'s built-in queue, which is why this pattern is sometimes known as a **Command Queue**. In the Update method you pick the first Command in the queue and run it while measuring time. To measure time you can use System.Diagnostics.Stopwatch. If you have time to spare, you run the next Command, and so on until you are out of time. How much time you can spend on the Event Queue each update depends on the game, so you have to experiment.
8+
9+
**When is it useful?**
10+
11+
- When you after an event will load an asset. This may take time, so if you want to play a sound when clicking a button, the game may freeze because it has to load the sound. A better way is to play the sound some frames after the click.
12+
13+
- When you after an event will play a sound effect. What if 100 enemies die at the same time and each time an enemy dies you play a death-sound. Now 100 sounds will play at the same time. If you put the events in a queue, you can check if a sound is already playing and then ignore the event. You can also merge the events that are the same, so you have only one of each event type in the queue.
14+
15+
- If you are making a strategy game, you can put orders in the queue that the player wants a certain unit to do: 1. build wall, 2. collect food, 3. attack creature. Now the player doesn't have to wait for a unit to finish one task. You can also put waypoints in the queue to make a unit patrol between waypoints. The AI can also put commands in a queue to for example determine which units should attack.
16+
17+
- When making a speech system. Each character has its own queue with audio it wants to say. To know which character should speak, you can go through all queues. If the player presses Escape because the player doesn't want to listen to the talk, you simply clear all queues.
18+
19+
**Related patterns**
20+
21+
- **Event Bus.** Similar to Event Queue but there's no delay.
22+
23+
- **Observer.** You use the Observer pattern to implement the Event Queue.
24+
25+
26+
## [Back](../)

Diff for: _text/facade.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 22. Facade
2+
3+
When you have several related classes, such as AI or audio, and want to make it simpler to access methods in those classes. The name Facade comes from [building facades](https://en.wikipedia.org/wiki/Fa%C3%A7ade) - you can only see the exterior of the building, but have no idea how the building looks like inside. You can still access classes in the subsystem if you need to - the Facade is just making it simpler to access the more common classes.
4+
5+
**How to implement?**
6+
7+
Create a manager class that provides a single interface to a large collection of related classes.
8+
9+
**When is it useful?**
10+
11+
- In games it's common to write standardized code libraries, such as a library for the AI, which includes pathfinding, etc. These tend to include massive amounts of classes. To make it easier for yourself you create a script that includes access to the most important methods you need, such as get a short path. I made an open source library: [Computational geometry](https://github.com/Habrador/Computational-geometry). There are multiple methods on how to generate a Delaunay triangulation. To simplify the access to those methods I wrote a class called _Delaunay, which access each Delaunay method in a simple way. Otherwise you would have to first go into the Delaunay folder and figure out which class is doing what and which method you should use to generate the needed Delaunay triangulation. And if I decided to use another triangulation library I only need to change the facade script. Multiple Facades are allowed, so I also have another Facade for the intersection algorithms.
12+
13+
- Random numbers are common in games. Should you use Unity's Random.Range or C#'s System.Random.Next? You can use the Facade pattern to easier switch between them. An example of this can be found in the code section. And if you find a third random number library, you can add it and you don't have to make a single change to the code that uses this Facade.
14+
15+
**Related patterns**
16+
17+
- **Service Locator.** The Service Locator is not necessarily consisting of several classes - the service we want to get might consist of a single class. But the Service Locator can use the Facade Pattern.
18+
19+
- **Singleton.** The facade class is often a Singleton because you need only a single object to manage access to audio or to AI.
20+
21+
- **Adapter.** This pattern is dealing with how to make code you can't modify work with your system. While Facade creates a new interface to simplify, Adapter adapts an old interface. These patterns are so similar that a book included both in the same chapter.
22+
23+
24+
## [Back](../)

Diff for: _text/factory.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# 21. Factory
2+
3+
Collect all methods on how to create new objects in their own class. The factory can also be responsible for the destruction of objects.
4+
5+
**How to implement?**
6+
7+
If you are creating several different factories, then they should inherit from some parent abstract class. And the products you create should also inherit from some parent abstract class, so you can handle them as their parent without caring which child product that actually came out from the factory.
8+
9+
**When is it useful?**
10+
11+
- If you've implemented the **Decorator** then you can decorate the objects in a procedural way by using the Factory pattern. An example of this is in the code where you manufacture the Tesla cars you ordered in the Decorator pattern example.
12+
13+
- To play sounds on different devices. An example of this can be found in the code section.
14+
15+
- For each object you make you have to allocate some memory. By creating all objects in a central area it makes it easier to monitor these allocations.
16+
17+
- To keep track of all of your Singletons.
18+
19+
**Related patterns**
20+
21+
- **Prototype.** The Prototype pattern is generally used if you want to make a copy of an existing object, while the Factory pattern is generating new objects. But some argue you can put the Prototype pattern inside of the Factory pattern.
22+
23+
- **Object Pool.** The factory doesn't have to create new objects - it can be a recycling plant if you combine Factory with Object Pool.
24+
25+
26+
## [Back](../)

Diff for: _text/flyweight.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Separate the data that’s not specific to a single instance of that object and
1616

1717
**Related patterns**
1818

19-
- **[Type Object](#12-type-object).** The main difference is that in Type Object you don't need to have the exact same data and you can also have behavior.
19+
- **Type Object.** The main difference is that in Type Object you don't need to have the exact same data and you can also have behavior.
2020

2121

22-
## [Back](https://github.com/Habrador/Unity-Programming-Patterns)
22+
## [Back](../)

Diff for: _text/game-loop.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 8. Game Loop
2+
3+
The game loop is the core of all games. It's basically an infinite while loop that keeps updating until you stop it. But the problem with such a while loop is that it updates faster on faster computers than it is on slower computers. This will be very problematic if you have some object that travels with some speed, then it will travel faster on the faster computer. To solve this problem you need to take time into account by using the following:
4+
5+
- Fixed time step. You determine you want the game to run at 30 frames-per-second (FPS). Now you know how long one while loop should take (1/30 = 0.03333 seconds). If the while loop is faster than that, you simply pause it at the end until 0.03333 seconds has passed. If it's slower, you should optimize your game.
6+
7+
- Variable (fluid) time step. You measure how many seconds has passed since the last frame. You then pass this time to the update method, so the game world can take bigger steps if the computer is slow and smaller steps if the computer is fast.
8+
9+
**How to implement?**
10+
11+
This pattern has already been implemented in Unity, which is actually using both versions of the while loop:
12+
13+
- Fixed time step: Time.fixedDeltaTime. This version is used for physics calculations where you should use a constant step to make more accurate calculations.
14+
15+
- Variable time step: [Time.deltaTime](https://docs.unity3d.com/ScriptReference/Time-deltaTime.html), which Unity defines as "The completion time in seconds since the last frame."
16+
17+
The game loop is also checking for input before anything else. This is why in Unity you can type "if (Input.GetKey(KeyCode.A))" because the game loop has already checked (before the update method) if the A key has been pressed and stored that information in some data structure.
18+
19+
**When is it useful?**
20+
21+
- When you have a bullet that should move with a constant speed. So you determine a bulletSpeed and in the update method you multiply the speed with Time.deltaTime so the bullet travels with the same speed no matter how fast the computer is.
22+
23+
24+
## [Back](../)

0 commit comments

Comments
 (0)