{"author_link":"\/users\/davide-rossetto","author_name":"Davide Rossetto","author_uid":"davide-rossetto","comments":[],"epoch":1649360660,"event":"LD50","format":"md","ldjam_node_id":291501,"likes":7,"metadata":{"p_key":"165483","p_author":"Davide Rossetto","p_authorkey":"1032518","p_urlkey":"391191","p_title":"Technical Postmortem - BLACKSUN","p_cat":"LDJam ","p_event":"LD50","p_time":"1649360660","p_likes":"7","p_comments":"0","p_status":"WAYBACK","us_key":"1032518","us_name":"Davide Rossetto","us_username":"davide-rossetto","event_start":"1648857600","event_key":"110","event_name":"Ludum Dare 50"},"node":{"_collation":{"body_sanitizer":"TextUtils::SanitizeHTML via existing importer","event":"LD50","removed_author":false},"_superparent":276397,"_trust":1,"author":32518,"body":"Hey guys and gals, Davide here! :v:\n\nI partecipated to LD50 with [BLACKSUN](https:\/\/ldjam.com\/events\/ludum-dare\/50\/blacksun), a resource management game based on the Aztec myth of the Fifth Sun and the subsequencial destruction of the Earth.\n\n![Cover-pm.png](\/\/\/raw\/60f\/7\/z\/4d61d.png)\n\nThe postmortem will be a little more on the technical side, mainly because I am a developer by myself and my art skills suck :robot:\n\nI will talk about Unity, C# and shaders (just a little). There is also a little chapter on the release, matter I'm not really expert, but during the compo I got some knowledge worth sharing.\n\nAbout any suggestion, critique or challenge to a duel to the death, please write them in the comment section. Happy reading you all! :v:\n\nP.S.: you can find the complete source code at [https:\/\/github.com\/DavideRoss\/BLACKSUN](https:\/\/github.com\/DavideRoss\/BLACKSUN)!\n\n## Singleton Pattern\n\nThe [singleton pattern](https:\/\/en.wikipedia.org\/wiki\/Singleton_pattern) is a very diffuse software pattern that let you instantiate a specific class (`MonoBehaviour` in our case) once, like it is a global variable. This is often seen as anti-pattern (something to avoid because prone to problems later in the project), but I find it very useful in Unity.\n\nIn practical usage let you access a `MonoBehaviour` object almost as static, so you don't have to link the object around the scene. Usually I have a block of important objects I use frequently called **managers**, like in my case the `GameManager`, the `ResourceManager` and the `AltarManager`.\n\nThere are different ways to create a singleton in Unity, each one with its bonus and malus, personally I use this one:\n\n```csharp\nusing UnityEngine;\n\npublic class GameManager : MonoBehaviour\n{\n    static GameManager _instance;\n    public static GameManager Instance\n    {\n        get\n        {\n            if (_instance == null) _instance = FindObjectOfType<GameManager>();\n            return _instance;\n        }\n    }\n\n    \/\/ Public variables\n    public bool IsPlaying;\n}\n```\n\nThe script declare a static property of the `GameManager` object returning the *non-static* `_instance` variable. If `_instance` does not exists yet, then search for it. That means if also you put two GameObject in your scene, both with the `GameManager` component attached, `GameManager.Instance` will refer to only one of these two. Then, if I want to get the `IsPlaying` variable from anywhere in the project, I just have to write `GameManager.Instance.IsPlaying`.\n\nThe theory behind a generic singleton pattern is not really intuitive to get in the beginning, but trying the pattern on Unity really shows how it's used and why. Give it a try!\n\n## Defining the ticks per second\n\nIn the beginning there was nothing, then Unity created `Start` and `Update`. But `Update` has a problem! It runs every frame, not caring if the game is running at 5 or 500 FPS, and I cannot calculate the duration of a job based on `Update`!\n\n(small trivia: a lot of games from 80s\/90s cannot be played without a proper support because modern CPU are much faster. This problem is still present nowadays: a famous Doom 2016 speedrun strategy depends a lot by the FPS. And about the speedrun: do you know that speedrunners prefer running on NTSC SNES instead of a PAL one because has a higher refresh rate?)\n\nYes, I could have used `FixedUpdate`, running on a fixed physics engine timeframe, but it's not really meant for that and I wanted more granular control. So I went for writing a tick clock by myself!\n\nThe system is actually pretty easy, it consists of three components: the interface, the registration and the propagator (not real computer science name, I like to be a little dramatic).\n\nThe interface is barely a couple of lines: its job is define a method that a class must have when it's inherited. The benefits of this method is that I can inherit the interface on multiple objects, and still I can fit them all into a single `List`. This is the code for the interface:\n\n```csharp\npublic interface IOnTickHandler\n{\n    public abstract void OnTick();\n}\n```\n\nPretty simple, huh? The interface just defines the **signature** of the method that must be implemented later in the class. Every class can implement the method as needed, like this:\n\n```csharp\nusing UnityEngine;\n\npublic class JobView : MonoBehaviour, IOnTickHandler\n{\n    private void Start()\n    {\n        GameManager.Instance.Register(this);\n    }\n\n    public void OnTick()\n    {\n        \/\/ Do stuff here\n    }\n}\n```\n\nThis script do three things: *inheriting* the interface, *implementing* the method and *registering* the object. But why the registration is needed? You can find the solution on the `GameManager` code:\n\n```csharp\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class GameManager : MonoBehaviour\n{\n    \/\/ Singleton implementation, see above\n\n    public float TickPerSecond = 20f;\n\n    float _time;\n    long _ticks = 0;\n\n    List<IOnTickHandler> _jobs = new List<IOnTickHandler>();\n\n    private void Update()\n    {\n        if (_playing)\n        {\n            _time += Time.deltaTime;\n            if (_time > 1f \/ TickPerSecond)\n            {\n                _ticks++;\n                _time -= 1f\/ TickPerSecond;\n\n                foreach (IOnTickHandler jv in _jobs.ToArray()) jv.OnTick();\n            }\n        }\n    }\n}\n```\n\nThe object with the interface inherited is added to a `List<IOnTickHandler>`, then in the `Update` function I sum `Time.deltaTime` (the time past from the last time `Update` is called) and check for a new tick. If the new tick has happened, cycle every object that inherit the interface and basically *propagate* the information that there is a new tick.\n\nAnd that's conclude the whole lap. It's a little convoluted and probably overengineered for a game jam, but in this way I can control from the `GameManager` component the speed of the game *during the game itself*, and it could be extremely useful!\n\n## Difficulty ramp\n\nI am not a game designer, and resource management games needs a lot of balancing, because there is the risk that a skilled player can manage to gather enough resources to keep playing the game indefinitely.\n\nTo solve this problem I've implemented an incrementing difficulty ramp. The variable is defined in the `GameManager` script:\n\n```csharp\nusing UnityEngine;\n\npublic class GameManager : MonoBehaviour\n{\n    public float Difficulty = 1f;\n\n    private void Update()\n    {\n        \/\/ ...\n\n        if (_time > 1f \/ TickPerSecond)\n        {\n            \/\/ ...\n\n            Difficulty += .0001f;\n            \n            \/\/ ...\n        }\n    }\n}\n```\n\nFor each tick, increment the `Difficulty` variable a little. Then this variable is used in various places around the game, like in the `AltarManager` script to pick the amount of resources to demand:\n\n```csharp\nusing UnityEngine;\n\npublic class AltarManager : MonoBehaviour\n{\n    public void SpawnHead()\n    {\n        \/\/ ...\n\n        int count = Mathf.RoundToInt(Random.Range(1, 3) * GameManager.Instance.Difficulty * (Random.value < .5f ? 3 : 5));\n\n        \/\/ ...\n    }\n}\n```\n\nIn this way the amount of resources is not only dependent from a random value, but it's also biased by the difficulty of the game. In the end some players managed to survive basically forever, but this method *shoud have* worked for most of the games.\n\n## The names of the gods\n\nThis is a last moment addition, only for giggles: on the tooltip for the god head you can found the god's name and his\/her domain. This elements are generated randomly, you can find the code in the `GodHead` script:\n\n```csharp\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class GodHead : MonoBehaviour\n{\n    public static List<string> Names = new List<string>() {\n        \"Macuilcozcacuauhtli\", \"Macuilcuetzpalin\", \"Macuilmalinalli\", \"Macuiltochtli\", \"Macuilxochitl\", \"Cuahuitlicac\", \"Patecatl\", \"Ixtlilton\", \"Ometochtli\", \"Tezcatzoncatl\", \"Tlilhua\",\n        \"Toltecatl\", \"Tepoztecatl\", \"Texcatzonatl\", \"Colhuatzincatl\", \"Macuiltochtli\", \"Iztacuhca\", \"Tlatlauhca\", \"Cozauhca\", \"Yayauhca\", \"Cipactonal\", \"Huehuecoyotl\", \"Huehueteotl\",\n        \"Mictlanpachecatl\", \"Cihuatecayotl\", \"Tlalocayotl\", \"Huitztlampaehecatl\", \"Quetzalcoatl\", \"Xiuhtecuhtli\", \"Mictlantecuhtli\", \"Acolmiztli\", \"Techlotl\", \"Nextepeua\", \"Iixpuzteque\", \"Tzontemoc\",\n        \"Xolotl\", \"Cuaxolotl\", \"Tloque-Nahuaque\", \"Ometeotl\", \"Ometecuhtli\", \"Tonacatecuhtli\", \"Piltzintecuhtli\", \"Citlalatonac\", \"Tonatiuh\", \"Nanauatzin\", \"Tecciztecatl\", \"Tlahuizcalpantecuhtli\",\n        \"Xolotl\", \"Xocotl\", \"Tezcatlipoca\", \"Quetzalcoatl\", \"Xipe-Totec\", \"Huitzilopochtli\", \"Painal\", \"Tlacahuepan\", \"Tepeyollotl\", \"Itzcaque\",\n        \"Chalchiutotolin\", \"Ixquitecatl\", \"Itztlacoliuhqui\", \"Macuiltotec\", \"Itztli\", \"Amapan\", \"Uappatzin\", \"Itzpapalotltotec\", \"Miquiztlitecuhtli\", \"Tlaloc\", \"Tlaloque\", \"Chalchiuhtlatonal\",\n        \"Atlaua\", \"Opochtli\", \"Teoyaomiqui\", \"Tlaltecayoa\", \"Cipactli\", \"Itztapaltotec\", \"Cinteotl\", \"Ppillimtec\", \"Omacatl\", \"Chicomexochtli\",\n        \"Chiconahuiehecatl\", \"Coyotlinahual\", \"Xoaltecuhtli\", \"Xippilli\", \"Xochipilli\"\n    };\n\n    public static List<string> Domains = new List<string>() {\n        \"stars\", \"medicine\", \"fertility\", \"underworld\", \"ballgame\", \"sacrifice\", \"earth\", \"art\", \"excess\", \"pleasure\", \"gluttony\", \"music\", \"gambling\",\n        \"healing\", \"peyote\", \"maize\", \"astrology\", \"old-age\", \"deception\", \"wisdom\", \"winds\", \"light\", \"fire\"\n    };\n\n    public string Name;\n    public string Domain;\n\n    public void Initialize()\n    {\n        Name = GodHead.Names.PickRandom();\n        Domain = Random.value < .5f ? \"Goddess of \" : \"God of \";\n        Domain += GodHead.Domains.PickRandom();\n    }\n}\n```\n\nIt's not really remarkable, if not for the `PickRandom()` method: this method is not native of the `List<string>` object, instead is added by the developer using what's called an extension method. You can find them on the `EnumerableExtension` script:\n\n```csharp\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\npublic static class EnumerableExtension\n{\n    public static T PickRandom<T>(this IEnumerable<T> source)\n    {\n        return source.PickRandom(1).Single();\n    }\n\n    public static IEnumerable<T> PickRandom<T>(this IEnumerable<T> source, int count)\n    {\n        return source.Shuffle().Take(count);\n    }\n\n    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)\n    {\n        return source.OrderBy(x => Guid.NewGuid());\n    }\n}\n```\n\nThose methods are using [generics](https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/fundamentals\/types\/generics) and [LINQ queries](https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/programming-guide\/concepts\/linq\/introduction-to-linq-queries), but the gist of it is that returns the first element of a shuffled list.\n\nPretty neat, huh? You can achieve the same result using a static method asking the list as parameter, but I'm a sucker for syntactic sugar, hence the expansion :stuck_out_tongue_winking_eye:\n\n\n## Clicking on the elements\n\nI have doing UI stuff. I really despise it. And of course my games are heavily UI based, guess I hate myself a little too. Making the player interact with UI, but still keeping a GameObject is boring: you can create a canvas for each GameObject that needs UI elements, or you can set your UI in world space and move GameObject and UI element together, and both methods seems a little hacky.\n\nI need that the player can click on a GameObject, but usually require casting a ray from the camera to the mouse position, but converted in world space and not in screen space. Then the method that shoots the ray should propagate the event to the correct object and make sure that the object handles it. A lot of work, isn't it?\n\nLuckily, Unity ~~warlords~~ developers provide us a couple of useful interfaces: `IPointerClickHandler`, `IPointerEnterHandler` and `IPointerExitHandler`. An explanation about the interface is provided a little above.\n\nThis those three interfaces I can handle all mouse events without caring to shooting rays, setting up colliders and propagating things. Thank you Unity devs!\n\nI used them mainly in `GodHead` and `JobView` scripts to handle the assignations and the tooltip. The methods provides also an object with a lot of useful informations, like the mouse position and the button clicked. This is the `JobView` script:\n\n```csharp\nusing UnityEngine;\nusing UnityEngine.EventSystems;\n\npublic class JobView : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler\n{\n    public void OnPointerClick(PointerEventData e)\n    {\n        if (e.button == PointerEventData.InputButton.Left)\n        {\n            \/\/ Assign a villager to this job\n        }\n\n        if (e.button == PointerEventData.InputButton.Right)\n        {\n            \/\/ Remove a village from this job\n        }\n    }\n\n    public void OnPointerEnter(PointerEventData eventData)\n    {\n        Tooltip.Instance.ShowJob(Job);\n    }\n\n    public void OnPointerExit(PointerEventData eventData)\n    {\n        Tooltip.Instance.Hide();\n    }\n}\n```\n\nI found this method straightforward and easy to use. The only thing you have to care about is setting up a Collider2D component (otherwise the events won't trigger) and be careful to not overlapping them with other UI elements blocking the raycasting.\n\n## A little take on shading\n\nI didn't used so much shaders for this project: the only one is a shader assigned to the god heads, changing the color of them while the time is running out. The shader itself is pretty basic, plus a couple of lines to make it work with the alpha.\n\nThe shader is pretty hacked up together, time was running out, the shader is called `GodHead_Shader` (here's only the interesting part): \n\n```glsl\nsampler2D _MainTex;\n\nfloat _Timer;\nfloat _Darken;\n\nfixed4 frag (v2f i) : SV_Target\n{\n    fixed4 col = tex2D(_MainTex, i.uv) * i.color;\n    \n    float4 alt = col * _Darken;\n    float blend = step(_Timer, i.uv.y);\n\n    clip(col.a - 0.5f);\n\n    return lerp(col, alt, blend);\n}\n```\n\nIn the fragment shader I use a `step` between the UV on the Y axis and an external property to change the color to a darker one. I can control the external property via script, like in the `GodHead` script:\n\n```csharp\nusing UnityEngine;\n\npublic class GodHead : MonoBehaviour\n{\n    public SpriteRenderer Head;\n    public float TotalTicks;\n\n    float _pastTicks = 0f;\n\n    public void OnTick()\n    {\n        _pastTicks++;\n        Head.material.SetFloat(\"_Timer\", Mathf.Clamp01(1f - (_pastTicks \/ TotalTicks)));\n    }\n}\n```\n\nThe `clip` function on the shader basically skip rendering the pixels when its argument is below zero. Writing the fragment shader this way make a **cutout** shader, where a pixel can be fully opaque or fully transparent, with to actual transparency.\n\n## Building and delivering\n\nThat's the part I was not really so expert. And to be honest I'm still not really *that* expert. I wanted to build the game for Windows and WebGL, so first thing I did is installing the **\"WebGL Build Support\"** module through Unity Hub. It took a dozen of minutes, pretty easy.\n\nSecond step was changing the **Project Settings**, specifically the **Player** section. For the Windows build I just changed a couple of settings, mostly the **Fullscreen mode** and the **Default Screen Width\/Height**.\n\n![ps_2.png](\/\/\/raw\/60f\/7\/z\/4d6bb.png)\n\nThird step: open **Build Settings** and add all required scenes to the **Scenes in Build** box, roughly ordered by the order of loading. I left all the other settings as they are and press **Build**: after a dozen of seconds it was done, zip the folder and upload it to my Drive. Done!\n\nTo build for WebGL the first thing you have to do is to switch platform from **Build Settings**: grab a snack, it will take a while. With WebGL had a little more problems: the first build I did has the resolution too high and for some users went out of screen, not good. So I limited the resolution and make the UI Canvas adapt the size for good measure.\n\n![ps_3.png](\/\/\/raw\/60f\/7\/z\/4d6bc.png)\n\nThen I had a couple of problems with [Itch.io](https:\/\/itch.io\/): with the default settings the browser cannot load the game, complaining about decompression issues. I solved disabling the compression from the **Publishing Settings**: the build is a little more heavier, but still manageable by any modern device.\n\n![ps_4.png](\/\/\/raw\/60f\/7\/z\/4d6bd.png)\n\nDone! Finally I can rest my old and worn body!\n\n## Outro\n\nWhoa! That took a good time to write. If you are still reading, thank you very much! I hope that this postmortem can help you in the future. If you want to go deeper down the rabbit hole of game programming you can check the code from the other Compo participants: understading other people code is an awesome tool to learn!\n\nKeep up the good work people, share as much you can without fear or doubt, we are not here to judge, but to help. Davide out!\n\n![cover_heads.png](\/\/\/raw\/60f\/7\/z\/4d6c3.png)","comments":1,"comments-timestamp":"2022-04-07T19:56:37Z","created":"2022-04-07T15:41:13Z","files":[],"files-timestamp":0,"id":291501,"love":7,"love-timestamp":"2022-04-07T21:23:11Z","meta":[],"modified":"2022-04-07T21:23:11Z","name":"Technical Postmortem - BLACKSUN","node-timestamp":"2022-04-07T19:44:20Z","parent":280244,"parents":[1,5,9,276397,280244],"path":"\/events\/ludum-dare\/50\/blacksun\/technical-postmortem-blacksun","published":"2022-04-07T19:44:20Z","scope":"public","slug":"technical-postmortem-blacksun","subsubtype":"","subtype":"","type":"post","version":904276},"node_metadata":{"n_key":"291501","n_urlkey":"391191","n_parent":"280244","n_path":"\/events\/ludum-dare\/50\/blacksun\/technical-postmortem-blacksun","n_slug":"technical-postmortem-blacksun","n_type":"post","n_subtype":"","n_subsubtype":"","n_author":"32518","n_created":"1649346073","n_modified":"1649366591","n_version":"904276","n_status":"WAYBACK"},"source_url":"https:\/\/ldjam.com\/events\/ludum-dare\/50\/blacksun\/technical-postmortem-blacksun","text":"Hey guys and gals, Davide here! :v:\n\nI partecipated to LD50 with [BLACKSUN](https:\/\/ldjam.com\/events\/ludum-dare\/50\/blacksun), a resource management game based on the Aztec myth of the Fifth Sun and the subsequencial destruction of the Earth.\n\n![Cover-pm.png](\/\/\/raw\/60f\/7\/z\/4d61d.png)\n\nThe postmortem will be a little more on the technical side, mainly because I am a developer by myself and my art skills suck :robot:\n\nI will talk about Unity, C# and shaders (just a little). There is also a little chapter on the release, matter I'm not really expert, but during the compo I got some knowledge worth sharing.\n\nAbout any suggestion, critique or challenge to a duel to the death, please write them in the comment section. Happy reading you all! :v:\n\nP.S.: you can find the complete source code at [https:\/\/github.com\/DavideRoss\/BLACKSUN](https:\/\/github.com\/DavideRoss\/BLACKSUN)!\n\n## Singleton Pattern\n\nThe [singleton pattern](https:\/\/en.wikipedia.org\/wiki\/Singleton_pattern) is a very diffuse software pattern that let you instantiate a specific class (`MonoBehaviour` in our case) once, like it is a global variable. This is often seen as anti-pattern (something to avoid because prone to problems later in the project), but I find it very useful in Unity.\n\nIn practical usage let you access a `MonoBehaviour` object almost as static, so you don't have to link the object around the scene. Usually I have a block of important objects I use frequently called **managers**, like in my case the `GameManager`, the `ResourceManager` and the `AltarManager`.\n\nThere are different ways to create a singleton in Unity, each one with its bonus and malus, personally I use this one:\n\n```csharp\nusing UnityEngine;\n\npublic class GameManager : MonoBehaviour\n{\n    static GameManager _instance;\n    public static GameManager Instance\n    {\n        get\n        {\n            if (_instance == null) _instance = FindObjectOfType<GameManager>();\n            return _instance;\n        }\n    }\n\n    \/\/ Public variables\n    public bool IsPlaying;\n}\n```\n\nThe script declare a static property of the `GameManager` object returning the *non-static* `_instance` variable. If `_instance` does not exists yet, then search for it. That means if also you put two GameObject in your scene, both with the `GameManager` component attached, `GameManager.Instance` will refer to only one of these two. Then, if I want to get the `IsPlaying` variable from anywhere in the project, I just have to write `GameManager.Instance.IsPlaying`.\n\nThe theory behind a generic singleton pattern is not really intuitive to get in the beginning, but trying the pattern on Unity really shows how it's used and why. Give it a try!\n\n## Defining the ticks per second\n\nIn the beginning there was nothing, then Unity created `Start` and `Update`. But `Update` has a problem! It runs every frame, not caring if the game is running at 5 or 500 FPS, and I cannot calculate the duration of a job based on `Update`!\n\n(small trivia: a lot of games from 80s\/90s cannot be played without a proper support because modern CPU are much faster. This problem is still present nowadays: a famous Doom 2016 speedrun strategy depends a lot by the FPS. And about the speedrun: do you know that speedrunners prefer running on NTSC SNES instead of a PAL one because has a higher refresh rate?)\n\nYes, I could have used `FixedUpdate`, running on a fixed physics engine timeframe, but it's not really meant for that and I wanted more granular control. So I went for writing a tick clock by myself!\n\nThe system is actually pretty easy, it consists of three components: the interface, the registration and the propagator (not real computer science name, I like to be a little dramatic).\n\nThe interface is barely a couple of lines: its job is define a method that a class must have when it's inherited. The benefits of this method is that I can inherit the interface on multiple objects, and still I can fit them all into a single `List`. This is the code for the interface:\n\n```csharp\npublic interface IOnTickHandler\n{\n    public abstract void OnTick();\n}\n```\n\nPretty simple, huh? The interface just defines the **signature** of the method that must be implemented later in the class. Every class can implement the method as needed, like this:\n\n```csharp\nusing UnityEngine;\n\npublic class JobView : MonoBehaviour, IOnTickHandler\n{\n    private void Start()\n    {\n        GameManager.Instance.Register(this);\n    }\n\n    public void OnTick()\n    {\n        \/\/ Do stuff here\n    }\n}\n```\n\nThis script do three things: *inheriting* the interface, *implementing* the method and *registering* the object. But why the registration is needed? You can find the solution on the `GameManager` code:\n\n```csharp\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class GameManager : MonoBehaviour\n{\n    \/\/ Singleton implementation, see above\n\n    public float TickPerSecond = 20f;\n\n    float _time;\n    long _ticks = 0;\n\n    List<IOnTickHandler> _jobs = new List<IOnTickHandler>();\n\n    private void Update()\n    {\n        if (_playing)\n        {\n            _time += Time.deltaTime;\n            if (_time > 1f \/ TickPerSecond)\n            {\n                _ticks++;\n                _time -= 1f\/ TickPerSecond;\n\n                foreach (IOnTickHandler jv in _jobs.ToArray()) jv.OnTick();\n            }\n        }\n    }\n}\n```\n\nThe object with the interface inherited is added to a `List<IOnTickHandler>`, then in the `Update` function I sum `Time.deltaTime` (the time past from the last time `Update` is called) and check for a new tick. If the new tick has happened, cycle every object that inherit the interface and basically *propagate* the information that there is a new tick.\n\nAnd that's conclude the whole lap. It's a little convoluted and probably overengineered for a game jam, but in this way I can control from the `GameManager` component the speed of the game *during the game itself*, and it could be extremely useful!\n\n## Difficulty ramp\n\nI am not a game designer, and resource management games needs a lot of balancing, because there is the risk that a skilled player can manage to gather enough resources to keep playing the game indefinitely.\n\nTo solve this problem I've implemented an incrementing difficulty ramp. The variable is defined in the `GameManager` script:\n\n```csharp\nusing UnityEngine;\n\npublic class GameManager : MonoBehaviour\n{\n    public float Difficulty = 1f;\n\n    private void Update()\n    {\n        \/\/ ...\n\n        if (_time > 1f \/ TickPerSecond)\n        {\n            \/\/ ...\n\n            Difficulty += .0001f;\n            \n            \/\/ ...\n        }\n    }\n}\n```\n\nFor each tick, increment the `Difficulty` variable a little. Then this variable is used in various places around the game, like in the `AltarManager` script to pick the amount of resources to demand:\n\n```csharp\nusing UnityEngine;\n\npublic class AltarManager : MonoBehaviour\n{\n    public void SpawnHead()\n    {\n        \/\/ ...\n\n        int count = Mathf.RoundToInt(Random.Range(1, 3) * GameManager.Instance.Difficulty * (Random.value < .5f ? 3 : 5));\n\n        \/\/ ...\n    }\n}\n```\n\nIn this way the amount of resources is not only dependent from a random value, but it's also biased by the difficulty of the game. In the end some players managed to survive basically forever, but this method *shoud have* worked for most of the games.\n\n## The names of the gods\n\nThis is a last moment addition, only for giggles: on the tooltip for the god head you can found the god's name and his\/her domain. This elements are generated randomly, you can find the code in the `GodHead` script:\n\n```csharp\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class GodHead : MonoBehaviour\n{\n    public static List<string> Names = new List<string>() {\n        \"Macuilcozcacuauhtli\", \"Macuilcuetzpalin\", \"Macuilmalinalli\", \"Macuiltochtli\", \"Macuilxochitl\", \"Cuahuitlicac\", \"Patecatl\", \"Ixtlilton\", \"Ometochtli\", \"Tezcatzoncatl\", \"Tlilhua\",\n        \"Toltecatl\", \"Tepoztecatl\", \"Texcatzonatl\", \"Colhuatzincatl\", \"Macuiltochtli\", \"Iztacuhca\", \"Tlatlauhca\", \"Cozauhca\", \"Yayauhca\", \"Cipactonal\", \"Huehuecoyotl\", \"Huehueteotl\",\n        \"Mictlanpachecatl\", \"Cihuatecayotl\", \"Tlalocayotl\", \"Huitztlampaehecatl\", \"Quetzalcoatl\", \"Xiuhtecuhtli\", \"Mictlantecuhtli\", \"Acolmiztli\", \"Techlotl\", \"Nextepeua\", \"Iixpuzteque\", \"Tzontemoc\",\n        \"Xolotl\", \"Cuaxolotl\", \"Tloque-Nahuaque\", \"Ometeotl\", \"Ometecuhtli\", \"Tonacatecuhtli\", \"Piltzintecuhtli\", \"Citlalatonac\", \"Tonatiuh\", \"Nanauatzin\", \"Tecciztecatl\", \"Tlahuizcalpantecuhtli\",\n        \"Xolotl\", \"Xocotl\", \"Tezcatlipoca\", \"Quetzalcoatl\", \"Xipe-Totec\", \"Huitzilopochtli\", \"Painal\", \"Tlacahuepan\", \"Tepeyollotl\", \"Itzcaque\",\n        \"Chalchiutotolin\", \"Ixquitecatl\", \"Itztlacoliuhqui\", \"Macuiltotec\", \"Itztli\", \"Amapan\", \"Uappatzin\", \"Itzpapalotltotec\", \"Miquiztlitecuhtli\", \"Tlaloc\", \"Tlaloque\", \"Chalchiuhtlatonal\",\n        \"Atlaua\", \"Opochtli\", \"Teoyaomiqui\", \"Tlaltecayoa\", \"Cipactli\", \"Itztapaltotec\", \"Cinteotl\", \"Ppillimtec\", \"Omacatl\", \"Chicomexochtli\",\n        \"Chiconahuiehecatl\", \"Coyotlinahual\", \"Xoaltecuhtli\", \"Xippilli\", \"Xochipilli\"\n    };\n\n    public static List<string> Domains = new List<string>() {\n        \"stars\", \"medicine\", \"fertility\", \"underworld\", \"ballgame\", \"sacrifice\", \"earth\", \"art\", \"excess\", \"pleasure\", \"gluttony\", \"music\", \"gambling\",\n        \"healing\", \"peyote\", \"maize\", \"astrology\", \"old-age\", \"deception\", \"wisdom\", \"winds\", \"light\", \"fire\"\n    };\n\n    public string Name;\n    public string Domain;\n\n    public void Initialize()\n    {\n        Name = GodHead.Names.PickRandom();\n        Domain = Random.value < .5f ? \"Goddess of \" : \"God of \";\n        Domain += GodHead.Domains.PickRandom();\n    }\n}\n```\n\nIt's not really remarkable, if not for the `PickRandom()` method: this method is not native of the `List<string>` object, instead is added by the developer using what's called an extension method. You can find them on the `EnumerableExtension` script:\n\n```csharp\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\npublic static class EnumerableExtension\n{\n    public static T PickRandom<T>(this IEnumerable<T> source)\n    {\n        return source.PickRandom(1).Single();\n    }\n\n    public static IEnumerable<T> PickRandom<T>(this IEnumerable<T> source, int count)\n    {\n        return source.Shuffle().Take(count);\n    }\n\n    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)\n    {\n        return source.OrderBy(x => Guid.NewGuid());\n    }\n}\n```\n\nThose methods are using [generics](https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/fundamentals\/types\/generics) and [LINQ queries](https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/programming-guide\/concepts\/linq\/introduction-to-linq-queries), but the gist of it is that returns the first element of a shuffled list.\n\nPretty neat, huh? You can achieve the same result using a static method asking the list as parameter, but I'm a sucker for syntactic sugar, hence the expansion :stuck_out_tongue_winking_eye:\n\n\n## Clicking on the elements\n\nI have doing UI stuff. I really despise it. And of course my games are heavily UI based, guess I hate myself a little too. Making the player interact with UI, but still keeping a GameObject is boring: you can create a canvas for each GameObject that needs UI elements, or you can set your UI in world space and move GameObject and UI element together, and both methods seems a little hacky.\n\nI need that the player can click on a GameObject, but usually require casting a ray from the camera to the mouse position, but converted in world space and not in screen space. Then the method that shoots the ray should propagate the event to the correct object and make sure that the object handles it. A lot of work, isn't it?\n\nLuckily, Unity ~~warlords~~ developers provide us a couple of useful interfaces: `IPointerClickHandler`, `IPointerEnterHandler` and `IPointerExitHandler`. An explanation about the interface is provided a little above.\n\nThis those three interfaces I can handle all mouse events without caring to shooting rays, setting up colliders and propagating things. Thank you Unity devs!\n\nI used them mainly in `GodHead` and `JobView` scripts to handle the assignations and the tooltip. The methods provides also an object with a lot of useful informations, like the mouse position and the button clicked. This is the `JobView` script:\n\n```csharp\nusing UnityEngine;\nusing UnityEngine.EventSystems;\n\npublic class JobView : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler\n{\n    public void OnPointerClick(PointerEventData e)\n    {\n        if (e.button == PointerEventData.InputButton.Left)\n        {\n            \/\/ Assign a villager to this job\n        }\n\n        if (e.button == PointerEventData.InputButton.Right)\n        {\n            \/\/ Remove a village from this job\n        }\n    }\n\n    public void OnPointerEnter(PointerEventData eventData)\n    {\n        Tooltip.Instance.ShowJob(Job);\n    }\n\n    public void OnPointerExit(PointerEventData eventData)\n    {\n        Tooltip.Instance.Hide();\n    }\n}\n```\n\nI found this method straightforward and easy to use. The only thing you have to care about is setting up a Collider2D component (otherwise the events won't trigger) and be careful to not overlapping them with other UI elements blocking the raycasting.\n\n## A little take on shading\n\nI didn't used so much shaders for this project: the only one is a shader assigned to the god heads, changing the color of them while the time is running out. The shader itself is pretty basic, plus a couple of lines to make it work with the alpha.\n\nThe shader is pretty hacked up together, time was running out, the shader is called `GodHead_Shader` (here's only the interesting part): \n\n```glsl\nsampler2D _MainTex;\n\nfloat _Timer;\nfloat _Darken;\n\nfixed4 frag (v2f i) : SV_Target\n{\n    fixed4 col = tex2D(_MainTex, i.uv) * i.color;\n    \n    float4 alt = col * _Darken;\n    float blend = step(_Timer, i.uv.y);\n\n    clip(col.a - 0.5f);\n\n    return lerp(col, alt, blend);\n}\n```\n\nIn the fragment shader I use a `step` between the UV on the Y axis and an external property to change the color to a darker one. I can control the external property via script, like in the `GodHead` script:\n\n```csharp\nusing UnityEngine;\n\npublic class GodHead : MonoBehaviour\n{\n    public SpriteRenderer Head;\n    public float TotalTicks;\n\n    float _pastTicks = 0f;\n\n    public void OnTick()\n    {\n        _pastTicks++;\n        Head.material.SetFloat(\"_Timer\", Mathf.Clamp01(1f - (_pastTicks \/ TotalTicks)));\n    }\n}\n```\n\nThe `clip` function on the shader basically skip rendering the pixels when its argument is below zero. Writing the fragment shader this way make a **cutout** shader, where a pixel can be fully opaque or fully transparent, with to actual transparency.\n\n## Building and delivering\n\nThat's the part I was not really so expert. And to be honest I'm still not really *that* expert. I wanted to build the game for Windows and WebGL, so first thing I did is installing the **\"WebGL Build Support\"** module through Unity Hub. It took a dozen of minutes, pretty easy.\n\nSecond step was changing the **Project Settings**, specifically the **Player** section. For the Windows build I just changed a couple of settings, mostly the **Fullscreen mode** and the **Default Screen Width\/Height**.\n\n![ps_2.png](\/\/\/raw\/60f\/7\/z\/4d6bb.png)\n\nThird step: open **Build Settings** and add all required scenes to the **Scenes in Build** box, roughly ordered by the order of loading. I left all the other settings as they are and press **Build**: after a dozen of seconds it was done, zip the folder and upload it to my Drive. Done!\n\nTo build for WebGL the first thing you have to do is to switch platform from **Build Settings**: grab a snack, it will take a while. With WebGL had a little more problems: the first build I did has the resolution too high and for some users went out of screen, not good. So I limited the resolution and make the UI Canvas adapt the size for good measure.\n\n![ps_3.png](\/\/\/raw\/60f\/7\/z\/4d6bc.png)\n\nThen I had a couple of problems with [Itch.io](https:\/\/itch.io\/): with the default settings the browser cannot load the game, complaining about decompression issues. I solved disabling the compression from the **Publishing Settings**: the build is a little more heavier, but still manageable by any modern device.\n\n![ps_4.png](\/\/\/raw\/60f\/7\/z\/4d6bd.png)\n\nDone! Finally I can rest my old and worn body!\n\n## Outro\n\nWhoa! That took a good time to write. If you are still reading, thank you very much! I hope that this postmortem can help you in the future. If you want to go deeper down the rabbit hole of game programming you can check the code from the other Compo participants: understading other people code is an awesome tool to learn!\n\nKeep up the good work people, share as much you can without fear or doubt, we are not here to judge, but to help. Davide out!\n\n![cover_heads.png](\/\/\/raw\/60f\/7\/z\/4d6c3.png)","title":"Technical Postmortem - BLACKSUN","wayback_source":[]}