Campo Santo
A small but scrappy video game studio in San Francisco

Shop

Shop

Press

"Like a supergroup of musicians from all the bands you don’t like. And not even the best musicians from those bands."

Rock Paper Shotgun commenter PopeRatzo, February 3, 2014

From the Blog

  1. Before After

    BULK REPLACER TOOL

    Time for another short code blog!

    While I was working on some very hairy player stuff one evening, Jane asked if there was a way to swap out every instance of one kind of tree with another kind of tree. After a few moments of looking around in the docs and forums, we determined there was not.

    Since I was stymied by rope physics, I decided to take a brief break and write a quick tool for Jane. It took maybe 10 minutes, and did exactly what it needed to. Wins like that are rare enough I am posting it to the blog.

    Here is the full source for the Bulk Replacer Tool.

    I have written several little utility windows at this point, so I had a decent framework for this. All I had to do was write the algorithm that would handle the replacement.

  2. Hello, I’m James Benson. I’m an animator. I’m going to animate the game “Firewatch.” If you think my animations are bad, you can lobby Campo Santo directly to replace me with a better animator by leaving comments below. I won’t delete them.

    As you can see in the above video, if there is a box that isn’t moving, I can rectify that in around 10 minutes. When I told the people at Campo that I only animate primitive geometric shapes, they thought I was joking, and I didn’t want to correct them b/c I need the money, so right now I’m booked in to animate all the games boxes, but also the main character and everything else.

    If it’s of interest, I worked as animator and designer on the game “Ori and the Blind Forest” and I piggybacked on the success of various Valve properties, exploiting these well-known brands to garner hits. The advertising money lasted a few years but that well has run dry, which is the primary reason I’ve started putting new YouTube videos up.

    Lovely to meet you,

    Let’s talk soon,

    James Nicholas Benson

    P.S. I worked on that Project Milo game where Peter Molyneux constructed a small interactive boy, so you know Firewatch is in safe hands.

    P.P.S. I find It hard to be sincere in a public setting. In truth I am a normal person who is very happy to be working with people I have admired and respected for years. They really are very good-looking.

  3. Feedback is the lifeline that connects the player to a game’s systems. Without good feedback, the player cannot understand how to interact with a game’s world. Inconsistent or inadequate feedback makes a game feel mushy, unresponsive, and unsatisfying to engage with.
Even though Firewatch doesn’t have complicated puzzles or intricate combat, it’s essential for players to understand which objects they can interact with in the game and how. It facilitates them being able to play intentionally and for us to communicate to the player what the possibility space of the game is. And as the HUD is something the player sees a lot, how interactive and polished it is has a big impact on player perception…
[[MORE]]
We wanted to get a HUD with appealing look and feel up and running early in development. Jake created the assets and I integrated them into the game itself. We wanted the UI system to be modular, so its appearance could be modified by Jake without needing many changes to the underlying implementation. We used a visual scripting system and a 3rd party UI package.
In general, I’m wary of visual scripting solutions. I find they are often brittle and make implementing simple features cumbersome and difficult features even more difficult. 
However, as Will wisely counseled, they are good for one thing procedural code is not: implementing state machines. A HUD is basically a bunch of elements responding to other actions executed within the game; it rarely does any execution itself.
We’re using Playmaker, a robust visual scripting package available in the Unity Asset store. It provides a state machine component that can be added to any GameObject, and within it you define states, actions to execute when entering those states, and events that will cause transitions to other states. But the best part about Playmaker is that in addition to be easy to add custom actions, it has a number of custom actions for other popular third-party Unity packages, including the UI package we’re using, NGUI. (Playmaker + NGUI integration is available here)
Under the hood, we have a HUD manager script that receives notifications from all the other relevant player-controlling scripts. It get notified when the player targets a new object, when the pick something up, etc. This HUD manager dispatches events to a root UI object. Rather than having one massive state machine for the entire UI, we gave each HUD element its own simpler Playmaker state machine. So the reticule that expands and contracts is its has its own state machine, the object name that appears beneath it has its own state machine, etc.
The HUD manager dispatches those events to Playmaker, and in turn the Playmaker state transitions execute actions that tell various NGUI tweens to play. In Playmaker, it looks like this:

So with the player targeting the “log” above, the targeting system tells the HUD manager the player has a new target, the HUD manager sends an event to Playmaker, and Playmaker handles that event by transitioning the reticule NGUI element from its “off” state to its “on” state. And as the player is close enough to see the object’s name, another event is dispatched to Playmaker, causing that text element to fade in.
The only challenge here was, while Playmaker allows sending events to specific state machines or broadcasting an event globally to every state machine currently active in the entire scene, it doesn’t seem to provide a way to send events to all the state machines on a single GameObject. Rather than maintain references to each individual state machine and needing to update them each time we add new state machines, I wrote a simple event broadcast component.
public class vgPlaymakerBroadcast : vgMonoBehaviour {

private PlayMakerFSM[] allFSMs;

// Use this for initialization

void Start () 

{

allFSMs = gameObject.GetComponents();

}

public void SendEventToAllFSM(string eventToSend)

{

for (int i = 0; i < allFSMs.Length; i++)

{

allFSMs[i].SendEvent(eventToSend);

}

}

}

