Development update #2

What’s been going on at the office lately? It’s still all about the battle! Well, almost all about the battle at least. We are working on getting certain features up and running, that will add interesting mechanics to our battle mode. At the same time, we are working hard on redefining the visuals to really match the look of adventure mode.

I, for one, have also had the privilege of reviewing our backlog (list of features/art/content to implement) and discussed with our publisher how we can work smart and reach our goals faster. I have also agreed on terms with a new programmer who will join our team next year. It is a person with a solid background in the games industry and we are really looking forward to getting that extra hand on deck to get the game done in a shorter time. Furthermore, I have been working on a contract for a new sound designer who recently worked on Mutant: Year Zero. Who doesn’t love a good contract, right?

Suitingly, Niklas has been working on converting our project to use a sound system called Wwise. We have been using our own sound system until now, aptly named LavaSound. That system is based on the Unity audio with memory handling in mind, but we want to be able to control and change the sounds outside the Unity project.

Wwise enables that, and it will be a good fit for our project and for our new sound designer. While we are on the topic of systems and plugins: David has been working on integrating More Mountains MMFeedbacks (a plugin for Unity) into our game to juice it up a lot more.

We are trying to get a better visual variatio by adding non-human troops to Doneria. Feel free to leave a comment below if you have feedback!

We are trying to get a better visual variatio by adding non-human troops to Doneria. Feel free to leave a comment below if you have feedback!

At the same time, Carl has been looking over how and if we can implement events in our game and also working on abilities and traits for the different units. And finally, our concept artist Felix have worked on concepts for two new Doneria units. The Lavaborn serve as mercenaries in the Donerian army and consist of a smaller weaker unit and a tanky high tier unit.

Finally, if you missed it, we recently shared our main theme. Take a listen and let us know what you think!


Please note that this is a devblog, features and graphics mentioned or displayed above may or may not change during the development process.

Development update

This week most of our team has been working with battle. Everything from troop design (and re-design) to battle UI and how the actual battle grid will look.

Personally, I’ve been working on a lot of admin stuff (some think I’m the CEO, but actually I’m not, I just act like I’m the CEO). I’ve also written some more story background for our Wielders, their motives and how they fit into our world. Part of this work is to help prepare for our portrait artist in creating amazing wielder portraits. Another aspect is of course that we really want the world to be believable and coherent, in its own weird way. Both myself and Carl, who writes most of the lore, read a lot of fantasy and have a strong opinion against creating a generic fantasy world with standard cliches. Carl has been delving even deeper into the game world this week and refined lore, campaign, and units.

An example of the Tooltip system in action.

An example of the Tooltip system in action.

In the meantime, David, along with Niklas, has been working on changing our camera rig to use Unity’s Cinemachine for making easier camera transitions. Furthermore, Niklas has been working with the backlog and structuring it for our next internal milestone. He’s also been working on getting the tooltips (when you hover over objects) working with our new 4K-ready designs.

Behold the evolution of our humble Squire troop. It is safe to say that the design of our characters have undergone a lot of scrutiny and evaluation. Which one do you prefer?

Behold the evolution of our humble Squire troop. It is safe to say that the design of our characters have undergone a lot of scrutiny and evaluation. Which one do you prefer?

And finally Anders, along with the rest of the art team, has been working on textures for the battlefield, redesigning our factions visual appearance to better fit their identity and redesigning our battle sprites (pixel pushing!).

We are exploring some new ideas for a large Rana troop. These are some initial concepts and so far we are leaning more towards a giant insect rather than a giant mammal.

We are exploring some new ideas for a large Rana troop. These are some initial concepts and so far we are leaning more towards a giant insect rather than a giant mammal.


Please note that this is a devblog, features and graphics mentioned or displayed above may or may not change during the development process.

The shader approach to billboarding

People have asked me about the technology behind the 2.5D billboarded look of our game, so I thought it would be time to write a blogpost about it.

A screenshot from our launch trailer

A screenshot from our launch trailer

In the beginning…

It became apparent very early in our 2.5D development that billboarding could quickly become a huge performance cost. We wanted thousands of animated billboards forming mountain ranges, forests and plains of grass. In our very first approaches we tried to use regular sprites with attached monobehaviors updating their rotation. This worked pretty well as long as our camera angle did not change. But as you’ve probably seen in our launch trailer, we wanted to be able to zoom in and out while changing the rotation of our camera.

Enter Cartography…

It was clear we needed to change our approach, and Cartography was born. Cartography is what we ended up calling the system in charge of generating and drawing our landscapes (ground, cliffs, trees, mountains, grass, water, etc). We also implemented Unity’s new Lightweight Rendering Pipeline to get even more performance out of our rendering.

To solve the billboarding problem we turned to shader approximations. We simply move the vertices of our “sprites” in a way that looks very much like they’re being rotated. From a first look this works very good, but we quickly ran into the problem of translating between world space and object space as we wanted the base of our objects to always remain still and attached to the ground. To solve this issue we ended up baking that information into the y-component of the second uv-channel of our billboard “sprites” (or meshes).

