An Intro to Cinemachine for Programmers

I’d first heard about Cinemachine in passing when it was released for free for all users of Unity. “Oh, cool,” I thought. “I’ve never done cinematics before in Unity, I should give this a shot.” Unfortunately, after watching a couple of tutorials, I found myself confused about what Cinemachine really was. I ended up getting the impression that it was for film-makers exclusively - entirely out of the realm of my comprehension.

I bet I am not the only one with these misconceptions. I believe that the tutorials and other official material out there presents Cinemachine in… sort of a misleading way, unintentionally. At the very least, the target audience for their tutorials is not programmers.

I think it’s a shame that Cinemachine is not more immediately understandable, because it turns out to be an incredibly powerful drop-in tool once you do understand it. in this post, I’ll give a brief overview of how I’ve found it useful, as a programmer, to think about Cinemachine.

Read more...

Preventing Third-person Camera Clipping

Animated gif of third-person camera animation

Third-person camera implementations are always tricky to get right. It’s not hard to get a camera to follow a character around at a fixed distance and angle, but then you have to deal with those gosh-darn walls that are everywhere.

There’s a few solutions to this problem, and the one we chose for our project is to push the camera forward whenever a wall is detected. The algorithm is simple and goes like this:

  1. Raycast from the player to the desired camera location (player position + separation distance).
  2. If the raycast hits a wall, put the camera at the raycast hit point.
  3. If the raycast does not hit a wall, put the camera at the original desired location.

This works… almost. A problem manifests when the player is very close to a wall, and is caused by using a raycast in step 1.

Read more...

Propagating Unity UI Cancel Events

Recently I ran into a problem with Unity’s UI system. The problem is simple: How do I close a menu using a controller?

To give an example, a main menu hierarchy will look something like this:

  • Canvas
    • Main menu
      • New game button, options menu button, etc
    • Options menu
      • Resolution dropdown, VSync options, etc
    • … other menus, like level select

If the player opens the options menu from the main menu, then hits the “B” button on their controller, they should be taken back to the main menu. Easily achieved by polling for Input.GetButtonDown in some component on the menu, right? Well, this works for most situations, but it falls over when some component needs to handle the cancel itself. For example, if a dropdown is open and cancel is pressed, then only the dropdown should close, not the menu.

The Unity UI InputModule already has a field which takes a cancel axis - can we leverage that? There is some limited support for doing so, but it turns out to be somewhat more complicated than at first glance.

Read more...

Thoughts on Fast Travel in Open-world Games

Morrowind, Ald Ruhn

If you’ve played Morrowind, you probably know exactly where this is - just outside Ald Ruhn in the Ashlands. Go north and you’ll find the small town of Gnisis, containing both a temple and Imperial guard post. To the east is forbidding Red Mountain, forever surrounded by the mystical Ghostfence. Just to the south you’ll find the Bitter Coast with its mushroom trees and dense marshes.

There are many things that make Morrowind special to me, but one of the foremost is the sense that I know the place. I’ve walked Morrowind from north to south. Its roads feel like home. I can still tell you, years later, the best routes to travel from Vivec to Tel Mora.

I can already see some of you rolling your eyes. “Oh yeah, this old argument. Fast travel is bad, yadda yadda, but seriously - who wants to spend fifteen minutes in a video game just walking?” And you’re right! I love Morrowind, but even I am not immune to the tedium. These days, it’s the big thing that puts me off from playing it again. And yet, something always makes my mind turn back to Morrowind, and think - why did that make me feel the way it did?

Note that this post contains spoilers for Morrowind, Dark Souls, and Subnautica.

Read more...

A Technique for Animating a Unity UI Layout Group

Imagine the following scenario: you have a list of objectives you want to show in the game HUD. Sounds simple enough to implement in Unity’s built-in UI system, right? Just throw a HorizontalLayoutGroup on a panel, insert your elements, and the panel will automatically size to fit. Instantiate new children as new objectives come in.

However, when you add new objectives, it doesn’t look especially nice to have the UI expand immediately. Plus, you want to draw the player’s attention to the objectives list when it is updated. So, you decide to animate the objectives list.

Using Unity’s built-in UI components, this turns out to be a bit difficult to do. There is no built-in support for animation in the UI system. How, then, do we go about animating this list?

Read more...

A Technique for Mixing RTS Audio in Unity

