Game Development Guides and Resources for Those Who Need It

>one downside to making my own engine: Making my own engine
giga280.png

>I'll tell you a secret, I don't know what the fuck I'm doin

giga277.jpg

>I am, however, looking into deterministic multiplayer as it seems like the least convoluted way of handling networking, especially with many entities that need to be synched.
giga175.png

>Unlike normal gamedev, networking seems to be a whole different beast.
giga225.png

>It feels like I'm starting from scratch, with a bunch of roads before me, each more convoluted than the previous.

giga288.jpg

>Maybe I lack some foundational knowledge about the internet that I need in order to understand all this shit, any advice?
giga79.png
 
one downside to making my own engine: Making my own engine
I'll tell you a secret, I don't know what the fuck I'm doin
I am, however, looking into deterministic multiplayer as it seems like the least convoluted way of handling networking, especially with many entities that need to be synched.
<
Unlike normal gamedev, networking seems to be a whole different beast. It feels like I'm starting from scratch, with a bunch of roads before me, each more convoluted than the previous. Maybe I lack some foundational knowledge about the internet that I need in order to understand all this shit, any advice?
im just gonna suggest it.
godot multiplayer scene replication as easy as clicking a few buttons
 
im just gonna suggest it.
godot multiplayer scene replication as easy as clicking a few buttons
Not what I'm looking for. Too much abstraction, too high level, I have no idea what's being done or talked about. Unity has the same shit and I kinda agree with bnwoclitty on the whole "what's this even doing?" thing. How is it synching these objects? How does it deal with dsync? What does the packet/internet/whatever traffic look like? What about lag, lag compensation, client prediction, rollbacks? I want to know what's going on! It feels like a closed, mystery box of "fuck you". It's not talking about actual networking, just about dragging and dropping this thingamajig or that doodad. I mean he literally goes "for some reason this fixed the issues"
Aside from that, I'm looking for a more robust solution for a specific usecase. The usecase being many synched entities. This is why I find deterministic solution appealing, aside from the fact that it seems a lot more... intuitive? Simple to grasp? Uncomplicated? I just feel like I have a more solid understanding of what's supposed to be going on: Make the game predictable and only synch inputs


1726240482263.png

also This made me geg
 
Not what I'm looking for. Too much abstraction, too high level, I have no idea what's being done or talked about. Unity has the same shit and I kinda agree with bnwoclitty on the whole "what's this even doing?" thing. How is it synching these objects? How does it deal with dsync? What does the packet/internet/whatever traffic look like? What about lag, lag compensation, client prediction, rollbacks? I want to know what's going on! It feels like a closed, mystery box of "fuck you". It's not talking about actual networking, just about dragging and dropping this thingamajig or that doodad. I mean he literally goes "for some reason this fixed the issues"
Aside from that, I'm looking for a more robust solution for a specific usecase. The usecase being many synched entities. This is why I find deterministic solution appealing, aside from the fact that it seems a lot more... intuitive? Simple to grasp? Uncomplicated? I just feel like I have a more solid understanding of what's supposed to be going on: Make the game predictable and only synch inputs


View attachment 40425
also This made me geg
I can understand where you're coming from, but you kind of only have two options
  1. Deal with the spooky magic shit that sometimes works sometimes doesn't (and if it does work it works poorly sometimes).
  2. DIY.
Option 2 is pretty much always a no go for me. Languages like go seem really appealing but when you get to those languages, you have to worry about pointers and fuckign mutexes and threads and goroutines and if you choose c++ it's evne fucking worst and then you have fucking Rust, which is so fucking garbage its just uggghh. IMO, I hate Python, I hate Java, I just want people to be able to run a fucking executable and play a game, but as a game dev, I really just want to pick up an engine and make the game, not have to build the entire fucking rendering system for the game or some bullshit like that or you know, make my own fucking game engine, HELL NAW!

Even do I have been buck broken because go and c are 1000000000000000x faster than gdscrip im not gonna lie 💀
But is all that effort worth it for a lil performance boost? smugjak

All I can say is, whatever you do, good luck, or something like that.
 
one downside to making my own engine: Making my own engine
I'll tell you a secret, I don't know what the fuck I'm doin
I am, however, looking into deterministic multiplayer as it seems like the least convoluted way of handling networking, especially with many entities that need to be synched.
<
Unlike normal gamedev, networking seems to be a whole different beast. It feels like I'm starting from scratch, with a bunch of roads before me, each more convoluted than the previous. Maybe I lack some foundational knowledge about the internet that I need in order to understand all this shit, any advice?
use a library
 