A screenshot from our editor drawing the pre-baked y-component of the second uv-channel. Notice how the base of the objects are completely black, and how objects gets brighter and brighter the taller they are. The whiter the part of the object is th…

A screenshot from our editor drawing the pre-baked y-component of the second uv-channel. Notice how the base of the objects are completely black, and how objects gets brighter and brighter the taller they are. The whiter the part of the object is the more it gets displaced, and blackness indicates the part of the mesh we don’t displace at all.

Baking this information was actually very simple as shown in the method below.

void BillboardFixer(Mesh mesh)
{
    var vertices = mesh.vertices;
    var uvs = new List<Vector3>(mesh.vertexCount);
    for (var i = 0; i < mesh.vertexCount; ++i)
    {
        var uv = vertices[i];
        uvs.Add(uv);
    }
    mesh.SetUVs(1, uvs);
}

With this baked information we then created a sub-graph for calculating the desired vertex position. Besides the baked second uv information we also needed to know the rotation of the camera. This is calculated and passed to our shaders using this simple line of code.

Shader.SetGlobalVector(
  "_Billboard",
  Camera.main.transform.rotation.eulerAngles * (Mathf.PI / 180f)
);
The sub-graph in charge of displacing the vertices to simulate billboarding

The sub-graph in charge of displacing the vertices to simulate billboarding

This in turn is fed into our shaders like in the very simple example below. Note that we also had to reconstruct our normals in order to get the lighting correct. We opted for a static reconstruction as this turned out to look better than a dynamic one. But this would definitely depend on the use-case.

A “final” shader using the billboarding sub-graph

A “final” shader using the billboarding sub-graph

Conclusion

This solution is pretty much tailored to our very specific use case, as billboards only rotate in the X-axis. A limitation that suits our game very well. This approach also batch well, and is generally very fast yet accurate enough for our needs. With that said, I should mention that we've opted for not using this approach when it comes to characters and buildings (anything dynamic really) as any performance gains are quickly outweighed by the complexity of the system.

Do you want to be a Game Dev?

19550972_10155274095935218_469930516_n.jpg

A lot of people would like to work in the gaming industry so I thought I’d share my story of how I got into it the ‘biz’. Hopefully, it might help someone to achieve the same thing.

A little more than a year ago one of my close friends, Magnus Alm, broached the subject of working on a game with him. I was surprised but, of course, interested in talking more about his idea for a game.

It was in the early morning, the sun was coming up and we were in an old rowboat in the middle of a lake. The weak morning sunshine made the mists drifting slowly over the waters look like playful sprites as we talked about creating a game with a rich fantasy setting. It all sounded very exciting but I didn’t really think it would come to anything. But dreams are free and talking about something never hurts.


I’ve worked in the entertainment industry since 2002 and if I’ve learned anything it is that you should leap at every opportunity that excites you. The idea of working with games really felt exciting to me! So even though I had no real training or experience in the gaming industry, I knew that the skills that I possess both through my other work and through my own passion for games would be enough to do the job that Magnus described.

More than half a year later we were hanging out, having a good ol’ Swedish fika. Out of the blue, he asked me if I was still interested in the job. Without a moment's hesitation, I said that of course I was. About a month after that, we were on our way to creating an amazing game.

A game designer doesn't always bring his chainmail to the office. But sometimes.

A game designer doesn't always bring his chainmail to the office. But sometimes.

So by now I bet you’re thinking that I had some crazy luck, and I have to agree with you about that. This is not the way you’re supposed to get into an industry. Pretty darn lucky! But then again what is luck? Luck is what happens when preparation meets opportunity.  And this is my first point about how to get into any job you want: if you don’t prime yourself for the opportunity then when it arrives you can’t seize it.

I had had a hunch that Magnus might ask me again, so I did a few key things to prime myself if the opportunity came knocking. I turned down full time work and instead worked as a freelancer, making less money than I otherwise would. After talking to Magnus the first time I made sure to go over my relevant skills and tried to learn more about what I didn’t know so I could accept the job with confidence. And lastly: if I hadn’t been so enthusiastic about being involved in the game in the first place, Magnus might not have asked me again when the time came around.

This is something that I’ve learned from the years I worked as an actor. Actors always need to be ready to show their skills at an audition or cold read, sometimes with as little as ten minutes prep time. They must have those skills polished and ready to deliver. If you’re prepared for opportunity, you’ll find that you’ll be more lucky. In other words, you make your own luck.

Stepping into a new biz

pexels-photo-616849.jpeg

I used to work as an actor and musical performer and also as a director, teacher and scriptwriter. Before that I spent over two years in the army, dealing mainly with troop tactics to a maximum of company level. These skills, along with with my passion for and knowledge of games, is what I brought to the table as I began my work. I still felt a gnawing feeling of doubt though. Would that be enough?
 
With great support from the rest of the team, I soon warmed up to my assignments. I found that working on a game is very similar to working on a feature script or a play, and that I could apply the same thinking and discipline to it. The creativity and work process that I have developed from working with improvisation theatre are also very helpful (I’ll probably write some posts about creativity later on.) Without a good team giving me relevant feedback so that I knew what worked and what didn’t, I might’ve struggled to trust that those skills were applicable to this job. 

