site banner

Tinker Tuesday for November 26, 2024

This thread is for anyone working on personal projects to share their progress, and hold themselves somewhat accountable to a group of peers.

Post your project, your progress from last week, and what you hope to accomplish this week.

If you want to be pinged with a reminder asking about your project, let me know, and I'll harass you each week until you cancel the service

2
Jump in the discussion.

No email address required.

Day 27 of NaNoWriMo. Passed the 40k mark on Sunday, we're in the home stretch now, and all going smoothly I'll have 45k in the bank by the time I go to bed tonight. As ever it's a high-variance project: some days getting the words out feels like pulling teeth, other days it's a smooth and flowing process. Monday evening was probably the most fun I've had since the start of the month, I wrote a sequence which (in my view) was equal parts funny and sad.

How have you been doing @Southkraut?

Still thinking about which engine to use. Are you tired of this topic yet? I am.

I had a bit of a thought.

  1. My main objection to Stride and Godot (and by extension Redot) is that they're buggy and poorly documented and support is often unhelpful. They're decent when they work, but too often they don't and it takes too much time and energy to figure out why.
  2. My main objection to Unity is that I'm not confident in its future development. Even with the recent issues concerning the pricing model having been laid to rest, Unity suffers from the company that manages it seemingly seeing it as a vehicle for advertisement, and its main target user base being mobile developers. Not exactly what I'm doing.
  3. All this switching engines has strongly reaffirmed my commitment to a maximally strict separation of my model from the engine, as explained last week.
  4. So there's nothing really stopping me from returning to Unity so long as I strongly separate the model from the engine so that if Unity does become unusable or intolerable in the future, a switch to another engine is as easy as possible.

All of this assumes C# scripting for easy migration, of course. So Unreal is right out.

From that thought onward, I considered my existing Unity codebase. There's a lot in there, ready to use, but it follows the old design doctrine of "everything is physical first, abstract second", which is of course the opposite of what I have discovered myself wanting. So even if I do return to Unity, it will take a lot of work to reshape the old code to conform to my new view, plus hanging into into the framework I build in Godot. I should think carefully about how to approach all this so as to achieve a good result without having to redo it several times over.

All that said, I'm strongly considering going for Unreal after all. It's been a pain so far, but for all the effort required to get anything done in Unreal, I am at least confident that the it will bear fruit at some point because the Engine is doubtless capable and not possibly-actually-broken like the others are in many respects. And unlike Unity, I needn't worry about its future nearly as much. That said, my two big pain points are of course C++, but maybe I just need to live with that language and its abominable two-files-per-class structure, and the fact that I won't be able to migrate over any of my old code.

So to recap: More thinking, still no coding.

And thanks for keeping this up. It prevents me from getting distracted entirely. Not like I'm getting much done either way, but this way I'm at least forcing myself to consider the issue regularly. There's hope yet. Please don't stop pinging me.

All this switching engines has strongly reaffirmed my commitment to a maximally strict separation of my model from the engine, as explained last week.

Do you have some idea on how to achieve this? I always loved the idea, but any time I took a stab at it, I ran face first into a wall. The minimalist approach is to have the entire game world happen off-engine, and than output the results as scene objects of any particular engine. That's simple enough, but then you inevitably run into stuff that the engine already has good to go out of the box (say, collision detection, including stuff like "is the mouse pointer over an object"), that would have to be rewritten in the backend from scratch, or the whole idea of separation would have to be abandoned because in the end, you're still using the engine internals.

I swear all these engines are deliberately designed to make "engine agnostic" projects impossible, so if you come up with some elegant way to do this, I'd love to see it.

And thanks for keeping this up. It prevents me from getting distracted entirely. Not like I'm getting much done either way, but this way I'm at least forcing myself to consider the issue regularly. There's hope yet. Please don't stop pinging me.

It's just a single line of text from my side. I'm just happy it's actually helpful!

Do you have some idea on how to achieve this? I always loved the idea, but any time I took a stab at it, I ran face first into a wall. The minimalist approach is to have the entire game world happen off-engine, and than output the results as scene objects of any particular engine. That's simple enough, but then you inevitably run into stuff that the engine already has good to go out of the box (say, collision detection, including stuff like "is the mouse pointer over an object"), that would have to be rewritten in the backend from scratch, or the whole idea of separation would have to be abandoned because in the end, you're still using the engine internals.

I swear all these engines are deliberately designed to make "engine agnostic" projects impossible, so if you come up with some elegant way to do this, I'd love to see it.

