Just some update when it feels right
-
Against the Storm

I have always loved playing resource management games. However, most of these games suffer from a shared weakness: a lack of clear goals. In the sub-category of colony sims, this is an eternal question.
It always feels like the first couple of hours are fun as you discover new systems and mechanics. But soon, you enter a loop of having nothing to do, expanding, managing resources, and then returning to having nothing to do. Many games try to fix this cycle by adding timed hazards (for example, winter making food unavailable, or enemy invasions) to force the player to work on expanding or hoarding resources. However, this only replaces “nothing to do” with “prepare for the hazard.” Even with those systems, players eventually run out of tasks, and many hazards end up being handled automatically.
In this regard, Against the Storm found a unique solution. If the problem is a lack of gameplay in the endgame phase, why not just loop the beginning of the game?
Against the Storm is a game where you build settlements in a wicked land to reach ancient Seals and keep a world-ending disaster at bay. Each settlement has specific requirements you must meet to move on, and you must end your expedition before the storm destroys everything. When you finish a Seal, the storm is pushed back, slowing its arrival. The more Seals you finish, the more time you have in the cycle, allowing you to travel further.
The goal is clear: reach the Seal. As the nearby Seals are completed, players naturally push for further ones. Since the cycle of the storm is long, restarting the cycle becomes costly, which increases the stakes and play time.
To ensure the gameplay feels different every time, there are multiple races with specialties that are offered as randomized choices, along with randomized starting buildings. People usually develop their own “to-do list” at the beginning of colony games, but the randomized starting conditions ensure there will always be some variation. Furthermore, “victory points” in the game depend mainly on the request (Orders) system. Every request offers a few choices; players can pick the one that is easiest for them, or one that aligns with what they were about to do anyway.
The randomization system in this game ensures the player has a say in what happens. It provides unpredictability and a sense of control at the same time.
With these systems, Against the Storm offers a one-of-a-kind experience. On that note, however, there are a few things that could be improved.
There is one area where the randomization system does not provide much choice: the hazard system. When you explore the forest, you encounter empty spaces that trigger events with negative effects. These events are solvable and usually come with decent rewards that are important for the game. The issue is that sometimes the game gives you something you cannot solve at all. This is a particular problem when a player needs to expand into those spaces for resources early on. You can do everything right, but picking a card without being able to look first can kill the entire game.
If a failed game didn’t take up all the time accumulated in the cycle, or if there were a way to avoid a “hard failure,” this wouldn’t be much of an issue. One could argue this is a skill issue—that you should always be prepared for the coming hazards. This is true, except on higher difficulties where preparation is not always an option. As a result, it feels extremely frustrating when playing on Prestige 20 or attempting the last Seal. Since it is required to play on max difficulty in many settlements just to reach the Seal, hours of perfect play can go down the drain with one second of bad luck.
Regardless of the bad taste left by these failures, the game does succeed in increasing playtime. It took me 20 hours to try for the last Seal, and I failed. Now it will take another 20 hours, or maybe I will take a break until I feel like playing again.
It would be nice if we could collect resources from failed cycles to help improve the next one. The game attempts this by giving you resources to upgrade your settlement’s starting package, but there is a limit on how many upgrades you can have. After that, it is just “dead resources” that don’t do anything.
Ultimately, Against the Storm is a masterclass in genre-blending. By combining the satisfying loop of city-building with the high stakes and replayability of a roguelite, it solves the “endgame boredom” that plagues almost every other colony sim. While the punishment for bad RNG at high difficulty levels can feel disrespectful of the player’s time—and the meta-progression system hits a ceiling too early—the core gameplay loop remains incredibly addictive. It is a rare game that manages to make starting over feel just as interesting as finishing, cementing its place as a standout title in its genre.
-
[Unreal] Packaging issue fix
I have been doing some research on common Unreal related mistake for Unreal beginners. Going to start making posts about the find and solution.
Packaging issue:- Not having game solution
- That is a must for C++ project. People might be able to by pass that somehow but that is never a recommendation. Generate your solution. You can do that from right clicking the .uproject file or just do it from editor