So what’s my second point? Trust that you’re good enough for the job that you have and trust work processes that you’ve used before. Change when you really need to change but remember to bring the strengths from your former career and life with you into your new job. After all, that is why you decided to go into the industry, start your own studio, or were offered that job to start out with.

Making the passion work

building-joy-planning-plans.jpg

I want to work with games because I love games. I loved spending hours grinding for my first Onyxia raid back in vanilla WoW, I loved taking over the world as the Sioux in Europa Universalis 4, and there’s a certain satisfaction when I get outsmarted in a long game of Twilight Imperium 3 when a friend wins with a sneaky victory push.

When I play a new game I immediately try to ‘break’ it. I find the most cheesy and overpowered strategy to beat it on the hardest difficulty. If it’s in a board game I sometimes point it out to everyone so we can implement a house rule, but other times I just use that design flaw to win. Yeah, I’m that guy. 
 
I read and write on forums and debate with other people like me about what would happen if a half point of something would be altered, or about why giving flying to a specific unit would make the whole game imbalanced. It’s these very things about me that Magnus picked up on and why he knew that I would fit in the team for the strategy game we’re working on.

Whatever passion fuels your love of games is the passion that you need to bring into the creation of games. That’s where you already have skills you might not have thought about and usually other skills that support it. Sometimes you stare so much at a title or a career goal that you forget to figure out what that job entails.

As an example, I know a lot of people that want to work as a screen actor. But most of them don’t enjoy reading hundreds of pages of script every month and constantly getting rejected for work they’ve put their heart and soul into. And if they do land a part, they might not enjoy working really long hours. But that’s the job, so it might not be ideal for them even if the title sounds appealing.

So you want to work in gaming, but with what exactly? Where will your passion help you? Let go of the titles and actually think about where your skills and your passion will help you. My third point is to look at what you can and want to do for hours on end, and not what fancy title you want to introduce yourself with at a party. Let your passion fuel you and your work.

Final words

color-pencil-drawing-coloring-colored-pencils-159825.jpeg

When I started writing this blog post it wasn’t really about what others could learn from me stepping into the biz. But as I was writing I noticed that that’s where it was going, so I went with it. I was just going to write about what it felt like coming into the gaming industry. I can sum that up real quick: I feel very fortunate to have the job I do,and I’m slowly learning to say “Game Designer” when someone asks me what I work with.
 
ps.
I don’t miss the questions that always popped up when I used to answer “Actor”: “No, I’m not famous. Yes, you might have seen me in something. No, I won’t win an Oscar one day.” But one day someone named Oscar might play a game I made. Even better.
 

Building value as a game developer

startup-photos.jpg

You build games, right? Of course you do! So let me take you out of your comfort zone and suggest that you build games AND value. Whether you like it or not. The question is, do you nurture that value and make it grow or let it go to waste?

A story about value creation

A lot of game developers bank everything on one game release. They pour passion, time and money into a game and then hope for the best. If the game succeeds, amazing! If the game fails, well, too bad. This might force the developer to make drastic changes, or even worse, close down the business. But let me yet again challenge that perception. I built a game studio along with a few other co-founders several years ago. We released very few games that generated more revenue than the cost of development. In fact, we were more than once close to going bankrupt. Even so, in the end we managed to sell the company. All founders got a nice payback for the time, passion and money invested, even though the company never really was financially very successful! So, while we never created short term value (a hit game with great sales) we did create long term value which was realized over time.

So, my statement is this: A game developer does not have to create a hit game to create value for its founders. Sounds weird? Not really.

Someone’s sitting in the shade today because someone planted a tree a long time ago.
— - Warren Buffett

How to create and grow your value

To an experienced entrepreneur the following advices might seem like no brainers, or just plain silly. But to an indie game developer with more passion for games than business development, the points below should be a guide for simple ways to build additional value besides the actual games.

Keep your contracts in place

Make sure all assets created actually belong to the business and not the individuals working on the game. Keep an NDA as a standard part of the employment or freelance contracts. Fight before you sign contracts, not after. If you get an opportunity to sell your business, merge with a larger entity or need to buy a partner out, your papers need to be in order.

Maintain ownership of your assets

This means all assets, such as code, art and IP. If you work with a publisher it is not certain you can retain all rights. But, you always need to negotiate to get your part of any deal as reasonable as possible. Perhaps retaining your code ownership is ok with a partner if you sign a perpetual license for them to use the code? Keep in mind that a publisher often ask for more than they really need, just for the sake of not missing out on any potential upside. But they can often be persuaded to step away from their standard contracts.

Say no to bad deals

This kind of relates to the point above. You'll always have to ask yourself: What is my dream of making games worth? I've turned down several high budget projects simply because I felt the other part was asking for too much. Furthermore, when potential partners start to play tricks and show poor manners already when negotiating, it is in my experience a sign of worse things to come. Getting stuck with a shitty contract is a painful experience and will keep your focus in the wrong place.

