Jump to content
  • Advertisement

Battletech Developer Journal - 01



I'm Chris Eck, and I'm tools developer at HBS for the Battletech project. I've recently been given permission to write up articles about some of the things I work on which I hope to post on a semi regular basis. Feel free to ask questions about these posts or give me suggestions for future topics. However, please note I am unable to answer any questions about new/unconfirmed features.

What's a tools developer?

I don't work directly on the game, instead I work on the tools that help make the game. My "customers" are the other game developers in the studio, and my goal is to make their lives easier, increase their productivity, or enable them to do new and exciting things. The main areas I'm responsible for are the Maps and Encounter logic and the tools that Designers use to build encounters, contracts, events, and flashpoints. 

I really enjoy the Tools Developer position as a job. It's literally a different problem to solve every day. I also like interacting directly with the people who use what I code, which is something most game developers don't get the chance to do.

For example, here are a few of the things I worked on last week:

Vertical Dropship Animation Style

In Urban Warfare environments, there are quite a few buildings scattered around (I hope that didn't spoil the surprise for anyone...) Our normal Leopard Dropship flyby animation comes in at a bit of an angle. In Urban maps, the wings would occasionally clip through a nearby building so I needed to give designers the ability to configure that behavior.

I added the configuration bit to the Lance so when units are spawning via dropship, designers can choose the animation style. One of our animators worked up some new animations, and our tech artist wired them up into an AnimatorOverrideController.


The AnimatorOverrideController is a Unity component that does just what it says. The original AnimatorController contains all the logic  for transitioning between various animation states based on animation variables set by the code. The  OverrideController basically maps any calls to the original animation over to the new vertical set.


Notice how we didn't override leopard_moveCoreGroundIdle? That's because nothing special needs to happen here. When the dropship has landed on the ground, it's just sitting there so there's no need to change the animation. Sittin' still is just sittin' still. :) When a particular override is unset, the original animation is used.


Design Mask System for Urban Environments

Urban maps are quite a bit different than the normal maps we've shipped in the past. For one, the ground isn't a Unity Terrain object. Instead, it's a bunch of GroundPlate "Obstructions" (an Obstruction is anything that can block movement, line of sight, or have units stand on - so big rocks, buildings, foundations, etc.). For normal terrain maps, Designers would paint down DesignMasks directly on the terrain. So they might paint a swath of trees down next to a little patch of rough terrain, and paint a road through them both. However, no No visible terrain meant designers couldn't paint down any design masks. 


