The Tech Behind Swarm – Riot Games Tech Blog

Data-Driven Waves

We’re now able to spawn a large number of minions that can target and follow Champions all over the map. The next challenge was how to give designers flexibility to author all the different waves while maintaining performance.

The League of Legends Engine has a C++ layer and a scripting layer. C++ is used to implement core gameplay and features that require a high degree of efficiency (e.g., pathfinding), while script is used for more high-level gameplay that requires fast iteration and flexibility (e.g., a specific spell).

Given the high turnover rate of minions in Swarm and all the calculations and processing involved in spawning and despawning each one, we wanted wave spawning to be as efficient as possible. To that end, we created data-driven waves that are handled in C++ and authored through data in editor, rather than script.

In data, designers control when waves spawn or despawn, which characters are in each wave, how many minions are spawned, at what frequency, where, and in what shape… the list goes on! Most of these variables can be scaled by number of players and difficulty level.

Buff Batching

At this point, we have waves of primordians that are spawned according to wave data. Champions can attack these simple code-driven minions, but they cannot apply custom effects on them, such as AoE stuns and damage over time.

All of these effects are typically applied through scripts called “buffs.” These buffs are the primary tools designers use to implement gameplay mechanics. Unfortunately, buffs were also the single most performance-draining aspect of the early prototype, presenting a notable scaling challenge. So, what do we do when a repetitive task starts to strain performance? Enter batching!

The concept of buff batching is straightforward: rather than applying a buff to each individual minion, the buff is applied to a group of minions simultaneously. By batching the buff, we significantly reduce the overhead associated with creating, maintaining, and destroying countless buff instances for each affected minion. The relationship between minions and batches is many to many, where each minion can be a member of multiple batches, and each batch contains multiple minions. Each batch is represented by a set of reusable proxies, each carrying the buff associated with the batch.

The primary use case for batch buffs is applying champion abilities and weapon effects onto a group of minions. For instance, consider an ability like Leona’s ult, where a single buff applies a timed AoE stun and damage over time to multiple targets.

Another use case is controlling the minions themselves. As I mentioned earlier, most minions in Swarm cannot carry buffs, except bosses and mini-bosses. But what about those in-between cases, like elite minions, where we need to spawn a large number of them, keep the wave performant, but with a bit of extra flair? In those cases, a batch buff is added to the wave data as an optional behavior, allowing designers more control over these minions while still keeping buffs in check.

I believe this is the first time in League history that we’ve had buffless minions that cannot be directly controlled through script. Modifying the way the game has always been scripted was nerve-wracking, but I have to give it to the Swarm designers who quickly adopted this style of scripting and still produced gameplay that feels authentic to League!

Client Optimization

Even after all the optimizations we talked about, the game still did not feel performant. This was largely a client problem, due to the crazy amount of things on screen all at once. Despite our server capacity metrics being within target, there were still moments when we were worried that we would have to cut back on the fun to make the game playable.
 


Source link

Leave a Reply

Your email address will not be published. Required fields are marked *