Maintain low costs, when possible

Keep an eye on all your costs and always negotiate. If you can lower costs with 10% and increase income with 10% it adds up nicely. Keeping a low cost profile is generally the way to go. However, sometimes you need to make investments in order to scale up. As an example: My old studio developed an online game that grew exponentially and caused our servers to crash three times in three weeks. Instead of putting in the cash for additional server power we opted for cheaper solutions. In hindsight it was a waste of future revenues to NOT invest in hardware at that time.

Diversify your revenue streams

Relying on only one source of revenue is risky. If you can place your eggs in several baskets instead of one, do so. This isn't always easy as you might focus on developing one game. But you should at least consider what options you have to generate revenue from several separate sources.

Take care of what you create

In my experience, developers often love to build specific solutions to all problems. It is rarely worth it from a business perspective. But lets say you do build solutions for specific problems, because you can't find an out of the box solution. Then you are building something that others potentially could be interested in. You should recognize this as a value. Perhaps you could sell or license the solution to others?

Network

Keep in mind that business deals are made between people and not the business entities themselves, regardless of what the contract says. In order to boost your value creation you'll need to get out and meet others. Building a reputation and getting to know the right people is a great way to increase your chances of growing value.

Take reasonable risks

I basically mean that you don't always have to stay on the treaded path. The road to success is rarely straight and more than often you can find value in places you'd never imagined.


In the end, it comes down to having a mindset. Building value is not really hard, certainly not harder than making a great game. So, why not do both?

 

Distributed teams - Possibilities and pitfalls

We consist of a fairly small team with only four employees and one freelancer. Even though we have an office some of us work from remote locations on a regular basis. A few of us have lenghty experience of working with team members spread out across several countries and offices. So this way of working feels fairly natural. With that said, we´d like to share some of the benefits and obstacles that can arise through working across different locations.


Possibilites

Personal freedom
Needless to say, there is a huge personal gain in being able to choose your own workplace. Even if everyone is based in the same city, it is great to be able to leave and pick up the kids from the school without stress and not having to spend time commuting. It is easier to take a break for exercising outdoors (depending on where you live of course) and get refreshed.

Focus
More flexibility can be a great way to increase enery and passion for your work, as you are allowed to perform your work tasks in an environment you prefer. Creating your own atmosphere can be a great mood booster. It can also greatly limit the amount of distracting elements, such as loud conversations, allowing you to easily find your focus.


Problems

people-coffee-notes-tea.jpg

Lack of social interaction
A CEO once told me that he didn't approve of too much work from remote locations, because people would miss the "watercooler moments".  He basically meant that there are important and informal dialogues going on at the office. When people kick back, have a cup of coffee and just happen to stumble into meaningful conversations (a.k.a innovation!).

How we handle it
Some of us regurlarly play team based games during the lunch break. It is a way to increase cooperation, playfulness and inspiration. But most of all, it is fun and doesn't really serve any specific purpose. Actively supporting people to do fun things together is just something that makes sense when building a great team.

All of our team members have a recurring calendar event at 3 p.m. Everyone dials in to the video conference and have a Swedish fika. We allow ourselves to just chat about whatever we feel like, but we also have the benefit of making a turn based strategy game, so we always engage in a multiplayer session. Friendly banter and random discussions connects the team and builds the sense of belonging, even for those not physically present.

Misunderstandings
It can be easy to misunderstand a text, likewise it is easy to misinterpret the tone in a chat conversation. While someone might perceive a sentence as formal and to the point, another person might view the sentence as bossy and harsh. When team members works from separate locations it is important to minimize misunderstandings.

How we handle it
We emphasize the importance of structure, documentation and review in all of our work. Our "definition of done" includes the two following points:

  • Documented where applicable
  • Reviewed by another person (if it’s meant for production use)

This means that any part of the development that is considered to be "done" has been both properly documented AND reviewed by someone else in the development team. This helps us offset problems with misunderstandings of direct instructions for implementation, but not social misunderstandings.

We regard sprint retrospectives to be an excellent platform for feedback and dialogue. It allows team members to regurlarly discuss what works well and what doesn't, so we can find solutions to potential problems. It is a great way to ventilate frustrations and clear out misunderstandings. But as the retrospective only happens after a sprint ends we also advocate a healthy dose of daily discussions, between team members in all locations. We do this by letting all team members use the same communication and planning tools, not just only the ones working off site. Everyone should be on the same page and up to date of what's going on. 

And, incidentally, this gives us an excellent transition into the next part.


Methodology & Tools

There are tons of more information about the topics below, so I won't go into great details. I'll rather focus on explaining how we use these tools in the context of having a distributed team.

SCRUM
Having the daily standup meeting as a natural meeting point and a way to kick off the day is great. It is also a regular appointment where people learn what others are working on and if they need help with something. Furthermore, we can also fall back on SCRUM as a framework for how we operate, meaning we have a solid foundation that we rely on as we grow.

