-
Notifications
You must be signed in to change notification settings - Fork 1
Playing with implementing very large battles in unity
sdocy/dark-kingdoms
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
https://sdocy.github.io/dark-kingdoms/ 2-03-18 A project in which I am exploring large-scale, autonomous battles. The main trade-off I have used to allow massive battles without extreme lag is turn turn off all physics collisions between units. The unit prefabs do include colliders, so that they may be picked up by Physics.2D.OverlapCircleAll() (which I use for finding enemy targets) but they don't actually collide with each other. This means they run over each other and get packed pretty close together, not the most realistic situation, but I think it still looks pretty decent and battle-like. There is also no animation for movement or battle. Once I learn the basics of Unity animation, I will add some simple animation and see how it impacts the scale I am able to achieve. Each unit includes code for controlling its own movement, targeting and attacks. - the prototype can handle 200 v 200 battles before starting to lag - sliders for choosing army units automatically adjust to allow a maximum of 200 units per army - I use Physics2D.OverlapCircleAll() to get enemies within visibility range and then choose the closet one using Vector2.Distance() - a number of movement strategies are implemented, including random, march and moveWithinDistanceOfTarget random movement is not completely random, it includes a stride attribute which tends to keep units going in the same direction, occasionally changing direction, for more natural looking wandering - armies are setup at the beginning in rows of 100 units, melee in front, archers in back.....or will be once I get the kinks out 2-15-18 It's been a few releases of Unity since I first implemented this. Added some major performance improvements and some movement tweaks - simply turning off all Physics2D collisions for the layers of both armies allowed me to scale up to 800 v 800 with no lag, 1200 v 1200 with a little lag - I tried replacing Physics2D.OverlapCircleAll() with Physics2D.OverlapCircleNonAlloc() but I didn't really see any reduction in lag - updated "move to target" algorithm to something that moves directly towards the enemy unit rather going on a diagonal and then straight. See my code gist for details....... mvt_stayWithin() - added small per-unit variance in movement speed, now the armies look much more natural as they charge at each other. I love when a simple idea adds a lot of depth to what you are working on - I need to update the sliders to handle the larger army sizes (I currently just hacked my army spawner to get bigger armies) and that will fix the troop counters on the battle page v.1.2 Feb 22, 2018 Big Features - updated armySpawner with functional, if not pretty (partial rows are not centered, orcs and archers potentially mixed in center row), support for multiple rows of each unit type - added initSliders() in orcTeam.cs which automatically initializes the orc slider to be 75% of max army size and the archer slider to be 25% - pushing army limit to 2000 vs 2000 - increased battlefield size to accommodate bigger armies - added WASD camera movement - implemented dynamic visibility. Start with small visible ranges for units (archer = visibleRange = rangedRange = 2.0, warrior = visibleRange = 2 * meleeRange = 0.6) and increase range by 1.0 anytime they see fewer than 5 enemies, up to a maximum visible range of 5.0. The goal is to reduce the overhead of searching for enemies when the battle is at its largest, and gradually allow units to look farther out for targets when the battle begins to thin out. Added a 'blooded' orc stat to prevent dynamic visibility from increasing visibility range while units are still marching to the battle. `blooded' is set and turns on dynamic visibility once an orc has damaged someone. I had to be fairly aggressive increasing visibility range since looking for targets is triggered by warrior/archer_impl(), which is currently repeated every 1.5 seconds, while moving happens continuously in update(). Get too lazy with visibility increases and the orcs walk completely out of range before the larger visibility range can pick up anyone new. Internal fixes, cleanups and optimizations - got rid of 'used' field in unit in armySpawner, instead added unitType 'none' to indicate empty unit spot in army array, this let me change armyArray from a struct array (all it contained now was unitType) to a unitType array - tracked down my issue with overLapCircleAll() not seeming to pick up changes in visibilityRange. The values set for orc stats in the editor seem to override the values set when the stats are declared, so I simply deleted the initial stat values in script and went with editor values - switched Vector3.Distance() for Vector2.Distance() - tried removing the rigidbody from my unit prefabs, since I don't really use them, but, if anything, it seemed to make lag worse - moved applyDamage() to a new script, interaction.cs, which will hold all inter-unit methods. Replaced SendMessage("applyDamage") with a direct call to applyDamage() (after getting the component) because I read SendMessage() has horrible performance, even though my lag when battle actually starts isn't too bad right now, it's the marching that's lagging. - got rid of GetComponent() calls to get script references to scripts on the same object and instead linked the scripts to a public variable in the editor. - removed init_archer_stats.cs and init_orc_warrior_stats.cs, moving their functionality into archer.cs and orc_warrior.cs - tried replacing transform.translate() inside Update() with RigidBody.MovePosition() inside FixedUpdate(). MovePosition() was only able to handle 400 vs 400 before lagging horribly. TODO: - Play with something I am calling "dynamic visibility". Currently, visibility (the radius used for OverLapCircleAll()) is set to 2.0f for all units. I am thinking that I could reduce this range when there are lots of units on the board (perhaps 1000+) and increase it as units get killed off. My assumption is that this could significantly improve performance by reducing the work overLapCircleAll() must do and also reduce the number of objects my code must examine with Vector3.Distance() to find the closest. This should be especially useful for melee units who get in close to to each other. It will likely have the undesirable effect of causing archers to move closer than I want to their targets, so I will likely only implement it for melee. - play with Vector2.Distance() instead of Vector3.Distance() - play with turning off remaining Physics.2D layers for brown and red team, see if it helps performance any more even though there are no other objects for them to collide with - replace army size hack with actual support for larger army sizes, requires updates to sliders and correctly breaking the armies into rows
About
Playing with implementing very large battles in unity
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published