Using the Unity3D engine. I'm making a multiplayer game for fun, using Unity's standard networking. If servers hold 25-50 players, what map size is recommended? How big can I make a very detailed map before it is too big for effective gameplay? How do I optimize a large map? Any ideas and advice would be great, I just want to learn and could not find anything about this on google :D
*My map is sliced into different parts.
The size of the map itself, in units, doesn't matter for performance at all. Just keep in mind that Unity (as any other game engine) uses floats for geometry, and when the float values get too high or too low, things can get funny.
What matters is the amount of data that your logic, networking and rendering engine have to churn through. These are different things, even logic/networking data, and limits on those greatly depend on architecture of your game.
Lets' talk about networking. There, two parameters are critical as your limits: bandwidth and latency. Bandwidth is how much data can you transfer, and latency is how fast. Ok, this explanation is confusing. Imagine a truck full of HDDs travelling from one city to another: it has gigantic bandwidth, and you can transfer entire data centers this way. But the latency, time for the signal to travel, is a few hours. On the other hand, two different people from these cities can hop on air balloons, look at each other in the night sky and turn their flashlights on and off. This way, they'll be able to exchange just one bit of information, but with the lowest possible latency: you can't get faster than light.
It also depends on how your networking works. RTS games, for example, often use lock-step multiplayer architecture can operate on thousands of units, but will only exchange a limited amount of data between users: their input commands. A first-person shooter, on the other hand, heavily relies on latency (which lock-stepping can damage): 10 ms when you jump and fire a rocket launcher are much more important than when you say your troops to attack. So, the networking logic is organised differently: every player's computer predicts what will happen, but the central server has authority on what actually happened. Of course, what I'm writing right now are just general examples of architectures that can be used; choosing the right way to do the networking is very difficult, but very interesting and creative task.
Now, logic itself. Actually, most of the gameplay logic used in modern games is relatively simple in terms of cpu requirements, unless it's physics or AI. Using physics in a multiplayer game is tricky enough on it's own, because of synchronisation problems (remember floats?); usually, the actual logic that can influence who wins and who loses is pretty simplified: level geometry is completely static, characters move using easy logic without real physical force, and the physics is usually limited just to collision detection. Of course, you see a lot of physical-based visual stuff: ragdolls of killed enemies falling down, rubble from explosion flying up; but these are typically de-synchronised between different computers and can't actually affect the gameplay itself.
And finally, rendering. Here, a lot of different constraints make place. To tell about them all, I would have to describe the whole rendering pipeline of Unity on different devices, and this is clearly out of scope of this question. Thankfully, there's another way! Instead of reasoning about this limit theoretically, just to a practical prototype. Put in different game assets in the scene, run it on target device and look how it performs. Adjust, repeat! These game assets can be completely ugly or irrelevant; however, they have to have the same technical properties as what you're going to use in the real game: number of polygons, sizes of textures, shaders, etc, etc. Let's say, for example, that you want to create a COD-like multiplayer shooter. To come up with your rendering requirements, just put in N environment models with N polygons each, using NxN textures, put in N characters with some skeleton animations with N bones, and also don't forget some fake logic that would emulate CPU-intenstive stuff so your perfomance measuring will be more realistic. Of course, it won't give you a final picture, but it'll be a good way to start, and it's great to do that before you start producing a lot of art assets.
Overall, game perfomance optimisation is a very broad and interesting theme, and it's impossible to give a precise answer to such a question.
You can improved this reducing the clipping plane of your camera to reduce the visible render distance, and too can use LOD improvement making your sliced part with minor details.
Check this link for more detail about LOD:
http://docs.unity3d.com/Manual/class-LODGroup.html
If you need more improvement you can make a script to load terrain in runtime based on a distance arround your player.
First and foremost: Make the gameplay work, optimize it later. Premature optimization is a waste of programmer's time.
Secondly: think of Skyrim and Minecraft. The world is separated into pieces that are loaded in background when you move around. Using that approach (chunking your world into pieces) you can have virtually infinite world size.
Related
I want to improve the performance of my game. I've done many things and there have been drastic changes in performance. I also want to change the light. but I don't know which light is more performance friendly.
It really depends on what type of lighting you are trying to do.
Baked lighting is stored in textures, so require a bit of ram, but it is fairly cheap to render, and allow for very complex light, as long as it is all static.
A single omni directional non-shadow casting light would not require any extra memory, just a fairly simple light calculation in the shader, so would be very cheap. But once you add more lights, shadows, global illumination etc, the cost goes up drastically, and you would typically need to apply various optimizations to get decent performance.This is just general recommendations that is non unity specific.
In unity you should have various settings for the lights that affect the quality of the lighting and performance. If you do not know where to start I would suggest starting with baked light, and adding realtime lights where needed, and be careful with things like realtime global illumination since that is a really difficult problem to solve.
Rust has millions and millions of grass, rocks, and trees instances across its maps, which get as big as 8km.
Is that grass placed dynamically around the player at runtime? If so, is that done on the GPU somehow or using a shader?
In my game, we use vertex colors and raycasting to place vegetation, and we store transform data which gets initialized with indirect GPU instancing at runtime.
However, I can't imagine this would scale well with something like trees. Are there really thousands of mesh colliders active in the scene at all times?
I thought perhaps they might store all those meshcolliders in the scene, and the gameobject could be tagged, and if you hit it with a tool, it adds a "Tree" component to it.
Am I headed in the right direction with a "spawn everything before hand, instance it at runtime" approach?
I've tested this and it actually worked, spawning 24 million instances (took 20 minutes to raycast), and then initializing the GPU with the instances.
This is cool and all, even though it lead my Unity editor to crash after a little while (memory leak?).
Maybe you store the instances before runtime, and then when you start the decicated server you do all the raycasting and place all the trees, rocks, and other interactive objects.
But I am worried that if I tried to store even 10000 gameobjects (for interaction, stuff like choppable trees, mineable rocks) that performance would tank.
You can actually see this for yourself in the code: https://github.com/Facepunch/Rust.World/blob/master/Assets/Scripts/WorldExample.cs
The game loads the instances in memory or can stream the instances as well, but you wouldn't ever have the prefabs all instanced at the same time in GO's as culling / chunks are needed to keep performance (and not crashing your program).
There's many tricks, lowering your draw calls, billboarding, culling, object pooling, chunking, just to name a few.
A suggestion if you're interested in systems like this is to look into ECS for unity as it offers a lighter way of instancing data: https://docs.unity3d.com/Packages/com.unity.entities#0.17/manual/index.html
That way you can have thousands of instanced objects for a fraction of what Game Objects would offer in size and performance.
I also don't want to get too deep into generating objects as that's not the main question, but to generate a map using raycasts is extremely slow as you now know, you should look into noise generation to create biomes and quickly spawn your instance, also maps really need a set place for objects you're just adding data that a user needs to load in. Another option is to place objects that serve as visual objects arbitrarily around a viewing distance so they only exist in memory, if someone runs past a generic grass pile, they will never care if it's moved the next time the run past it.
I'm making a game in Unity3D and am currently creating an AI for the enemy. The enemy needs to walk around and search for the player without running into walls.
The enemy always moves forward on it's local z-axis until it encounters an obstacle or the ray made by Raycast hits an object. When the Raycast hits an object that is part of the environment it then Raycast in all 7 directions diagonally, side-to-side and front-to-back to check for more obstacles near it as shown in this image.
The path it takes is then determined by whether or not these rays hit another object and go in the direction in which a ray didn't hit anything and that is the most optimal direction.
By most optimal I mean in the order:
fl OR fr
l OR r
bl OR br
b
I need to decide based on this data which direction to turn. If in a case where say fl and fr are both true then I would randomly decide between the two directions.
I want to optimize this process so I don't have to use multiple if-statements. I had thought of using bitmasking techniques since there are 8 directions, if you include forward, and each bit could represent a direction.
Any ideas, constructive criticism, etc is welcome. Thanks for your time.
Do not optimize pre-maturely, it is the root of all evil, as some say. This would be a perfect example.
The reason we code in C# and not in assembly (or even C) is not performance, it's readability. While it may be possible to make your code run a tiny bit faster, the results may not even be measurable. an IF branch here is still pretty tiny, and I would strongly advice against replacing it with anything else - you will loose a lot of readability, while not gaining much, if any at all performance. Bitmasking techniques start to become effective when you deal with thousands of objects (i.e. Entity), but if your if branch fits on a couple of pages, I would not touch it unless I'd find it to be a major drag by measuring it in the profiler. If you are not sure what you are doing its not that hard to make your code run slower. The priority is to make the code readable (definitely in your case as you won't be running it in a tight loop), and easy to modify. In some cases it's better to unroll the code into a more verbose if branch than to pack it into some bizarre loop - remember a loop is also an instruction.
G,day!
I have been reading a lot lately about the new path-finding system in Unity 2018. I was wondering if you had checked it out yet?
If you wanted to create it from scratch, mad props to you - however, I would be following the documentation (on the Unity website) to create an Update script on the enemy GameObject that would find the shortest path to the player GameObject's transform position, making sure to adjust for obstacles.
Have a browse around on YouTube as well - there are heaps of great tutorials.
Otherwise - if you were looking to do it on your own, the way that I would personally do it (which probably won't be the most optimal) will be though at each frame, scanning for potential paths and then finding the shortest one and acting upon it by moving the enemy based on a predetermined speed * time.deltaTime. A great visualization of the system can be found on Devon Crawford's website (link below).
Unity Documentation Link: https://docs.unity3d.com/Manual/Navigation.html
Devon Crawford's Website: http://www.devoncrawford.io/software/pathfinding
So my issues is that, for large groups of units, attempting to pathfind for all of them in the same frame is causing a pretty noticeable slow down. When pathing for 1 or 2 units the slow down is generally not noticeable but for many more than that, depending on the complexity of the path, it can get very slow.
While my A* could probably afford a bit of a tune up, I also know that another way to speed up the pathing is to just divy up the pathfinding over multiple game frames. Whats a good method to accomplish this?
I apologize if this is an obvious or easily searched question, I couldn't really think of how to put it into a searchable string of words.
More info: This is A* on a rectilinear grid, and programmed using C# and the XNA framework. I plan on having potentially up to 50-75 units in need of pathing.
Thanks.
Scalability
There's several ways of optimizing for this situation. For one, you may not have to split up into multiple game frames. To some extent it seems scalability is the issue. 100 units is at least 100 times more expensive than 1 unit.
So, how can we make pathing more optimized for scalability? Well, that does depend on your game design. I'm going to (perhaps wrongly) assume a typical RTS scenario. Several groups of units, with each group being relatively close in proximity. The pathing solution for many units in close proximity will be rather similar. The units could request pathing from some kind of pathing solver. This pathing solver could keep a table of recent pathing requests and their solutions and avoid calculating the same output from the same input multiple times. This is called memoization.
Another addition to this could involve making a hierarchy out of your grid or graph. Solve on the simpler graph first, then switch to a more detailed graph. Multiple units could use the same low-resolution path, taking advantage of memoization, but each calculate their own high-resolution path individually if the high-resolution paths are too numerous to reasonably memoize.
Multi-Frame Calculations
As for trying to split the calculations among frames, there are a few approaches I can think of off hand.
If you want to take the multi-threaded route, you could use a worker-thread-pooling model. Each time a unit requests a path, it is queued for a solution. When a worker-thread is free, it is assigned a task to solve. When the thread solves the task, you could either have a callback to inform the unit or you could have the unit query if the task is complete in some manner, most likely queried each frame.
If there are no dynamic obstacles or they are handled separately, you can have a constant state that the path solver uses. If not, then there will be a non-negligible amount of complexity and perhaps even overheard with having these threads lock mutable game state information. Paths could be rendered invalid from one frame to the next and require re-validation each frame. Multi-threading may end up being a pointless extra-overhead where, due to locking and synchronization, threads rarely run parallel. It's just a possibility.
Alternatively, you could design your path finding algorithms to run in discrete steps. After n number of steps, check the amount of time elapsed since the start of the algorithm. If it exceeds a certain amount of time, the pathing algorithm saves its progress and returns. The calling code could then check if the algorithm completed or not. On the next frame, resume the pathing algorithm from where it was. Repeat until solved.
Even with the single-threaded, voluntary approach to solving paths, if changes in game state affect the validity of a paths from frame to frame, you're going to run into having to re-validate current solutions on a frame to frame basis.
Use Partial Solutions
With either of the above approaches, you could run into the issue of units commanded to go somewhere idling for multiple frames before having a complete pathing solution. This may be acceptable and practically undetectable under typical circumstances. If it isn't, you could attempt to use the incomplete solution as is. If each incomplete solution differs too greatly, units will behave rather indecisively however. In practice, this "indecisiveness" may also not happen often enough to cause concern.
If your units are all pathing to the same destination, this answer may be applicable, otherwise, it'll just be food for thought.
I use a breadth-first distance algorithm to path units. Start at your destination and mark the distance from it as 0. Any adjacent cells are 1, cells adjacent to those are 2, etc. Do not path through obstacles, and path the entire board. Usually O(A) time complexity where A is the boards area.
Then, whenever you want to determine which direction a unit needs to go, you simply find the square with the minimal distance to the destination. O(1) time complexity.
I'll use this pathing algorithm for tower defense games quite often because its time complexity is entirely dependent on the size of the board (usually fairly small in TD games) rather than the number of units (usually fairly large). It allows the player to define their own path (a nice feature), and I only need to run it once a round because of the nature of the game.
I'm working on an overhead shooter and what happens is, over time, as I move in circles around the arena, the enemies will begin to stack on top of each other until they're one giant stack of units. It ends up looking pretty silly.
The AI is pretty simple and basic: Find the player, move towards him, and attack him if he's in range.
What's the best way to push them away from each other so that they don't all end up on the same spot? I think flocking is a bit overkill (and probably too intensive since I'll have 100-200 enemies on the screen at a time).
Ideas?
Thanks!
Here are a few different approaches you could take to solving this problem:
You could define a potential field for each unit that associates a "height" or "badness" to each location on the map. Each unit moves in a way that tries to minimize its potential, perhaps by taking a step in the direction that moves it to the lowest potential that it can in one step. You could define the potential function so that it slopes toward the player, causing all units to try to move to the player, but also be very high around existing units, causing units to avoid bumping into one another. This is a very powerful framework that is exploited all the time in AI; one famous example is its use in the Berkeley Overmind AI for StarCraft, which ended up winning an AI StarCraft competition. If you do adopt this sort of approach, you could probably then tweak the potential function to get the AI to behave in many other interesting ways, and could easily support flocking. I personally think that this is the best approach to take, as it's the most flexible. It also would be a great starting point for more advanced pathfinding models. For a very good and practical introduction to potential fields for AI, check out this website. For a rigorous mathematical introduction to potential fields and their applications, you might want to check out this paper surveying different AI methods using potential fields.
If you define a bounding circle for each enemy, you could just explicitly disallow the units from stacking on top of each other by preventing any two units from being within two radii's distance of one another. Any time two units got too close, you could either stop one of them from moving, or could have them exert forces on one another to spread them apart. When two units bump into each other, you could just pick a random force vector to apply to each unit to try to spread them apart. This is a much hackier and less elegant solution than potential fields, but if you need to get something up and running it's definitely a viable option.
You could choose a set of points around the player that the units try to move toward, then have each unit randomly choose one of those target points to move to. This would cause the units to spread more thinly in a ring (or whatever shape you'd like) around the player, avoiding the huge masses that you've seen so far. Again, this is way less elegant than using potential fields, but it's another quick hack you could experiment with if your goal is to get something working quickly.
Hope this helps!