No, I'm afraid my engine-agnostic is probably your strongly-coupled. There's just a few points that I try to consistently follow to make things easier for myself in the long run (but more difficult in the short one, and performance suffers, too).

  • Don't use engine-specific data types except for when directly communicating with the engine. (The casting here is a major source of performance loss, but that's a hit one must choose to take.) Example: Use your own Custom.Vector3 class or struct instead of UnityEngine.Vector3, and only cast to UnityEngine.Vector3 when assigning a value to a transform. Maybe even be cheeky and cast implicitly, but that opens up some black pits of anti-optimization.
  • Any call of an engine function should be wrapped by a non-engine-specific method, and those wrappers should be somewhat centralized (in as few files as sensibly possible) so as to limit the points of maintenance in case of engine switching. Example: Don't call UnityEngine.Physics.Raycast(...) everywhere in your code, but instead have your own Custom.Physics.Raycast(...) that in turns calls UnityEngine.Physics.Raycast(...). Now when you switch engines, you only need to adjust your Custom.Physics class to completely migrate your raycasting capabilities instead of making changes in every single class that ever used a raycast.
  • Use as few engine features as possible. This is fairly trivial for me because I hardly even do graphics, but your mileage will vary greatly if you want more out of the engine you use.

IMO, for someone who actually wants to leverage a great breadth of a given engine's potential, it makes no sense to aim for engine-agnostic design. It's a lot of hassle and performance cost for a type of damage control that doesn't even come into play unless something goes horribly wrong - and that really shouldn't happen in the first place for a well-designed, well-scoped project. The only reason why I drone on about it is because my projects are the vague, un-designed, tele-scoping, lifelong obsessions of a hobbyist with too little concentration but too much persistence for his own good.

What genre of videogame are you making?

1st person optionally violent interactor in a very large procedurally generated world with a side dish of "large numbers of people" simulation.

Look, I have no idea what I'm making. There are a bunch of themes I'd like to do and a bunch of mechanics I'd also like to do and a bunch of simulation aspects that I'm usually doing instead of either of the former because somehow I feel at home in technical rabbit holes.

But if I could just stay strictly on course and work towards results instead of in circles, I suppose we'd end up with something like a first-person Kenshi, if that means anything to you.

Boid simulation in Redot

Short entry for today. I dusted my old code and adapted it to Redot's compute shader, and even managed to fix a bug that stumped me the last time I was working on this project. I was hoping I'd have enough time to clean up the code, upload to github, and show off the results, but today was a brutal day, so the github repo, and a more elaborate description of what I managed to get done will have to wait until tomorrow.

Well, as usual getting something animated to work turned out to be a massive pain in the ass, so I'm calling it quits for today and leave you guys with a screenshot.

What's happening here is that all these little dudes are following the mouse cursor (marked with the red dot, because it's not captured by the screenshot). When they run into each other they push each other out of the collision area, and mostly keep trying to walk towards their target, a sort of "zombie horde trying to eat your brains" mechanic. The colors show with how many other entities each one has collided. Blue means no collisions, touching a single other unit turns it red, and then the more collisions happen they gradually turn yellow.

In my first approach to this project I ran into the issue of collision causing the horde to get "fuzzy" (kinda like this). The collision resolution only caused units to run into each other more, which needed more resolutions in the following frame. Particularly the center of the horde was under a lot of "pressure" causing some freaky Brownian motion.

I managed to solved it this time around. First, the original approach was over-complicated - I was calculating some weird "reaction force" to a collision, trying to force a pusback effect. I decided to drop it altogether and only leave the "resolution" part where units are moved away from each-others collision areas.

This still generated a lot of fuzziness, because each unit still tried moving toward the target on each frame, so they kept putting pressure on each other. On a whim I decided to multiply the "follow the target" vector by the dot product between it, and the "collision resolution" vector. So if a unit ran into another, it would get pushed back, but if it got pushed on from behind, it would still be allowed to move forward. It turned out to be very good for stability, and removed most of the fuzziness.

This still left me a bit unsatisfied because it made the horde behave too "sticky". If you moved your cursor the units with a relatively direct path would come at you, while the ones coming at a sharper angle would run into each other and get stuck. It was hard to get a "you're getting swarmed" effect, because they were unable to approach the target from behind, once they started reaching it. I tried a few ideas with varying degrees of success, but what ended up working well was, in turn, adding the cross product of "collision resolution" vector and "follow the target" to "collision resolution", this allowed for a "make some room with your elbows" effect as the sideways movement got an extra push.

This was good for mobility, but again had impact on stability resulting in the return of fuziness. So as a final tweak I divided that "extra push" by the number of collision (with some magic factors attached, but you get the point - more collision less of a sideways boost). This finally resulted in a nice compromise between stability and mobility. You can see how the edges of the swarm tend to be blue, which means they can keep moving towards the target along the edges of the group.

If anyone wants to try it out, here's the github repo