A bunch of Audio clips in a Unity asset library.

There are remarkably few resources around the internet for creating an audio mix in Unity. Of the ones that exist, they seem to always fall into one of two categories:

  1. Get started playing sounds in Unity with an Audio Source!
  2. Here’s how to integrate Wwise into Unity!

I needed something in the middle. Playing sounds using sources and listeners wasn’t going to cut it, and I didn’t have time to learn Wwise, as we were submitting our game to an expo in a month and we had zero sounds.

Since our game was an RTS, there were a few of specific challenges I needed to solve:

  1. Many sounds are less important than others (a gun firing, vs “You are under attack!”). Unity does support priorities on audio sources, but a higher priority only makes sure that the sound gets played; we needed the sound to play louder relative to other sounds.
  2. There are a ton of sounds going off, all at once. This especially presents an issue when a bunch of units all begin firing at once; this causes a very unpleasantly loud sound as the amplitudes add up.
  3. The sounds are all over the map, so we need 3D audio. Since the camera is overhead, we can’t use the 3D position to attenuate, we need to use the 2D position relative to the units.

In desperation, I turned to Unity’s AudioMixer. Though most sources I’ve read around the internet say it’s not good, I managed to make it work.

A note of caution, first, that I am not an audio engineer. I’m not even particularly good at audio stuff. This is just what I found works for our project - there are no doubt better ways to do it. With that in mind, below is a high-level outline of my solution.

Read more...

Building a More Efficient NetworkTransform

I’ve been using Unity’s free networking solution, UNET, in an RTS. On the whole, it works, but it doesn’t work especially well. Since UNET has to support many different types of games, the choices made by the developers lean towards versatility and flexibility, rather than efficiency.

Case in point: the NetworkTransform. It supports many things out-of-the-box, including interpolation, rigidbodies, and variable send rate, but it makes tradeoffs in the efficiency department. Every time it syncs a transform, it’s sending position and rotation uncompressed. With 3 floats for position and 3 floats for rotation, that’s 24 bytes every time a sync happens. The entire Unity networking library is open source, so you can analyze the NetworkTransform yourself.

There’s two reasons for wanting to reduce the bandwidth of the NetworkTransform:

  1. The Unity Matchmaking Service enforces a per-second bandwidth limit of 4kb in pre-production mode. 4096/24 is about 171. Assuming 10 updates a second, thats means only 17 NetworkTransforms syncing at once - with no other traffic at all.
  2. Reducing the amount of bandwidth allows us to push the send rate higher than 10x a second, reducing the amount of interpolation needed along with the perceived latency.

A couple of notes before we get started. First, a lot of this article is based on Glenn Fielder’s (Gaffer’s) snapshot compression article, which is applicable no matter if you’re using Unity or not. I’m going to be explaining a few concepts from the article, for completeness, but you should familiarize yourself with it before reading on.

Second, you should be familiar with bitwise operations. Since we’re trying to save as much bandwidth as possible, we’ll be hand-packing bits.

Read more...

Delaunay Triangulation for Terrain Generation in Unity, Part 2

Island in Wasteland Dogs

This post is a companion post to my previous post on using delaunay triangulation in terrain generation. In that post, I covered some of the implementation details involved in taking a Triangle.Net mesh and transforming it into a Unity3D mesh.

In this post, I’ll talk about a couple more things I did with the terrain:

  • How to space out the triangulated points better
  • How to find the height at an arbitrary point in worldspace

Read more...

Cool Things I've Been Doing With Unity Shaders

In-development screenshot of the RTS project in Unity.

I’ve been on an art kick working on my most recent side project, an RTS made in Unity. In this post, I want to share some neat things I’ve been doing with shaders.

Note that this is an area I’m still exploring and learning in. These are just the results of some of my first experiments. If you have ideas on how to improve them, please leave me a comment at the end of the post.

Read more...

A Curious Case of Deadlock

Some knowledge of Swift and thread synchronization is required ahead.

Normally, on this blog, I write about games and game development. However, most of my time is spent on working on something else entirely; by day, I’m an iOS app developer at a big company you’ve probably heard of.

Recently, our team ran into a really interesting deadlock. I was working on writing a threadsafe cache implementation - a cache only one thread can read from, or write to, at a time. Seems like by-the-book multithreading. Except… well, it wasn’t, of course.

Read more...