w3schools is a meme, use learncpp or K&R for C
godot just went woke so stick with unity or use raylib
 
Pathfinding


1697906624612.png

Getting an agent to navigate a space may be one the the greatest challenges for any programmer with enough gall to accept it. The amount of bullshit you have to account for is insane, it's no wonder most people use prebuilt solutions. But to honor a specific use case I decided to attempt tackling the challenge on my own.

I decided to go with a flowgraph (or something approximating it) reasoning being the algorithm would be easier to implement and it would scale well with higher number of units (as compared to A* which calculates the path for each unit individually). The downside is that the computing time grows with map size more so than unit count, I figured it was a worth while deal so I proceeded.

The graph is made up of points, each point knows it's own neighbours (cardinal and diagonal). That's all they know, nothing else. I figured working like this would make for an elegant solution, not having to bother with storing the whole grid of their positions or anything, all they would need is an array of their neighbours (technically 2), don't even need to know which direction those neighbours are in!

But then, how do I get a path to a point? Simple: Every point has a reference to another point called "direction". From this, the destination point simply takes all it's neighbours and sets their direction to be itself (the destination). Now all of the points around the destination are "pointing" to the destination. After this, each of these points do the same to their neighbours, and then those points do the same to their neighbours etc. This creates a sort of wave of points, stepping further away from the destination and direction the outer points towards the center. It is an elegant solution in the sense that the algorithm is exceedingly simple, I added some additional logic to make it prefer cardinal connections over diagonal connections just to make corridors not crowd one edge.

Imagine my surprise when calculating a flow graph took MULTIPLE SECONDS. That's intolerable, so I went to see what I can mend in the code. First, I replaced one of the lists with arrays, this just about cut the time in half (as expected from previous experiences, NEVER USE LISTS). After this I decided to try changing up the algorithm slightly. At first , in order to get this wavy behavior, I had implemented a static queue (first-in-first-out list) where I would add each newly "directed" point and take out the point which was done "directing". I figured an alternative would be making a static delegate function that would trigger a function of every point, this function would then check if the step (the index of the wave or whatever you wanna call it) belongs to the wave currently being calculated. This is basically a function that gets run on 300 points for every point, so yeah, you do the exponentially increasing math. YET SOMEHOW STILL It was faster than using a single fucking queue. <- have a load of this shit. This brought me to about 60ms to calculate a flow graph of 300 points. Not great but probably tolerable with multithreading (not that I know how to do that), I then tried doubling the points to 600 and got a computing time of 350ms. This is what we call exponential suffering. Adding more points not only means more points need to be calculated, but that every calculation is more demanding due to the function that is being called on every single point. The function itself isn't demanding for any point not in the current wave, for most points it's just an integer comparison. But evidently, doing 600 integer comparisons 600 times gets a little fucking demanding.

Well at least it seems like it would have a simply solution, minimize the amounts of times this function is being called. I tried to do this by dynamically subscribing the function to the delegate only when it needs to be called, and unsubscribing it when it's no longer needed. BUT THIS MADE IT WORSE! It went to about 380ms! I guess the delegate's list of subscribers is itself some sort of list, so any gains I get by not calling the function unnecessarily get trumped by editing the list.

(none of this is including the garbage time which increases the computing time by about 70~80% [angry])

I was hoping to somehow bandaid a way to "block" certain directions (this would kinda ruin the elegance because I would have to start checking for positions), so I can make certain corners sharp, or even add cover, but I highly doubt I can do that with the current atrocious performance. There's other little peculiarities like figuring out when a path is no longer being used and disposing of it and what not, but one foot after the other, kinder.

At this point I'm shit out of ideas for optimizing this thing. I was hoping to have thousands of points for the paths but I dread even attempting something like that. The performance hit wouldn't be as drastic if the graphs were divided into two, because the exponentiality decreases, so that's a silver lining for whatever use case that would fit.

I do plan to rewrite this into ECS code (entity component system) which should make it a lot faster or some shit, but I would first need to learn ECS, as well as learning multithreading for ECS for deterministic multiplayer and I do not like the sounds of that one bit