Of course, shortly after we implemented this, Unity announced they will be adding a new native UI system in Unity 4.6. But hopefully, since we set up the HUD to be modular, we can simply change the Playmaker actions from targeting NGUI components to targeting the native Unity UI components instead.
Hopefully that’s been at least somewhat useful! One of the most pleasantly surprising things about working with Unity is how often you can find an asset store package like Playmaker that saves a mountain of time not needing to re-implement known needs like simple state machines. Instead it allows you to just focus on using those packages to make the game look, feel and play better.

    Feedback is the lifeline that connects the player to a game’s systems. Without good feedback, the player cannot understand how to interact with a game’s world. Inconsistent or inadequate feedback makes a game feel mushy, unresponsive, and unsatisfying to engage with.

    Even though Firewatch doesn’t have complicated puzzles or intricate combat, it’s essential for players to understand which objects they can interact with in the game and how. It facilitates them being able to play intentionally and for us to communicate to the player what the possibility space of the game is. And as the HUD is something the player sees a lot, how interactive and polished it is has a big impact on player perception…

  4. Hello again. Olly here. Hi.

    I’m told that it has been too long since the last art blog was posted. So here I am, posting some art in a blog.

    These are some early sketches and colour thumbnails for environments you may see in the final game. Not pictured: Ice level. Lava level. Warp zone.

  5. Enjoy your Fourth of July and this small update!

    Enjoy your Fourth of July and this small update!

  6. Hello everyone,
You don’t know me, but you might have played one of the games I worked on. Even if you did, it might be difficult to explain what I did on it…
Did you notice how the lighting was smooth across surfaces without artifacts? Have you noticed that the character shows damage exactly where it was hit along the correct direction the enemy was slashing? Yes?
Well, then I have a few more: Did your game ever crash? Did any textures pop in close to the camera? Were you surprised by how complicated the complicated world in front of you looked and what the developers did to render it?
Hi, I’m Paolo. I am a graphics and core engine programmer. I am the director behind the curtains who makes sure all the silicon available in the box you are playing the game on is used. I am the guy that can talk about “physically based rendering,” or “memory compression techniques,” and I need to know that, for a computer, ((a * b) * c) is not necessarily equal to (a * (b * c)) (and yes, I know that multiplication is commutable, I am talking about this). I am the guy who spends his time on profilers, trying to understand how to lay down your data in such a way that artists and designers don’t have to worry about it, but your machine is not screaming cache misses every 3 cycles.
No more than a couple of months ago, I saw Campo Santo was looking for a graphics programmer. Interesting. I knew Jake, Sean and Chris from their podcast and the games they worked on. I thought I would give them a call, just ‘cause. The call ended up being a two-hour discussion about the game, what they needed, and how to achieve it.Things like: We need to take Olly’s art and make it look awesome in 3D.
No pressure.
It sounded extremely interesting. A cool game developed by some of the coolest people from the industry? A few weeks later, I decided to pack my room and move up to San Francisco. Now I am here. Let’s see what comes next. More on that soon.
—Paolo

    Hello everyone,

    You don’t know me, but you might have played one of the games I worked on. Even if you did, it might be difficult to explain what I did on it…

    Did you notice how the lighting was smooth across surfaces without artifacts? Have you noticed that the character shows damage exactly where it was hit along the correct direction the enemy was slashing? Yes?

    Well, then I have a few more: Did your game ever crash? Did any textures pop in close to the camera? Were you surprised by how complicated the complicated world in front of you looked and what the developers did to render it?

    Hi, I’m Paolo. I am a graphics and core engine programmer. I am the director behind the curtains who makes sure all the silicon available in the box you are playing the game on is used. I am the guy that can talk about “physically based rendering,” or “memory compression techniques,” and I need to know that, for a computer, ((a * b) * c) is not necessarily equal to (a * (b * c)) (and yes, I know that multiplication is commutable, I am talking about this). I am the guy who spends his time on profilers, trying to understand how to lay down your data in such a way that artists and designers don’t have to worry about it, but your machine is not screaming cache misses every 3 cycles.

    No more than a couple of months ago, I saw Campo Santo was looking for a graphics programmer. Interesting. I knew Jake, Sean and Chris from their podcast and the games they worked on. I thought I would give them a call, just ‘cause. The call ended up being a two-hour discussion about the game, what they needed, and how to achieve it.
    Things like: We need to take Olly’s art and make it look awesome in 3D.

    No pressure.

    It sounded extremely interesting. A cool game developed by some of the coolest people from the industry? A few weeks later, I decided to pack my room and move up to San Francisco. Now I am here. Let’s see what comes next. More on that soon.

    —Paolo

  7. Scratch VO recording with Erin Y. Ashe and Nick Herman. We use Logic for Mac for in-house scratch track recording. A grey box layout of a canyon area.

    Progress! I wanted to post a few shots of the last week of work. We had our good friends Erin Ashe and Nick Herman in over the weekend to lend some temporary voices for Henry and Delilah. If you’re a Telltale fan you’ll know Erin from her work as Molly in The Walking Dead and Snow in The Wolf Among Us and Nick, a multi-talented director over there, was the voice of Glenn in The Walking Dead.  

    Jake laid out a near area of the game (the greybox above) while Jane and new hire Paolo made existing areas look pretty (which you can see Jake and Jane playing). We play through the game as a group a couple times a week and yesterday’s play-through was particularly invigorating. 

  8. Issue 2 of The Campo Santo Quarterly Review is here.  What on earth is The Quarterly Review, you ask? What if I told you it was a collection of articles and short stories written and curated by Campo Santo Ombudsman Duncan Fyfe? Would that tickle your fancy?