- Engine integrity issue
- Fix: go to Epic Games Launcher and verify your engine

- What does it cause?
- When you look at your UE5 solution and you can’t build UE5, that means your game project lost the proper reference to the engine. It still “works” but when you compile it, it could fail to build proper binary for packaging
- Example for working project:


- What caused this?
- This is an super old issue exist in UE4 or older(usually for C++ projects), can be caused by many reasons. Unreal is just that sensitive.
- Wrong target file
- Under your root for game project, under Binaries\Win64, you will see <GameProjectName>Editor.target. However, when building, you need <GameProjectName>-<Platform>-<Config>.target
- And you can generate that from building your game project with the platform and config you want to use, which UE5 integrity is required
- On that note, I recommend get use to pack for shipping config so you don’t ended up having a development or debug installer that is slow
- Not having game solution
-
[Dev Log] save system V0.1
Got a pretty interesting surprise today when I started working on the project. For some reason my github is corrupted. I did some research and ended up removing and adding my origin back. Not sure why the head became null out of no where…but then after that I finally got to complete the first iteration of the high level game loop and move on to the save system.
When you load the game, you need to have a few information:
- name of the scene
- player data
- health, mana
- current location
- state
- item data
- With their specific information
More is needed for saving:
- save time
- progress (ex. chapter 3 – 1)
- name of the save
The class that holds the information above should use attribute [System.Serializable] since we are using the JsonUtility in Unity. Using ToJson and FromJason can easily turn the class into text format. I choose to have a static member of save data to carry them across the scene. We have all the scene script derived from a base scene script. It will be nice if we can define the load function callback in the base script’s awake, and have the base call it. Unfortunately, Unity’s C# behave a little bit different and won’t do that. Seems like we will have to either have all the scene script do their own loading function in Awake or call it in Awake, or having the base class do it in its own Awake and make sure the child always call base.Awake() as the first line.
Not all the scene needs to load data, so having each scene handles the data is probably what we are going to do…however, it will be nice if we can clean the save data after we are done loading. We could use an in-game MonoBehaviour to track it, but that means we need another actor/component in every scene. Something I want to try is a clean-up-after-yourself approach. When the save data got taken, it should clean it self after it. When all the data got cleaned, we know all the loading has happened and it can wipe itself after that. Right now it works without thinking about the loaded data, meaning it might have trouble when finishing a game and move into next level. The next step will be implementing that system.
-
Unity notes
- Macro: nameof(functionName) returns a string, which is the same for just doing “functionName”, but it is safer.
- It is safer because we can change our function name in future. If we are using a normal string, it will compile and lose the ability to know that it needs to change. On the other hand, nameof() method will fail as the parameter is no longer valid.
- Often used specifiers:
- For member:
- [Header(“catagory”)]
- [Min(value)]
- [Max(value)]
- [Space]
- [SerializeField]
- [Tooltip(“tool tip”)]
- [HideInInspector]
- For class:
- [RequireComponent(typeof(class))]
- [System.Serializable]
- Make sure you have this if you want to have this class editable in Unity editor
- For function:
- [SettingsProvider]
- For member:
- To create a custom project setting, make a class from ScriptableObject with the target variable with [SerializeField]
- In your class, create a const string with the path of the asset for you setting
- Create functions to create/save setting
- Create another class from SettingsProvider, with a SerializedObject as member
- Override the OnGUI function and use EditorGUILayout.PropertyField and call FindProperty on your SerializedObject to make the property on the project setting UI, followed by ApplyModifiedPropertiesWithoutUndo
- EditorGUILayout.PropertyField(CustomSettings.FindProperty(“SettingName”));
- Create a function that returns your SettingsProvider and use [SettingsProvider] on the function
- When you have C++ DLL for unity project, Unity won’t be able to recover from critical errors like how it handles it in C#
- The crash log and dump will be stored at this location: C:\Users\<username>\AppData\Local\Temp\Unity\Editor\Crashes\
- In the situation where there are static data for the scene and you are loading scene asynchronously. The game might have issue as the static data will be polluted.
- The solution for this is create a buffer map, something like loading map to load between the 2 scenes. To make sure the new map will be loaded after the old map unloaded
- OnValidate is called when member got modified in editor, and when entering play/editor mode against default value. The latter might need to be avoid
- you can have a bool to mark if OnValidate is called or not
- use EditorApplication.isPlaying and EditorApplication.isPlayingOrWillChangePlaymode to prevent the logic being called during play mode
- LineRenderer can only do 1 line, but it can do a lot of nodes
- When want to render more than 1 line, you can use multiple game object with LineRenderer component or have the 1 LineRenderer component render a long line like embroidery
- When doing singleton, don’t do it in constructor (That is what you should do in C++, but not Unity)
- Do it in Awake function
- Macro: nameof(functionName) returns a string, which is the same for just doing “functionName”, but it is safer.
-
[Dev Log] pick-a-path map generation