Google Drive
Using Google Docs, Sheets and Presentations is amazing for collaboration. The comment functionality makes reviewing easy and you can also check for changes swiftly. We prefer to keep our design documentation across several folders and specify features in stand alone documents. We want to make it easy for others to dive into selected parts of the game design when needed.

Google Calendar + Google Hangouts
Great for setting up both team wide and personal appointments. We use the calendar to plan for daily standup, reviews, retrospects, etc. As our SCRUM team will never be more than 9 team members, we are not overly worried about the chat or video lines being too crowded.

Slack
A great way for keeping up the daily conversations. With multiple channels not everyone needs to see or react to everything. Works particurlarly well for our graphic freelancers who quickly can get feedback and bounce variations back and forth.

Trello
A digital SCRUM board allows everyone to see what the others are working on and who needs help with reviewing something. It is also a good way to spot tasks that have remain blocked for a long period of time.

screenhero.png

Screen Hero
Pair Programming is something we love, and try to engage in as much as possible. Working from a distance can make this challenging, but we've found Screen Hero to be an excellent solution.


A final note

Working from home, co-working spaces or cafés isn't for everyone. But allowing team members to pick their own location can be a great way to allow personal freedom and keep up motivation among team members.

You can find further insights into the topic in this great blogpost at Happy Melly.

Investment vs. publishing

Ever since I started in this industry (about 10 years ago) there has been talks about both the demise and rise of the publishers. It seems that when a new platform comes around developers tend to see it as a solution to a problem of independence. Or even more specifically, a way to self publish. During my time as a game developer those revolutions have been the digital channels for consoles (Xbox Live Arcade, etc), Social networks (Facebook mainly), the smartphone/tablet Appstores and now the talk is all about VR/AR.

Whenever a new platform comes around there is generally a window of opportunity for smaller developers to reach an audience without the need for publishers. It works well for a while, but as the competition stiffens and the amount of content grows, the sales decline. And, yet again, the publishers tend to move in and establish themselves as sort of gatekeepers. With access to capital, marketing channels and good relations with the platform holders, they have the business tools that a developer often lacks. But, should a developer have proper funding and a long term business perspective, there is no reason a developer couldn't manage to gain all those tools themselves. Trying to get signed with a publisher isn't much more different from getting an investment from a venture capitalist. So, let's compare the two and consider the pros and cons.

Publishing

What do you give up?
More often than not, you have to give up your IP, and if not that, at least a rights of first refusal to publish any sequels or derivative works. You also have to consider working in a way that might not suit you, but rather the publisher, as most publishers pay on a milestone basis. Meaning that for a certain chunk of work done, they pay you a chunk of money. You will also share the revenue of the game with the publisher and those terms will vary greatly. Getting a 70/30 split (with 70% going to the developer) is quite good, but then again, it comes down to a lot more details such as if the publisher can deduct costs prior to sharing the revenue, etc.

What do you get?
You should be getting funds to develop your game. Feedback and support during the development process. Marketing budget and strategy executed by the publisher, often along with yourself and your team. Furthermore, the publisher should have access to gatekeepers at whatever platform you are targeting, to make sure you have potential for being featured.

you often end up in a weird “work for hire” kind of relationship

My experience
I have heard about a few developers who had great relationship with their publishers. I've heard way more often about developers who disliked their publisher. This is most likely not because the publishers always suck, it more likely has to do with different expectations. In my experience you often end up in a weird "work for hire" kind of relationship where the publishers only leverage towards the developer is the payments of milestones. As deadlines slip, the developers goal changes over time, from creating the best possible game to just staying in business. The publishers goal is to release a great game on time for a low budget. But as time progresses, if the development is on track, the power balance skews from the publisher over to the developer. The developer sits on the code, art and know how to finish the project. The Publisher might refuse to pay a milestone, but will then not get to release a finished game.

Developer vs. Publisher balance of power

Investment

What do you give up?
You give up equity. An investor will get some of your company shares. Many investors will want to have a seat on your board and the opportunity to influence your business decisions, or at least stay closely informed.

An investor often invests as much in you as your company

What do you get?
Cash in the bank. Freedom to make your own decisions (mostly). The ability to build something from the ground up. What it really gives you is time. Hopefully enough time to go to market, make some mistakes, adapt, improve and overcome. An investor often invests as much in you as your company

My experience
When I sold my game studio some years ago the buying company had several investors. I went from presenting monthly revenue and financial situation to my buddies over lunch, to travelling to London and reporting to a board of venture capitalists from various funds. A bit of a difference. While the access to the funding was great, it was really problematic that the investors didn't get the games industry. They had little understanding of development cycles, iterative/agile process and why the hell we weren't making millions of dollars yet.

As for Lavapotion, we have an amazing investor. The fine folk at Coffee Stain Studios understand exactly what we are working on. They attend our sprint reviews, give great feedback and advice, but never interfere with what we do. It is a relationship built on mutual respect. The funds give us the security to take long term decisions and always keep whats best for the game in mind. With that said, we are still open to work with a publisher, should we be able to find a great win/win-scenario.