We created the Quarterly Review for a bevy of reasons. Firstly, I always wanted to work for a company that published a literary journal as I think it’s a clear mark of succeeding in American business. Like owning a professional sports team. Secondly, we believe in putting out entertaining things as often as possible. So when Duncan said he would be our ombudsman, it struck me that we finally had a chance to make something great worth reading (as he would write it and he is brilliant) and  it would be in service of giving you some insight into what’s going on over here. Is a literary journal a bizarre thing for a video game company to publish? Yes. But in our case it’s a no brainer. Enjoy!

    Issue 2 of The Campo Santo Quarterly Review is here.  What on earth is The Quarterly Review, you ask? What if I told you it was a collection of articles and short stories written and curated by Campo Santo Ombudsman Duncan Fyfe? Would that tickle your fancy?

    We created the Quarterly Review for a bevy of reasons. Firstly, I always wanted to work for a company that published a literary journal as I think it’s a clear mark of succeeding in American business. Like owning a professional sports team. Secondly, we believe in putting out entertaining things as often as possible. So when Duncan said he would be our ombudsman, it struck me that we finally had a chance to make something great worth reading (as he would write it and he is brilliant) and  it would be in service of giving you some insight into what’s going on over here. Is a literary journal a bizarre thing for a video game company to publish? Yes. But in our case it’s a no brainer. Enjoy!

  9. MECANIM ANIMATION CALLBACKS IN UNITY
In order to get the most out of James’ amazing first-person animations in Firewatch, we need to have the ability to reflect the state of our Mecanim State Machine—which drives animation in Unity—in the gameplay code. I spent a few days looking for various solutions, and never found one I was thrilled with.
What I really wanted was an easy way to have code wait for Mecanim states and transitions to do things. My first pass was simply extracting the play duration of a given state, and using co-routines to wait. This worked for a prototype, but I knew it was never going to be a shipping solution. The rule of thumb with player animations is that you assume they will be interrupted, and I needed to be able to capture that in code.
I decided that what I needed was an event that to hook into that would let me know when states and transitions were started and finished. Sadly, as far as I can tell, Mecanim doesn’t provide this functionality by default. 
After some research, I made a system that allows me to register specific functions to fire on Begin or End for any Mecanim State or Transition. I used C# delegates for both speed and flexibility. 

