Explanations and other things
Some of you may have already noticed that I have made fewer posts in social media. Actually, I have stopped following and using social media for the most of it. Development of Planetrism and other games continue as ever, but I’ll try explain why the social media did not server any purpose for the development, and how it started to be an obstruction and nuisance - it just turned the focus away from the development and getting the game finished.
Indie Developer and Social Media - Is It Really Worth It?
When we started the development of Planetrism and other games, we really thought - like the most indie developers - that social media could provide us a way to reach out for potential players. We do not have a big marketing budget like AAA studios, actually, we have no marketing budget. Social media is free, and most gamers use Facebook, Twitter, Twitch and other media.
More than two years ago - and before that even more - it really was the case. Social media was a good venue to reach for potential. But during our development, we found out that many things had changed there, and continues to change, and most of it for worse from my point of view. Social media is riddled with a negative and usually toxic atmosphere, where trolling is a commonplace. And sometimes it seems, that most accounts following you are just bots. Facebook and Twitter are riddled with fake accounts no matter how much they try to prune them.
There are other problems too. During this time Twitter made some drastic changes in its system, and after that, it seems that it is practically impossible to get any kind of attention. When previously you could get lots of likes and retweets, suddenly they diminished to almost nil. It seems, that the algorithms in the Twitter system just do not show your tweets to relevant people. Based on my observations I am not the only one who has noticed this. One reason could be, that the number of real and fake users have risen a lot during all these years. There is just too much noise in social media.
Basically, after careful analysis, it is quite clear, that one should do lots and lots of work in order to really push through all the noise. Actually, it needs so much work that it is a full-time job. That is why those bigger studios have people dedicated to marketing and social media. Unfortunately we do not have one, and in reality, I am a developer, and not very sociable anyway.
So, after weighing all the pros and cons, it seemed, at least to me, that social media really is not worth it, and there is no point wasting too much time with it. Although it is free, my development time is not really free. I have a certain amount of hours each day only, and I cannot purchase them more anywhere. Now I will use Facebook, Twitter and most of the others only rarely. Instead, I will limit my communication to this newsletter and our web page, mostly.
But most of all I will just concentrate on the development of games, where there is every day some problems to solve, like this one.
Unreal LAN Networking problems
Although the Unreal Engine contains features that make multiplayer game development quite easy, you have to remember, that there is a profound difference between the development of the single-player game and multiplayer game. In a single-player game, nearly everything is contained within the application itself, and usually, the only worry is about hardware compatibility. But the multiplayer game has several problems beyond those.
First of all, there are problems with keeping all clients synchronized within the game itself so that player A and player B perceive the game events in a similar fashion. As said, UE has a replication framework for that. This means, that you do not have to make network code from scratch. But even then, there is the problem of relaying the data between clients and server. The network is an area, where nothing can be taken as granted. On the contrary, anyone who has dabbled with network programming will know that usually everything is denied of access.
A PC is not connected directly to a server or other clients. Data packets have to flow through routers, switches, firewalls and anyone of them may have blocked the ports that server and client need to communicate. There may be other software interfering with data packets.
Just recently I noticed this kind of situation while developing multiplayer features for our game ROT-8 Rover. I knew that the network code worked since everything worked in one machine.
If you do not already know, there is an easy way to test UE multiplayer game on one machine only. In the PIE options, you can determine how may player you need, and when you press Play, it will open that number of separate viewports.
But for some reason client on one machine could not find a hosting server on another machine.
It was not a firewall problem since the necessary ports were open, and I eventually turned firewalls off, but the problem persisted. Eventually, I thought that I have VirtualBox installed (for testing servers, operating systems, and security), and it adds certain network configurations. It seemed farfetched - VirtualBox was not even running - but I thought that they may interfere with network configurations. And actually, yes it did.
VirtualBox has this Host-Only networking interface which prevents this networking no matter what. So, the solution was simple. All I had to do, was to disable it through Resource Manager, and immediately client found server on another machine. In the end, this is no big problem, since host-only networking is not needed, if your virtual machines use NAT.
So if you encounter a similar situation where the connection between machines does not work in LAN, it might pay to check if some software is interfering. If you have VirtualBox installed, then disable the host-only network interface
Complexity of algorithms
Why is it important to understand the complexity of algorithms? I am designing games, not math, most people would say. Games are fun, why involve boring math in development.
Yes, this is something that I have noticed quite often on social media. An indie game developer may be quite fluent to write code, and he may think himself as an adept programmer. Then this same person complains that the performance of his game is poor, and tries to blame either the engine, hardware or both. In some cases, it may be true, but usually, the reason is that
- He has not optimized anything because
- He does not understand the complexity of algorithms
Although modern CPUs and GPUs are fast, they still have limits. They can only do a certain amount of operations within one second, and it is very easy to choke that CPU with an algorithm that does too much work. So, unless one wants to have poor performance in his game, it is really important to understand the complexity of algorithms within the scope of the game, including the code, effects, all assets, any procedural systems, etc.
O-notation
There are specific mathematical methods to estimate the complexity of the algorithm, and it is expressed with O-notation. With these methods, you can estimate worst-case scenarios of an algorithm and its average, etc. Even without exact math, you are able to estimate how much work your algorithm actually does, since it follows quite common and easily understandable logic.
But there is one problem, though. High-level languages hide many complex procedures within one program command, and unless you understand the implementation of programming language and algorithms involved, you could create bottlenecks without realizing it. One high-level program instruction may contain lots of instructions that create much more work than just one.
Loops
It is easy to understand that program loops, and especially loops within loops, can do a lot of work, depending on how many times (N) the loop is executed. You should also think carefully whether it is necessary to execute the loop all those times, or is it possible to break the loop execution. For example, if you are looping an array of objects to find out if any of them fulfills some condition, you can break the execution of loop when you find one. There is no need to do any work on that since it does not change the outcome.
In the example above, we know that on the average the loop is executed N/2 times, and in the worst case, it is executed N times. Sometimes it may be even less, but we cannot know this beforehand. This is just statistical analysis.
It is easy to understand this when you are writing these loops yourself. But many basic high-level programming instructions have loops "under the hood", usually in the form of search algorithms. Such a simple data structure as an array involves search algorithms. Basically accessing any variable in the program needs searching through references in memory. Usually this is very fast and optimized, but anyway, if you have enough instructions that manipulate and access variables, you will hit the limits of CPU.
Data structures
Arrays and complex data structures are even more problematic since they usually have an internal structure of references to memory location. It also depends on how these data structures are implemented. Avoiding the use of complex data structures is not an answer, usually, they are necessary, but you have to learn to implement in such a way, that the work is minimized as much as possible.
When the user writes an instruction to access an item in an array, it means that beneath the hood it has to loop through memory references to find the specific item. Bigger the array more work is done. When these data structures get more complicated, especially in databases, any kind of search through the structure can be very costly in terms of CPU work.
Big Picture
When designing a game it is not just individual algorithms or actors, but the whole game itself. You have to think about how many actors there are constantly running loops, and how big loops they execute, and whether they have internal loops and so on. Although each individual algorithm may look fine, when you stack them together, you may see, that there is just too much work involved
Even if one object in the game is doing something very simple, you can hit performance limits when you have several millions of these objects in the game. Usually, the number of objects may vary a lot during the gameplay. You should always think about how everything will perform in the worst cases, not just average or optimal cases.
Example: Resource locations in Planetrism
As an example, I can show how planetary resources are handled in Planetrism. A 25 square kilometer area has potentially a million different resource locations. They have to be handled as some kind of data structure within the game since they can change during the game and be affected by other factors and actors in the game. On the other hand, they have to have existed as objects in the scene for other reasons, but they are invisible and do not affect GPU calculations.
Due to their great number, they should not be implemented as active objects, because a million objects running even simple algorithms would choke the game. But even a million dummy objects in one array is a performance problem. To avoid this, these resources are handled within a hierarchical multi-layered structure, where an individual resource is part of a small region controller, with just 100 resources. These small region controllers are spread out like a map grid and are handled by a larger region controller, again with just 100 items. This goes on until there is the top-tier controller object.
We can compare the worst case search for nearby resource objects. If all these million objects were put in one big array, it would take 1000000 steps to find the closest in the worst case. And during every step, it would be necessary to calculate the distance, too. But when we use this hierarchical data structure, we first search for the closest top-tier controller, and then the closest region controller, etc, until we look for the closest resource in the lowest level region controller.
It is easy to see that in the worst case there are 100 + 100 + 100 steps or 300 steps in total. This is an enormous difference compared to 1000000 steps. This shows that with careful optimization with appropriate data structures you can have lots of objects, without poor performance.
But optimization can create problems if you start to over-optimize - or you may not gain any significant reduction in the work of algorithm. It is quite usual that when you optimize your algorithm and data structure for fast access, it will be harder to upkeep that data structure.
Basically, I just scratched the surface of optimization. There are lots of books about the theory of algorithms and complexity of algorithms. But if you are interested to hear more and discuss this subject, especially on a specific game engine or programming tool, just comment or drop a line. I just wanted to point out that although many indie game developers omit this subject totally, it is really important if you want to make better games. Optimization of algorithms may allow you to use better effects, more object, more complex game mechanics than without optimization.