To sum it up
In the end, it all comes down to how you want to work. Remember, many publishers started out as developers. What ever they learnt, you can learn too. But it takes time and effort. If you aren't interested in business development and marketing then a publisher is obviously a relevant option for you.

Whatever you do: Only sign contracts with people you could see yourself working with for a long period of time. Trust your gut feeling and consider how the other partner would react in stressful situation, because they will inevitably appear down the line.

And finally, here are some publishers that in my opinion really care about the process and developers:

Coffe Stain Publishing - Coffe Stain have created quite a few hit games themselves and are now taking on publishing with some very interesting titles signed. Lovely people to work with.

Raw Fury - Run by a savvy team with industry veterans. Offers very reaonable deal terms to the developers and really care about each project.

And, some investors who really gets game development:

London Venture partners - I've met these guys at lots of dev conferenses, they have been around for a long while and they get game development.

Indie fund - While I've only met a few of the people behind the fund, they have a transparent and very relevant business model, which I greatly appreciate.

Nordisk Film Games - Last, but certainly not least, these guys know game development, they know how to spot good teams and has already made some interesting investments. As a disclaimer I should mention that I have worked for them, helping them with analyzing potential investments.

And finally - Feel free to reach out if you want some friendly advice :)

Connecting Unity Cloud Build and HockeyApp (the slightly hackish way)

When we started our project at Lavapotion, we wanted an automated way to build our game to any platform we wanted as well as a seamless and easy way to give these builds to ourselves, stakeholders and testers.

With the number of great services that is available today, we decided to use Unity Cloud Build to build and then use a script that uploads all the successful ones to HockeyApp with the commit messages as the changelog.

Why Unity Cloud Build?

Unity Cloud Build got options to unit test, build and export to platforms like iOS, Android, MacOS and Windows. Which is all we need at the moment. They also have the options of choosing exactly what Unity Version to build from if you want, and they always have the latest as an option to.

It's super easy to connect with slack (for build notifications) and the setup is pretty straightforward. Disregarding that sometimessome builds fail for no reason, it's really everything we need at the moment.

Why HockeyApp?

Sure, you can share all your builds in Unity Cloud Build by creating a share link and send it to the people that needs it, but there's a whole manual process involved there and no easy way to restrict downloads to certain groups.

HockeyApp got distribution groups that you can add/restrict to any builds pretty much whenever you want. You can also notify people with an email with a changelog when a new build is ready. It's neat.

Connecting the two platforms. Why do we need it?

The obvious way to connect the services is to do it manually everytime. To break it down into a step-by-step instruction - take a look at the list below.

  1. Log into Unity Cloud Build
  2. Download all the successful builds for the platforms you want to upload to HockeyApp to your computer
  3. Log into HockeyApp
  4. Choose the app that's on the platform you want to update.
  5. Upload a new version
  6. Write/Copy-Paste the changelog
  7. Choose the Distribution Groups that should have access to this specific build.
  8. Decide if they should get an email notification.
  9. Repeat steps 4-8 for every platform you would like to update.

A philosophy that we strongly hold at Lavapotion is to reduce all the "screw-up-able" steps that can occur in our process and automate as much as possible. Not only is the list above extremely time consuming, but almost every step is error prone to all kinds of mistakes because there are so many manual steps.

So as a first step, we decided to reduce the manual steps to the following when there's a successful build.

  1. Run a script.

That looks way better, doesn't it? ;)

Setting everything up

You will need to do the following before we start:

  • Your project in a Git repository (for the automatic changelog)
  • Install Node Package Manager on your computer
  • Setup your project in Unity Cloud Build
  • Setup your applications in HockeyApp

The script we're creating will be written in Javascript and using a gulp job to perform the actual tasks of downloading and uploading, so we will need to setup the node project first.

Create a file called package.json at the root of your project and fill it with the following: 

(Replace the placeholder with your own information.)

{
  "name": "Super secret project",
  "description": "The best super secret game in the world.",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "gulp": "node ./node_modules/gulp/bin/gulp.js"
  },
  "repository": {
    "type": "git",
    "url": "<YOUR GIT URL>"
  },
  "author": "<YOUR COMPANY NAME>",
  "license": "<YOUR LICENSE>",
  "private": true,
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-download": "0.0.1",
    "gulp-hockeyapp": "^0.2.4",
    "gulp-rename": "^1.2.2",
    "request": "^2.80.0",
    "simple-git": "^1.67.0"
  }
}

This will setup a simple npm project. The devDependencies object explains what modules we will use in our scripts. The "gulp" part in scripts is optional - it's added so that we can easily use the locally installed version of gulp rather than a global one.

To install all of the devDependencies, open the command prompt (or terminal) and locate yourself at the root of the project and run the following command:

D:\YOUR_PROJECT_PATH>: npm install

After everything is installed, you can create a file called Gulpfile.js in your project root.

Gulp!

Given that your project is setup in Unity Cloud Build and HockeyApp, you can setup your Gulpfile.js like this and change the placeholders to your specific settings. This example will use an android build to upload.