Here is a link to the full source of my solution.
That is a sanitized version. My version is embedded in a class that also reflects a bunch of the concrete player Mecanim state machine that you obviously can’t use in your own Unity projects. In order to avoid lots of costly hashing, I cache off all the variable and state name hashes. 
The Event Handler consists of two major parts. Firstly, we have an update loop that lets us tell when a Mecanim state or transition change has occurred.
In void Start() we set up some arrays to track our Mecanim States and Transitions every frame, per animation layer:
previousTransitions = new AnimatorTransitionInfo[animator.layerCount]; previousStates = new AnimatorStateInfo[animator.layerCount];
Then, every frame, we check to see if our state or transition has changed:
private void UpdateMecanimCallbacks() {   for( int i = 0; i < animator.layerCount; ++i )   {     AnimatorTransitionInfo tempTransition = animator.GetAnimatorTransitionInfo(i);     AnimatorStateInfo tempState = animator.GetCurrentAnimatorStateInfo(i);     int previousTransition = previousTransitions[i].nameHash;     if( tempTransition.nameHash != previousTransition )     {       //Handle Callbacks!       previousTransitions[i] = tempTransition;     }     int previousState = previousStates[i].nameHash;     if( tempState.nameHash != previousState )     {       //Handle Callbacks!       previousStates[i] = tempState;     }   } } 
This neatly goes through all of our layers, checks our current state, and fires off callbacks as necessary. Well, right now it fires off comments. To the callbacks!
If you have never used them before, I highly recommend you look up everything you can on delegates in C#. Basically, they are function pointers done well. In order to handle our callbacks, we declare and create a set of dictionaries matching state or transition name (hash) to delegates, like so:
private Dictionary<int, System.Delegate> stateBeginCallbackMap;
private Dictionary<int, System.Delegate> stateEndCallbackMap;

And to initialize them to non-null in void Start():
stateBeginCallbackMap = new Dictionary<int, System.Delegate>();
stateEndCallbackMap = new Dictionary<int, System.Delegate>();

Now we need to provide ways for external clients to register their own callbacks with this system. We need to allow other systems to register and unregister for Begin and End on both states and transitions. Here are the functions for state Begin:
public delegate void Callback();

public void RegisterOnStateBegin(int animStateHash, Callback callback)
{
  RegisterCallback(stateBeginCallbackMap, animStateHash, callback);
}

public void UnRegisterOnStateBegin(int animStateHash, Callback callback)
{
  UnRegisterCallback(stateBeginCallbackMap, animStateHash, callback);
}

private void RegisterCallback(Dictionary<int, System.Delegate> dictionary, int animHash, Callback callback)
{
  if( dictionary.ContainsKey(animHash) )
  {
     dictionary[animHash] = (Callback)dictionary[animHash] + callback;
  }
  else
  {
    dictionary.Add(animHash, callback);
  }
}

private void UnRegisterCallback(Dictionary<int, System.Delegate> dictionary, int animHash, Callback callback)
{
  if( dictionary.ContainsKey(animHash) )
  {
    dictionary[animHash] = (Callback)dictionary[animHash] - callback;
  }
}

The first two functions are just uninteresting wrappers. There are a few more of those in the full file. It just makes the calling code easier to parse. The concrete RegisterCallback and UnRegisterCallback do the real work. Callback, in this context, is the name of my delegate type. Delegates can be added to or subtracted from, in order to register and unregister functions to call. It is quite useful. This code searches our dictionaries for a given hash value, and then increments or decrements the resulting delegate.
Now that some client code has registered some callbacks with us, we can trigger those callbacks in our UpdateMecanimCallbacks function above:
System.Delegate endCallback;
if( stateEndCallbackMap.TryGetValue(previousState, out endCallback) )
{
	((Callback)endCallback)();
}

System.Delegate beginCallback;
if( stateBeginCallbackMap.TryGetValue(tempState.nameHash, out beginCallback) )
{
	((Callback)beginCallback)();
}

Certainly not the most beautiful code. We use TryGetValue on our dictionaries to get any callbacks that have been registered for our previous state End or our new state Begin. That function nicely handles the case that no one has registered for a given hash value. We also have to cast our System.Delegate into our nicely typed callback delegate. But, that syntactical ugliness aside, it ends up being fairly straightforward. Get our delegate, then call it. That then calls every function that was registered with the system.
Some example calling code to round things out. Here I am registering a callback to know when I have stopped using an item. This lets the player state know it can go back to walking around, having conversations, and generally being a sad man in the woods.
eventHandler.RegisterOnStateEnd( vgPlayerAnimState.Examine, OnExamineAnimationComplete );

I hope someone out there finds this useful. I have gotten a ton of information from the Unity community at large. It is really the best thing about the engine.

    MECANIM ANIMATION CALLBACKS IN UNITY

    In order to get the most out of James’ amazing first-person animations in Firewatch, we need to have the ability to reflect the state of our Mecanim State Machine—which drives animation in Unity—in the gameplay code. I spent a few days looking for various solutions, and never found one I was thrilled with.

    What I really wanted was an easy way to have code wait for Mecanim states and transitions to do things. My first pass was simply extracting the play duration of a given state, and using co-routines to wait. This worked for a prototype, but I knew it was never going to be a shipping solution. The rule of thumb with player animations is that you assume they will be interrupted, and I needed to be able to capture that in code.

    I decided that what I needed was an event that to hook into that would let me know when states and transitions were started and finished. Sadly, as far as I can tell, Mecanim doesn’t provide this functionality by default. 

    After some research, I made a system that allows me to register specific functions to fire on Begin or End for any Mecanim State or Transition. I used C# delegates for both speed and flexibility. 

  10. Some experimental first person animation tests for Firewatch.