In the past few days, I have been working on sorting out the functional needs for the RTS Rogue-like game. We eventually decided to make a path picking system like FTL or Slay the Spire. It is an important system for balancing strategic planning with the replayable chaos that makes roguelikes fun.
I wanted players to navigate through a branching network of nodes, each representing a mission. The player chooses a path through this map, picking missions that align with their resources, army composition, or long-term strategy. Unlike card battlers, RTS missions are longer and more intense — so every node needed to matter.
To capture this, I aimed for a tiered layout with a clear top-down flow. Each tier has several nodes, and each node can connect to one or multiple nodes in the next tier. This structure balances randomness with control: the player is never fully at the mercy of RNG, but still gets surprises and tactical choices.
The system allow to set rules–for example, the first and the last tier will only have 1 node since they are the beginning and the ending. We also give each node count its own probabilities so we can shape the map based on other settings. Another rule we added is not allowing one node tier to be followed by another one node tier, since it practically removes the point of having a selection map like this. To make the map dynamic and versatile, all the parameters are adjustable, from the number of tiers to min/max number of nodes allowed.
Here’s how the system works:
- Fixed number of tiers: For example, 6 rows of nodes.
- Each tier has 2-4 nodes: Chosen randomly within a max width.
- Connections are constrained: Each node connects only to nodes in the next tier, ideally 1-3 downstream connections.
- Guaranteed reachability: Every node must be reachable from the start, and all path must always lead to the final node.
This is just a working prototype. The next step is to create the scene that will connect to/be connected from this path-picking map.
-
Mysteries Errors
Cool, so there is a way to add date to blog post, but I need to add the component myself? Maybe there is a template or some sort…not like a block pattern that I still need , but actually automatic.- Ah, yes. As I type that, editing the post template just make sense and there is no reason to add date in title anymore.
- Seems like C# in Unity also got the issue of “this is null”…I understand they are functions that can be static, but the language should know that. It will be nice when a function is being called on a variable that has yet to be initialized it will fail right there instead of inside whatever function it is calling. Pretty sure there are times it does handle it properly…
- When making DLLs for your Unity project, including C++ solution into the C# solution won’t be needed. Seems like it used to be the right way but it no longer works. Just have the C++ solution generate the DLLs into the right location where C# solution can get.
- Circular dependency in blueprint is still the devil for Unreal engine. Since it couldn’t detect it, it will just break some random, unrelated things. The best way to fix it is just walk through the changes and find out which one happened to be the one who completed the cycle.
Unity Input Systems
When making input systems, sometimes you ended up with a number of inputs are basically the same, but have to be implemented separately. For example: ctrl + num
I was using the Unity Input Action System, and ended up having a huge number of input actions: ctrl + num, shift + num, alt + num, and even just the number key needs its own input. That is 40 of them with 4 different actions.It is going to be really annoying to go through all 40 of them and assign proper callbacks, not even saying the difference will just be the integer that got passed in…
The right way to handle it with grace is get the property(variable) with name. Lucky Unity Input Action System allows us to do that with C#.
Make your input action assets into code and you can access the input actions as below:
[C#] m_myInput = new MyInput(); for (int i = 0; i < 10; i++) { string index = i.ToString(); string inputActionName = $"InputAction{index}"; //MyInputActions means it is under Action Maps "MyInput" var inputActionProp = typeof(MyInput.MyInputActions).GetProperty(inputActionName); m_MyActions[i] = (InputAction)inputActionProp .GetValue(m_myInput.MyInput); //need to capture new variables for each lambda int capturedIndex = i; m_MyActions[i].performed += ctx => MyCallBack(capturedIndex); }Not satisfied with that code block up there, but it will do for now.
-
[May 2025]short note
- This might be something you learn sooner or later as you are coding…..even if your space complexity is the same, some methods are still better than the other ones and there is a reason why some method is preferred more than others
- For example, array is always going to be better then hash map. As hash map are likely built with a larger size array as a base to make sure they got space for all the potential inputs
- You can write all the code you want to integrate ChatGPT to your project, and it seems like free tier also has some capacity to use. However, it will not work until you put money in.
- I wonder if it used to be ok, then the pricing chanced without all the documents updated
- When making a project with LLM in mind, make sure you think about business model since every query costs
- Suck up! does a pretty good job about it
- It might be better to use LLM for something more lengthy and fancy, or rewrite lines into different flavor/personality
- By putting your definition of relationship between variables into code makes things faster as you skip the conversion of A->B (if applicable), but it also limits the possibility of extending the function. Pick whichever that fits the need.
- Edge AI looks pretty interesting, it should provide a better distribution of LLM model to games without needing to be always online
- It probably will be with embedded system first
- Before being part of the game, it is likely to go through a few generations
- Probably still need a few year done the line for it to be part of PC…but console might be able to have it in the next generation? If this happens, PC game and console game will separate til PC catches up, vise versa
- If it really is used in game, that means we can no longer have the same-same experience for everyone, but it should be fine as long as it is used for not-lore important elements, just like LLM.
- This might be something you learn sooner or later as you are coding…..even if your space complexity is the same, some methods are still better than the other ones and there is a reason why some method is preferred more than others
-
[Garden]Fight the slug
For a while my garden is full of slugs, but it was never a problem until this year since I started growing leafy vegetables.
Little broccolis and radishes struggle to grow while slugs catering on their baby leaves for a while, which they eventually prevail and start to looks like what they should be.
Kiwi is suffering from some bites, but it is a big enough plant that is still keep growing like nothing happens.
On the other hand, Radishes called a tie on some loses but about 50% of them still manage to grow some leaves.
For a long time, my rule was the survivor is the fitter, and let the garden be whatever, but it changed this week.
My little pepper plant just reached 5 inches tall, and it was full of leaves. It was about the right time for it to go outside to see what world and what it has to offer. However, the next day after the transplant, baby started to lose leaves. Since it was growing quite fast, I decide to keep an eye on it instead of doing something right away.
I was planning to use coffee ground to repel the slugs. Since it is a vegetable garden, I can’t use anything that is harmful for human. There are a lot of berries is getting ready, so I want to use something that is friendly to pollinator as well. Coffee ground is a good option.
The situation doesn’t seem to improve. The next day, I went out to get some coffee ground, and going to spread it around my plants to create a ring to block those little devils. Only to find out, the slugs had got my pepper plant over night. Where it used to be a pepper plant, now it is just a stick!
I am starting a project to make sure my planter box borders will be covered by coffee ground, and we will see how that goes.
-
[Feb 2025]Misc Note for Coding
Busy
UEFN Verse:
- No abstract instance allowed. All devices must exist in the map as actor in order to function
- Prop Manipulator only calls on harvest when it is damaged by an axe AND when the prop manipulator think there are still resource in this node
- To make infinite resource node, override the resource and then you can set the resource given to 0 so it never decrease
- If your Prop Manipulator is controlling a blueprint, OnHarvest would not be called if the blueprint is set to not drop resources
- The default cube doesn’t seem to have right UV……not big deal but it make it not idea to use when doing material work while waiting for the model
- The default blueprint asset is a big pink glowing cube. If you are making particle effects with blueprint assets and see that, that means you didn’t setup that particular asset
- Material can do some cool thing to rotate the model, but it doesn’t seem to like the animation controller (or the basic cube has something that messed it up, like bad UV map)
- I really want a way to properly make a function fail instead of doing something like 5/0 or Mod[10,0]
- When you are doing material work in UEFN, there are something special when it come to sizing the object from material
- If you are using the material in blueprints, make sure you check “Evaluate World Position Offset” to be true. Otherwise the sizing function for the material will fail
- Want to reference material in verse? put them in Materials folder and you can reference it as “Materials.MyMaterial{}”
- Want to organize it in folder with in the materials folder? Declare modules in Verse such as below:
- TopLevelFolder<public>:= module:
SubFolder<public>:= module:
- TopLevelFolder<public>:= module:
- Then you can access it as “TopLevelFolder.SubFolder.MyMaterial”
- Want to organize it in folder with in the materials folder? Declare modules in Verse such as below:
- Sound device does not have the feature to play sound on location (not the same as play to an agent), it also doesn’t have the feature to set the sound in the Verse. You need a lot of sound device if you want something to fire different sound in different situation AND you want multiple players to hear
- Technically, you can collect players who are close to target location and play to them in Verse, but it doesn’t really give you directional information if you care about that. Regardless it does work but making more sound device and make them play when right condition is met individually is still an easier/more native solution
- The solution of teleport the sound device to target location and play has issue when the same sound is being triggered multiple times, since it can only be played in one location.
- FindCreativeObjectsWithTag is bugged in npc_behavior?(need to verify that)
- Analytics require an agent when they fire event, which make things a bit strange. Say we want to know if no one have enter/interact with something, the right way is putting analytics device on every other option, which can be a lot depends on the game
Unity:
- I was just amazed by the input manager, but after looking into it a bit more. There are actually things that is pretty easy that it doesn’t cover/require extra setting
- For any key press input, it doesn’t have a way to tell when you release it. Even with the one that does detect release, it calls the same function as it is pressed. If you want to track press/release with one input, you need an extra bool to remember which one is which. Pretty redundant.
- Another way is use 2 input: one calls for press and the other one calls for release. Still redundant but more reliable and safe in turns of edge cases
- It used to be able to set hold time for each input, doesn’t seem like it anymore
-
[Jan 2025]Misc Note for Coding
Changing the title as I will be including notes not just for verse
UEFN Verse:
- No global leader board….! I am surprised that it is still not a thing for verse
- Right now the way is to have a community for people to post their stat so the creators add it manually in regular update
- I don’t understand the reason you need weak_map(session, t)…unless you can access other sessions? Otherwise it is the same as local
- Turns out that is THE way to make global variables
- Epic remove global variables and force everyone to re-make them with weak_map
- map of a map if you want to have a map as global variable….yikes
- For global variables, the main reason thar it has to be weak_map(session, t) is because module scope require weak_map, which is used to create persistent data
- Conditional button doesn’t fire event when people put require items in them. It usually is not an issue if you have “All key items required at once” is true, but when it is false you will want that event fired
- The way to do it right now is using a button to trigger conditional button so you know when the button is pressed
- Barrier device no longer load on far distance 😦
- Even though you can block the gun fire, it doesn’t block axe, keep that in mind if you want to use this device to block damage to something
- Item on ground despawn naturally when there are too many items in the world. In a map that we allow player dropping item and also have resource spawn into the world as item. Some resource will be removed randomly
- It will be great to have a list of items will never despawn in island settings, or just make them higher priority so we despawn other item that we care less about first
- Item spawner only spawn one thing in the item list. When you call the function “cycle to next item”, it will remove the previous spawn
- Using ToolTip in verse actually cause UEFN to crash, not sure when that started
- The actual way to use it is this:
- @editable{ToolTip:=TestToolTip} MyVariable : logic = true
- Prop manipulator device only fire harvest event if the resource is overridden
- Editable doesn’t support map container, really should imo
Unity:
- New input system is pretty good, but you totally need to go through videos to learn it since they are quite a few steps. Patient pays well.
- Sometimes a function is grey out as “it is not used”. That isn’t true. Be confident if you are following your video right.
- EulerAngles are clamped from 0 to 360. Even when it make sense to have it over this range.
- Delta time is not consistent
- No global leader board….! I am surprised that it is still not a thing for verse