'use strict'
var gulp = require('gulp');
var gulpDownload = require('gulp-download');
var rename = require('gulp-rename');
var request = require('request');
var git = require('simple-git');
var hockeyApp = require('gulp-hockeyapp');

var cloudBuildSettings = {
    apiKey: "<YOUR_CLOUDBUILD_API_KEY>",
    organizationID: "<YOUR_CLOUDBUILD_ORGANIZATION_NAME>",
    projectName: "<YOUR_CLOUDBUILD_PROJECT_NAME>"
};

var hockeyAppSettings = {
    apiKey: "<YOUR_HOCKEYAPP_API_KEY>",
    androidDevKey: "<YOUR_HOCKEYAPP_APPLICATION_ID>",
    devTeamID: <YOUR_TEAM_ID>
};

var tasks = {
    hockeyApp: 'hockeyapp',
};

var paths = {
    dist: 'dist/'
}

Downloading information about the latest build

Before doing anything, we need to be able to download the build information of the last successful build on Unity Cloud Build so that we can download it to our computer.

Luckily, Unity got a REST API that we can use to do this that is well documented.

Using the "List all builds" method, we can fetch the information that we need. Add the following function to your Gulpfile.

function downloadBuildInformation(pBuildTargetID, pOnCompleteCallback) {
    var baseURL = 'https://build-api.cloud.unity3d.com/api/v1';
    var options = {
        url: baseURL + '/orgs/' + cloudBuildSettings.organizationID + '/projects/' + cloudBuildSettings.projectName + '/buildtargets/' + pBuildTargetID + '/builds?buildStatus=success',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Basic ' + cloudBuildSettings.apiKey
        }
    };
    request(options, function (error, response, body) {
        var latestBuild = null;
        if (!error) {
            var builds = JSON.parse(body);
            var latestDate = new Date(-8640000000000000);
            for (var i = 0; i < builds.length; ++i) {
                var currentBuild = builds[i];
                var finishedDate = new Date(currentBuild.finished);
                if (latestDate < finishedDate) {
                    latestBuild = currentBuild;
                    latestDate = finishedDate;
                }
            }
        }
        else {
            console.log('Failed to get build information! message: ' + error);
            pOnCompleteCallback();
        }
        if (typeof (pOnCompleteCallback) !== 'undefined' && pOnCompleteCallback != null) {
            pOnCompleteCallback(latestBuild);
        }
    })
}

This function will download the successful builds available and return the newest one in the complete handler once done.

Downloading the build

After we get the information, we need to download the build to our computer. The build will be downloaded with a npm module called gulp-module. When the file is downloaded, we will return the file name in the complete handler.

Add the following function to your Gulpfile:

function downloadLatestBuild(pBuildInfo, pOnCompleteCallback) {
    if (pBuildInfo === null) {
        throw 'Cannot download build! Information is null!'
    }
    var latestDownloadFileName = cloudBuildSettings.projectName + '_' + pBuildInfo.buildtargetid + '.' + pBuildInfo.links.download_primary.meta.type;
    gulpDownload(pBuildInfo.links.download_primary.href)
        .pipe(rename(latestDownloadFileName))
        .pipe(gulp.dest(paths.dist))
        .on('end', function () {
            console.log('\nFinished Downloading Build\n');
            pOnCompleteCallback(latestDownloadFileName);
        });
}

Creating the change log

Since HockeyApp supports uploading a change log in markdown, we wanted a quick look on what's been done since the last build. At this point we don't need any curated or filtered logs, so we can just use the git commit logs for now (given that our commit messages are properly written).

To do this, you can add the following three functions to your gulp file. One takes the information available from unity cloud build and the other two gets information from your git repository and retrieves the commit messages.

function createMarkdownReleaseNotes(pBuildInfo, pOnCompleteCallback) {
    if (pBuildInfo === null) {
        throw 'Cannot get changelog! Information is null!'
    }
    var markdownChangelog = '#' + cloudBuildSettings.projectName + ' ' + pBuildInfo.buildTargetName + '\n';
    markdownChangelog += '**Branch:** ' + pBuildInfo.scmBranch + '\n';
    markdownChangelog += '**SHA1:** ' + pBuildInfo.lastBuiltRevision + '\n\n';

    var ignoreCommitIds = [];
    if (pBuildInfo.changeset.length > 0) {
        markdownChangelog += '## Recent Changes \n\n';
        markdownChangelog += 'If installed, this build will: \n';
        for (var i = 0; i < pBuildInfo.changeset.length; ++i) {
            var message = pBuildInfo.changeset[i].message;
            markdownChangelog += '* ';
            markdownChangelog += message;
            markdownChangelog += '\n';
            ignoreCommitIds.push(pBuildInfo.changeset[i].commitId);
        }
    }

    var gitLogSettings = [];
    var maxHistoryLogs = 50;
    gitLogSettings.push(pBuildInfo.lastBuiltRevision);
    gitLogSettings.push(pBuildInfo.scmBranch);
    getGitLog(gitLogSettings, function (pLogArray) {
        markdownChangelog += buildChangelogHistoryFromGitArray(pLogArray, maxHistoryLogs, ignoreCommitIds);
        pOnCompleteCallback(markdownChangelog);
    });
}