(mind you I still haven't tackled the actual navigation agent AT ALL)



If anyone is interested I can share the code, it's basically a single class with some 200 lines of code (elegance or something). Would be great if anyone had a clue as to what gear could be greased for better performance.

now excuse me as I go back to stare at it and ponder
 
Pathfinding



Getting an agent to navigate a space may be one the the greatest challenges for any programmer with enough gall to accept it. The amount of bullshit you have to account for is insane, it's no wonder most people use prebuilt solutions. But to honor a specific use case I decided to attempt tackling the challenge on my own.

I decided to go with a flowgraph (or something approximating it) reasoning being the algorithm would be easier to implement and it would scale well with higher number of units (as compared to A* which calculates the path for each unit individually). The downside is that the computing time grows with map size more so than unit count, I figured it was a worth while deal so I proceeded.

The graph is made up of points, each point knows it's own neighbours (cardinal and diagonal). That's all they know, nothing else. I figured working like this would make for an elegant solution, not having to bother with storing the whole grid of their positions or anything, all they would need is an array of their neighbours (technically 2), don't even need to know which direction those neighbours are in!

But then, how do I get a path to a point? Simple: Every point has a reference to another point called "direction". From this, the destination point simply takes all it's neighbours and sets their direction to be itself (the destination). Now all of the points around the destination are "pointing" to the destination. After this, each of these points do the same to their neighbours, and then those points do the same to their neighbours etc. This creates a sort of wave of points, stepping further away from the destination and direction the outer points towards the center. It is an elegant solution in the sense that the algorithm is exceedingly simple, I added some additional logic to make it prefer cardinal connections over diagonal connections just to make corridors not crowd one edge.

Imagine my surprise when calculating a flow graph took MULTIPLE SECONDS. That's intolerable, so I went to see what I can mend in the code. First, I replaced one of the lists with arrays, this just about cut the time in half (as expected from previous experiences, NEVER USE LISTS). After this I decided to try changing up the algorithm slightly. At first , in order to get this wavy behavior, I had implemented a static queue (first-in-first-out list) where I would add each newly "directed" point and take out the point which was done "directing". I figured an alternative would be making a static delegate function that would trigger a function of every point, this function would then check if the step (the index of the wave or whatever you wanna call it) belongs to the wave currently being calculated. This is basically a function that gets run on 300 points for every point, so yeah, you do the exponentially increasing math. YET SOMEHOW STILL It was faster than using a single fucking queue. <- have a load of this shit. This brought me to about 60ms to calculate a flow graph of 300 points. Not great but probably tolerable with multithreading (not that I know how to do that), I then tried doubling the points to 600 and got a computing time of 350ms. This is what we call exponential suffering. Adding more points not only means more points need to be calculated, but that every calculation is more demanding due to the function that is being called on every single point. The function itself isn't demanding for any point not in the current wave, for most points it's just an integer comparison. But evidently, doing 600 integer comparisons 600 times gets a little fucking demanding.

Well at least it seems like it would have a simply solution, minimize the amounts of times this function is being called. I tried to do this by dynamically subscribing the function to the delegate only when it needs to be called, and unsubscribing it when it's no longer needed. BUT THIS MADE IT WORSE! It went to about 380ms! I guess the delegate's list of subscribers is itself some sort of list, so any gains I get by not calling the function unnecessarily get trumped by editing the list.

(none of this is including the garbage time which increases the computing time by about 70~80% [angry])

I was hoping to somehow bandaid a way to "block" certain directions (this would kinda ruin the elegance because I would have to start checking for positions), so I can make certain corners sharp, or even add cover, but I highly doubt I can do that with the current atrocious performance. There's other little peculiarities like figuring out when a path is no longer being used and disposing of it and what not, but one foot after the other, kinder.

At this point I'm shit out of ideas for optimizing this thing. I was hoping to have thousands of points for the paths but I dread even attempting something like that. The performance hit wouldn't be as drastic if the graphs were divided into two, because the exponentiality decreases, so that's a silver lining for whatever use case that would fit.

I do plan to rewrite this into ECS code (entity component system) which should make it a lot faster or some shit, but I would first need to learn ECS, as well as learning multithreading for ECS for deterministic multiplayer and I do not like the sounds of that one bit

(mind you I still haven't tackled the actual navigation agent AT ALL)



If anyone is interested I can share the code, it's basically a single class with some 200 lines of code (elegance or something). Would be great if anyone had a clue as to what gear could be greased for better performance.

now excuse me as I go back to stare at it and ponder
Alright, you're not going to believe what just happened.
Get this, the actual computing time for the graph was 30ms, the rest? Well the rest went away after I got rid of all the debug.logs. Yeah, the debugging took 10 times longer than the actual algorithm. Isn't that a fucking riot? Man, life is such a grand ol' time.
 
geg gegdot money went to some tumblr whore
View attachment 47517
godotsisters... it's fucking OVER
View attachment 46702
godotxisters?
Okay. Now. I know I have supported Godot a lot in the past, but now, I don't think I can do that anymore.
blenderchvd fvcking won.... it's over...
sad neutralplier.png
 
Back
Top