Trending
Opinion: How will Project 2025 impact game developers?
The Heritage Foundation's manifesto for the possible next administration could do great harm to many, including large portions of the game development community.
Featured Blog | This community-written post highlights the best of what the game industry has to offer. Read more like it on the Game Developer Blogs or learn how to Submit Your Own Blog Post
A tangent-free, short (for me) practical example of applied system design on a fundamental game element: projectiles.
This article was originally posted on the Joy Machine blog; maybe check it out too! <3
This is one of my most concise articles ever, but only because it’s a segment we ended up cutting for a piece I wrote that actually is going through an “editing process”. I know, it’s a crazy thing. It needed to get cut, as it was a lengthy, borderline-tangential segment of the article, but I thought I’d reuse it here. The land where “proofreading” doesn’t exist.
A projectile is a pretty simple object on its own; the delivery mechanism (weapon) is responsible for its creation and all of the data it needs to run its simulation until it ultimately hits something.
Now, granted, for us it isn’t sufficient that a projectile simply hit something and do damage. That could be all it does, but then we’d be eliminating an entire possibility space of reactions that could arise out of a single impact. So, we have an impact event; we wanted to explore what happens in reality when a projectile hits something. If it’s an explosive, that result is obvious: it explodes. If it’s a bullet, however, it could ricochet, penetrate (cause damage but still pass-through) its impact surface, or simply hit and that’s that.
So, based on what that projectile impacts, what angle the impact hits at, and what material was hit ends up becoming a fairly major factor in the overall game experience. And the response has to always be consistent; if it hits asphalt at a certain speed and angle and ricochets, then given the exact same context in the future it has to have the same response (because randomness in a simulation can give players the sense that the game is cheating them).
The projectile itself has no need to know about the world at large; it just acts on a specific subset of information. So we took advantage of Unreal Engine’s existing “physical material” (which every single material in the world has defined), and injected our own data into it for game-side use. So, when a projectile hits a surface, it receives that physical material that we’ve added additional data to (in this context: density, whether it could be penetrated and how much a penetration would alter speed/direction, what the ricochet potential was, sound effects to play, particle effects, etc.
No matter what, the projectile was going to have to trigger effects and audio; all we did was change the medium from which it got those effects from. And once the projectile-side logic was added to handle ricochets/penetration, it got all its information from an outside medium.
Now, that’s one example. And a seemingly simple one; but consider that there are two major complications: different projectile types and a whole myriad of physical material types. By divorcing the projectile from everything outside its core functionality, we can then isolate customization of physical materials game-wide and deliver that data to the projectile without ever having to alter the projectile itself.
Physical materials themselves are so ubiquitous throughout many aspects of the game, so they end up becoming a great source of information for otherwise independent objects to act upon. Foliage and oil are flammable, flames spread to other flammable materials, and stop spreading when reaching materials that don’t. By isolating these properties in one area, we reduce our overall workload by not having to specifically handle every possible permutation. Because as of right now there are 34 types of different physical materials. Each containing about a dozen or so parameters (and that will grow). By keeping the data compartmentalized, we end up saving ourselves time debugging, knowing where to add functionality to components as-needed, and enforce consistent results through common base elements.
Read more about:
Featured BlogsYou May Also Like