function buildChangelogHistoryFromGitArray(pLogArray, pMaxHistoryLogs, pExcludeShaArray) {
    var changeHistory = '';
    if (pLogArray.length > 0) {
        changeHistory += '\n## Change History \n\n';
        for (var i = 0; i < pLogArray.length; ++i) {
            var message = pLogArray[i].message;
            if (pExcludeShaArray.indexOf(pLogArray[i].hash) === -1) {
                changeHistory += '* ';
                changeHistory += message;
                changeHistory += '\n';
            }
            if (pMaxHistoryLogs !== -1 && i >= pMaxHistoryLogs) {
                break;
            }
        }
    }
    return changeHistory;
}

function getGitLog(pGitLogSettings, pOnCompleteCallback) {
    git().log(pGitLogSettings, function (err, log) {
        var logArray = null;
        if (!err) {
            logArray = log.all;
        }
        pOnCompleteCallback(logArray);
    });
}

Uploading the build to HockeyApp

To upload the build to HockeyApp, we are using a package called gulp-hockeyapp. It does exactly what we need and you can also decide whether or not you should send an email notification to your HockeyApp distribution groups.

Add this function to your Gulpfile.js that will use all of our previous functions and once everything is done, upload the build to hockeyapp.

function downloadAndUploadToHockeyApp(pBuildTargetId, pHockeyAppID, pOnCompleteCallback, pNotifyAll, pTeams) {
    downloadBuildInformation(pBuildTargetId, function (pBuildInfo) {
        downloadLatestBuild(pBuildInfo, function (pDownloadFilename) {
            createMarkdownReleaseNotes(pBuildInfo, function (pMarkdownChangelog) {
                var options = {
                    id: pHockeyAppID,
                    apiToken: hockeyAppSettings.apiKey,
                    inputFile: paths.dist + pDownloadFilename,
                    notify: pNotifyAll === true ? 2 : 0,
                    status: 2,
                    teamList: pTeams,
                    notes: pMarkdownChangelog,
                    notes_type: 2
                };
                console.log('\nUploading to hockeyapp...\n');
                hockeyApp.upload(options).then(
                    function (response) {
                        console.log("Successfully uploaded build to HockeyApp!");
                        pOnCompleteCallback();
                    },
                    function (err) {
                        throw err;
                    }
                );
            })
        });
    });
}

Creating the Gulp job

By now, we have all the functions that we need. The only thing left is to create a gulp job that uses the function that we just created.

Add the following gulp task to your Gulpfile:

gulp.task(tasks.hockeyApp, function (done) {
    var notifyByEmail = false;
    downloadAndUploadToHockeyApp('android-dev',
        hockeyAppSettings.androidDevKey,
        done,
        notifyByEmail,
        [hockeyAppSettings.devTeamID]);
});

That's it! To run this, just use the following command at the root of your project in the command prompt or terminal to set the job in motion:

D:\YOUR_PROJECT_PATH>: npm run gulp hockeyapp

Ending Notes

As the title suggests, there is much room for improvement with this script. You could split the methods into several files, create unit tests, add better error handling or even use a build computer with jenkins to automatically poll when a new build is successful and run everything automatically.

But at this moment, this is good enough for us. We removed some manual steps and saved everyone in the team some time. We hope that this can be of use to some of you as well!

If you need to have a look at the Gulpfile in it's entirety, you can find it here.

 

Starting over again, doing it the right way

It is a rare treat indeed to get to start on a new game. I started a game development company along with some buddies several years ago. We created advergames, facebook games and eventually mobile games. We produced over seventy games spanning various genres. Some of them did ok, a few did amazing but most of them never got much attention beyond a marketing campaign. Never really having funds to give every game the time and love it needed was frustrating. Eventually we sold the company and moved on with our lives.

And here we are again. Starting a new studio and working on something we passionately love - Strategy games! With funding from the amazing team at Coffee Stain Studios and a team of great developers. This time we are doing things the way we always wanted. Let me share some of our core beliefs.

We believe in SCRUM
It works well for us. SCRUM helps us with keeping our development in line with what our stakeholders expect and making sure that we do not loose sight of our target. It is also great to have a methodology to fall back onto when things are shaky. Being agile within constraints is a great thing.

We believe in work/life balance
This means that we do not work overtime. We take care to plan our days carefully and we make sure to allow both flexibility and structure, where needed. We work together, but we also play games together and enjoy our very Swedish fika every day. We encourage ourselves to work out, stay curious and having fun at work.

We believe in building something long term
As we are driven by passion, we want to maintain it and help it grow. We discuss very openly about personal goals as well as company goals. How can we align targets and how can we create a workplace where we enjoy our work each day? Building great games take time and if we enjoy that time, then better games we are going to create.

In the end, it all comes down to what we want to do with our lives. We choose to work with games because well, we love games. Creating games is a labour of love and for us, the process is equally as important as the result.