We came up with the idea to create these MaterialSlots on the GroundPlates. Pictured here is a blank GroundPlate with four MaterialSlots. When the designer selects the Trees designer mask, it paints that section of the GroundPlate with a nice looking grass texture. As part of the map export process, a DesignMask camera takes a snapshot of all the different Materials (one for each DesignMask (Trees, Water, Roads, etc) and saves png's out for the game to read in later.

In the combat game, we use those PNG's to determine which design masks units are standing in, and will impart different game effects based on that. This was already working since we did a similar export process for Terrain based maps. 

One more thing I had to do though was add a special design mask for ground plates. Normally when a building is sitting inside a forest and a mech jumps on top of it, you wouldn't want the design mask of what's painted on the ground. The mech isn't "in trees" it's on a building. But in the case of GroundPlates - I DO want to use the underlying design mask of the "terrain". So in the GroundPlate BuildingDef I set it to UseTerrain. So whenever a unit is standing on a ground plate, it checks the terrain to get the correct design mask.


Combat Dialogue Sequences

One problem we were having was when multiple dialogues could fire get fired off at the same time, the order was non-deterministic. It just depended on who registered to listen for that message first. Sometimes it was okay, but sometimes was a bit jarring depending on how the dialogue was written. So we made Combat Dialogue Sequences

Instead of individual dialogues firing off onesy-twosy style in whatever order they happen to be registered, the DialogueSequence says we'll fire DialogueA then DialogueB then DialogueC. It also has some smarts in it to skip over dialogue that has been turned off by the contract. Say DialogueB is in a ControlledByContractChunk that's turned off. The sequence will play DialogueA and then DialogueC.


This ensured a specific order that Designers and Contract writers could count on and also cleaned up some weird CameraFocus issues that were occurring.

I decided to also support playing DialogueSequences just in case. So we could have something like DialogueA - DialogueSequenceB (Dialogue B1, B2) - DialogueC. I didn't make the editor component as pretty as I could, but there's . There's a slot for a Dialogue and a slot for a Sequence for each DialogueItem. You're only supposed to set 1 and there's a validation error if you try to set both. Maybe one day I'll go back and pretty it up, but probably not.


Dynamic Structure Points for Buildings

One of the designers was worried about buildings having a static amount of structure points. Give the building too many and it takes forever to beat it down with lighter mechs in the early game. Give them too few and heavier mechs can take down a building too easily when you're trying to defend it in the later game. So we came up with the idea to adjust the amount of structure points based on the difficulty of the contract.

In CombatGameConstants, I defined a structure to hold a row of building hit points per difficulty. The designer then tags specific buildings in the level with scaled_small, scaled_medium, or scaled_large. And when the combat game loads up, the starting structure points of these buildings are overriden appropriately.



That's all for now

So there was a glimpse of a few issues that I tackled last week. If you found this interesting or have any questions, let me know in the comments below. Or via the twitter post below.

Until next time,
- Eck




Recommended Comments

Thank you for posting this Eck - and I look forward to seeing more of these (as your time allows)!  Would love to see a future one that talks about some of the tools you made and are in the bundle (like the Flashpoint maker).

I'm sure it is safe to say that the Modding Community appreciates the work you do, and how you (and many other HBS staff)work to make our lives easier :D

Thanks again!

Share this comment

Link to comment
On 4/7/2019 at 8:01 PM, JustinKase said:

Thank you for posting this Eck - and I look forward to seeing more of these (as your time allows)!  Would love to see a future one that talks about some of the tools you made and are in the bundle (like the Flashpoint maker).

The Flashpoint editor is a beast and would probably need a couple of articles all on it's on. Plus I'd need to learn how to use it! I wrote the tool, but it's just a WinForms app that can load/edit/save the data structures that are there. I don't fully understand what the SimGame calls or how the data is used. However, there's an excellent writeup that Amechwarrior did here: https://forum.paradoxplaza.com/forum/index.php?threads/flashpoint-authors-guide.1153590/

I'll try to do a write-up on the Contract Parser in the next couple of journals and maybe the Event Parser sometime after that. 

On 4/7/2019 at 8:01 PM, JustinKase said:

I'm sure it is safe to say that the Modding Community appreciates the work you do, and how you (and many other HBS staff)work to make our lives easier :D

Thanks again!

Aw thanks man. I'm thrilled to be able to help the modding community. I'll pass your thanks along to the rest of the team.

- Eck

Share this comment

Link to comment
8 minutes ago, Kareem "Daigoji Gai" Harper said:

This was great and, without spoiling, awesome reassurance we're marching towards a summer of urban warfare



Can barely wait as well !


Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By Ruben Torres
      [The original post with its formatting can be found at the Unity UI Profiling entry]
      You spend an infinite amount of time optimizing your Unity UI. But, all it takes to really screw up performance is a sneaky modification on a tiny attribute of an almost invisible Canvas UI element. And when that happens, not even Unity UI Profiling will save you from dropping frames. Are you ready for the road ahead?
      This is what happened in my last project...
      I worked hard to optimize the several UI panels of our port to Oculus Quest. This was mostly about reducing the overdraw level to an acceptable amount to make sure the GPU would be all comfy with the real 3D rendering.
      So I worked on Unity UI Optimization for at least a month and made pretty damn good progress.
      At some point, it was so well optimized that the GPU timings were barely moved by the UI. The opaque UI shading techniques I applied compensated most of the overdraw caused by UI Layering (elements drawn on top of other elements).

      There I was, with a super optimized hybrid UI system that effectively occluded the 3D elements drawn behind it.  It became very easy to discard the rendering of these occluded fragments.
      However, I was far away from being done...
      When I hooked the Unity UI Profiler, one thing caught my attention.
      I saw an overwhelmed CPU taking over 1 ms per frame on UI rendering. That's a hell lot of time for a platform that gives you a budget of 13 ms for the whole game execution: physics, logic, 3D rendering, input, VR, networking are all in the same bucket.
      And I've seen cases where UI kills CPU performance even more.

      Unity UI: Expensive Build Batches
      And that is the thing: UI can be optimized to be GPU-friendly, but that doesn't directly translate into being CPU-performing.
      In fact, CPU and GPU have very different tasks to accomplish in Unity UI Rendering. No wonder, I suggest you approach CPU and GPU optimization very differently, as seen in my previous blog post about Unity UI Optimization.
      Doing more of Unity UI Profiling showed me the obvious problem: the UI was constantly being re-created every single frame, i.e. there was a Canvas Rebuild happening every frame.
      A constant hit of 1 ms on the CPU... ouch.
      But why would Unity do this to me?
      I thought Unity cached the UI Canvases...
      Actually yes, that is correct. Unity effectively caches the canvases to make sure they are built just once.
      The problem arises, though, when you change the properties of any of the UI elements of the canvas, such as a color, a position and so on.
      That means, all animations we love, such as button hover effects, are killing your performance and you might not know it.
      When UI property changes happen, Unity does the famous Canvas Rebuild that will crush your game's performance.
      A Unity UI Canvas Rebuild makes Unity iterate over all UI elements of that Canvas to generate an optimized list of draw calls (a set of vertices, colors, materials, etc.). And Canvas Rebuilds take longer than a Seat Panda doing a 0-60 mph test.
      That said, once you've acknowledged you suffered from constant UI Canvas Rebuilds, the natural question to make is...
      Why am I suffering the Canvas Rebuilds and what can I do about them?
      ​Answering that innocent question led me to spending 5+ hours researching this topic and empowering the Unity UI Profiler.
      Let's see how.
      Quick Navigation (they all redirect to the original blog page)
      1. Unity UI Profiling: All Good, until...
      2. Unity UI Profiling: A wild Canvas Rebuild appears!
      3. Finding the Saboteur: a politically incorrect brute-force approach
      4. Bonus: Augmenting the Unity Profiler for UI Optimization

      1. Unity UI Profiling: All Good, until...
      Let's say we have a weirdo of a UI in front of us.
      That UI is barely doing anything but sitting there, being annoying to the player who just want to see something through it.
      As a collection of 350+ images using a Grid Layout Group, it (miserably) looks like this:

      Unity UI Profiling Example
      And that's fine, even if it contains 350+ images. They will normally be rendered in just two draw calls, as there are two unique images that are not atlased in a sprite atlas.
      Effectively, I can see in the profiler there's almost no overhead on the CPU side. Most of the time we're under 0.01ms, which is pretty damn good.

      Unity UI Profiling: Sneaky Spike
      (...Most of the time)
      ​Wait, what was that CPU spike at the end of the graph?

      2. Unity UI Profiling: A wild Canvas Rebuild appears!
      What has just happened there at the end of the Unity Profile? The Unity UI CPU cost has more than doubled in just a second, how weird.
      I want to play a game
      Find the two differences in the samples below (you may want to click on them for zooming in).

      Unity UI Profiling: Cheap Canvas

      Unity UI Profiling: Canvas Rebuild
      I'll give you five seconds to find it out.
      5, 4... Ok here's a hint to make it easier:

      Unity UI Profiling: Canvas Rebuild Overhead
      PostLateUpdate.UpdateRectTransform and UGUI.Rendering.UpdateBatches really wanted to take all the highlight in today's show.
      What do these regions do?
      The first, UpdateRectTransform, implies that a transform of a specific object has changed, and therefore Unity has to run some expensive logic to keep visuals coherent. We don't know whether it was a position, a rotation, a scale or any other of the RectTransform properties.
      Heck, we don't even know if it was just one attribute or all of them. Was it one object, or multiple? In any case, which ones? This is the problem: we do not know.
      The second cost, UpdateBatches, relates to the fact that the whole Canvas geometry has to be rebuilt. This process is famously known as a Canvas Rebuild. A canvas rebuild implies that Unity goes through all the Canvas hierarchy to generate a list of draw calls, so to speak. The vertices, indices, colors, uv's of all elements are computed and then a batching pass is done to we merge as many draw calls as possible to reduce the CPU overhead of issuing them to the graphics driver.
      Now we know what's going on, kind of. We're on the right track. But how do we go about avoiding these canvas rebuilds? What is causing them?
      We just need to find out more specific information...

      An attribute change in a UI element will mark the element itself as dirty A UI element can be totally dirty, but can also be partially dirty: vertices-dirty, layout-dirty, material-dirty. Partial dirty states are cheaper to recover from Unity will rebuild canvases entirely, as soon as any of its elements are marked as dirty Canvas rebuilds are expensive on the CPU, avoiding them is the key  

      3. Finding the Saboteur: a politically incorrect brute-force approach
      We are still to give an answer to the following question:
      Who's triggering that sucky Unity UI Canvas Rebuild?
      It turns out, there's no fast way of finding that out, especially if your canvas hierarchy is immense.
      But, to start out, I'll show you the brute force approach for finding the source of UI Canvas Rebuilds.

      1. Keep the Unity UI Profiler recording
      Filter the metrics so you can focus on what is important: Rendering, Scripts, and UI.
      Keep an eye on the baseline to have a visual cue of your current baseline cost, which should include the expensive Canvas Rebuilds.

      2. Deactivate UI Game Objects and compare
      Select a group of game objects and deactivate it.
      Compare the performance baseline.
      If the baseline didn't improve much, continue deactivating game objects till you see a significant improvement.

      3. Find out who is modifying its properties
      Now you managed to isolate which object is triggering your Canvas Rebuilds. But, who's actually causing those?
      Is it a script scaling it? Or maybe an animation changing its position?
      It helps to do a right-click on the RectTransform and press "Find References in Scene"
      Once you know who's causing the UI canvas rebuilds, do something about it, such as disabling animations or transforms.
      Ruben, how am I supposed to follow this approach in a huge UI hierarchy? Don't give me crap
      I told you it was going to be neither fast nor fun, but your players asked for it.
      That's the thing. Having a huge hierarchy in place is not ideal in the first place. Exactly those massive, deep hierarchies will make your Canvas Rebuilds incredibly expensive on the CPU.
      But big and nested UI hierarchies can (and will) happen, so expect canvas rebuilds to hit you where it hurts the most: your players' game-play experience.
      While the brute force approach helps finding the source of canvas rebuilds, this does not scale in the long-run.
      Becoming more professional about optimizing UI is what got me into creating a tool that would give me all the answers I needed to match my players' expectations...

      Canvas Rebuild Profiling
      4. Bonus: Augmenting the Unity Profiler for UI Optimization
      By now, hopefully, I stressed enough how frequent and impactful UI Canvas Rebuilds can be.
      These troll canvas rebuilds that infested my game stole 10% of my entire CPU budget!
      As we saw, there is a slow brute-force approach for finding the source of a canvas rebuild. Then, I hope you'll be able to do something about it, based on the strategies I posted on my Unity UI Optimization post (visit it, it's free, I promise!).
      But such as error-prone approach is a process a real guru would never settle for. You can literally spend days trying to avoid canvas rebuilds, but the moment you expect it the least, they'll come back just to disappear as soon as you attach the Unity UI Profiler.
      This becomes crucial if you're doing VR development. You don't want canvas rebuilds in your world-space UI. Like not at all. If you don't get rid of these, you're very much likely to convert your players into patients.
      I get it, I will get rid of the canvas rebuilds. But the Unity Profiler won't tell me much about those! What advice can you give me?
      I'm glad you asked. It turns out we can convince the Unity Profiler to give us useful information about who's messing with the performance of our UI.
      You and I can augment the functionality of the Unity UI Profiler. We do so by altering the Unity UI source code that is publicly available. Once you have the source code, you'll want to find the code functions where the Canvas Rebuilds take place. Then, all we need is some BeginSample and EndSample Profiler API magic.
      If you're running Unity 2019.1 or earlier, the Unity UI source code is available for free in their Bitbucket repository. You can follow their guide there to download, install and modify it.
      My suggestion? Use a newer Unity version, at least 2019.2.0. New versions of Unity include the UI source code by default, as the UI system is now part of the package manager. That's the hassle-free way of doing this.
      Here's a list of code regions I found during my investigations where you could add the Profiling API calls:
      CanvasUpdateRegistry.cs: function PerformUpdate Graphic.cs: function SetAllDirty Graphic.cs: other functions such as SetVerticesDirty, SetMaterialDirty, etc..
      Unity UI: Profiling Source Code
      Useful? Yes. 
      Artist/Designer-friendly? No.
      That's why I wrote a small open-source Unity Extension to enhance the Unity Profiler for you.

      The free tool will allow you to quickly switch over profiling modes to make sure the performance of your game is on top.
      The best part of the Unity Profiler enhancer? It just works outside of the editor, effectively replacing all the aspirins you've been taking while profiling your UI in Android and other platforms. 
      Here it is, all its power under your control with two simple buttons: 
      Buff my Unity Profiler Nerf my Unity Profiler. Grab it now here:

    • By rogerdv
      Some weeks ago I was asking how to fill a fixed byte[] array with values (floats, ints, etc). Now I need the opposite: I have to parse that array, received from the client, into values. Seems that BitConverter cant accept fixed byte[] as parameter, how can I convert it to something usable bit BitConverter?
    • By UnificationIndeed
      Its almost 4 AM in here, i am foreigner who lives in south Korea, married and i have also a stable job. i live in Seoul, and i am looking for a serious group that willing to design and develop a game as a hobby. I am kinda dead serious about it. I made a game but its far form being finished, because lack of ideas and code lines.
      I am looking for group of friends who live in south Korea and are willing to sit down, have a coffee, discuss ideas, and start bringing these ideas to life. (Online, Offline, card or mobile) game. I am good with Unity3d, and a good painter and illustrator, furthermore experienced with WACOM tabs. 
      Many games started from a garage by a small groups of developers, and now they reached the sky with their dreams and ideas. Please contact me or comment here, if your passion fall in this direction.
      Here is couple of screenshots of the project i am working on. called "chronicles of SORFIA" 

    • By Cringey Boy
      Looking for a 2D artist to make with me a top-down game with cool features, guns, spells, and powerups. I'm a programmer, and I already made the code for the guns, different spells, powerups and basic mechanics like shooting and moving and stuff like that. I just don't have any assets to use so I'm looking for 1-2 2D artists, can be a pixel artist or anything that you want. Compensation will be 50% for you and 50% for me if we are only 2 and will be different if we are gonna be a trio, you are not working for me (or volunteering) we are a team. The only thing that I control and you not is the money, but you can argue with me and I will probably give you the amount that you think that you deserve. It doesn't have a name yet, we will decide about the name together. You can create guns with no coding because of a system that I created so you will also be able to create content for the game, besides ideas and art. I really need an artist so if you are interested please contact me in discord: #1615Cringey Boy
      I will leave a video to see the game and also the build to try and actually play the game that I have right now. I don't have any art so it looks bad (;
      https://drive.google.com/drive/folders/1Na3JKPBYXuUpxtP-lBUO-hIl0xO1ujSj?usp=sharing < this is the build, just download the folder called "Dungeon" and in there press on Dungeon.exe to open the game.
      1. Switch to the main gun
      2. Switch to the secondary gun
      Mouse Left Click. Shoot (you also aim with the mouse)
      R. Reload the gun that you are holding.
      E. Use main spell (currently, fireball which explodes and deals damage. And you also aim that with the mouse)
      Q. Use secondary spell (currently, heal aura which heals you pretty fast. You don't need to aim)
      (In the video there is no restart but in the build, there will be a restart button when you die)

      Desktop 2019.10.21 - Desktop 2019.10.21 - )
    • By RoKabium Games
      On Aura you can find the Track Ray fossilized bones usually split up in 6 parts. This extinct reptile was incredibly colourful and was one of the largest land animals ever to have inhabited this cold planet. It is speculated that the thick feathers and scales were good insulators for the cold and the colour was most likely a display to attract mates.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!