Cutscenes, subs and… stairs

Two months of madness

Hi everyone! we were busy as hell since the last update, focused on solving different tech issues and including key features to advance in the game development.

This post will be less “flashy” than others because some things related with animations and designs enter the spoiler terrain. Either way we made some improvements that Carlos will summarize, explaining what’s been done in the coding department during this time. Mainly we’ve made progress in the cutscenes area, which are a key to achieve our vision of Paradise Lost, and we’ve also hit a very hard wall with something that didn’t look that difficult to begin with, stairs. Here we go.

Importing sprites

Until now every sprite we made I imported into Unity manually, I grew tired of this so I made a tool to import these sprites, saving us a lot of time in the process. The importer is very simple and ad hoc, we pass the importer a folder and all the sprites inside this folder are named so the tool knows everything needed to cut them into the correct number of frames, the width and height of these frames is also set on the name. For example the file fall_9_10x10 would be imported as a sprite named fall, cut it into nine frames of ten by ten, but a file named recovery would be imported as a single sprite with that name.

 

Additional options let us import the sprites as Advanced Textures and set a Packing Tag shared by all the sprites inside the folder.

Cutscenes and subtitles

In February we bought Cinema Director from the Unity Asset Store, a tool to make cutscenes inside Unity using timelines and actions, with the ability to preview the cutscene outside play mode. At first this sounded amazing, but the asset was made with 3D in mind and 2D was not supported. Thankfully the asset came with the source code, so the first week was spent learning the asset and customizing it for our project, with pretty good results.

The most important changes made to the asset were the inclusion of a MoveTo action to the timeline, which lets us move any 2D entity using our previously built movement components, and the Subtitles action, which writes subtitles on the screen using our DialogueManager. Also MoveTo gives us a good estimation of the time that’s gonna take the entity to reach the set position, even on preview mode, which makes life so much easier.

To give you an idea of what we would be doing to move a character without the addition of the custom MoveTo action, we would have to add an Animation track to animate the entity, an Audio track for the steps, having to synchronize the sound with the animation with the same precision as the code does, and a Translation track to actually move the entity.

 


 

How to move a character inside cutscenes with the original asset. As you can see there are too many steps to make a simple cutscene and a velocity curve is needed to reproduce the character’s movement, which is bothersome and not very precise.

 

How to move a character inside cutscenes with our customized actions. With a pair of clicks the character is moving with the same pace and motions as in-game.

Subs

About the subtitles, we wanted to add ones similar to what you can see in the trailer, with only minor changes to improve them, this was easier than expected and now we have a DialogueManager, and the previously mentioned custom action inside Cinema Director to add subtitles to the timeline. Its functionality is very straightforward, first we create an XML with the actors and the lines they say, then we can either run the subtitles by code or setting a new action inside Cinema Director, always specifying duration and the XML path.

 

On this example both dialogue animations have the same length but the second one needs to show more words. The DialogueManager will write the subtitles at the right speed given a certain duration -we tied speed to duration to properly synchronize dialogue with animations-.

This enhancements give us the possibility to portray a more cinematic look to the scenes, pairing the texts with the length of each animation and avoiding the classic dialogue-skip scheme with breaks, typical of this kind of games.

Stairway to hell

If someone asked me what I thought was going to be really difficult to code, I would never have said slopes. Probably some of you remember the designs made by Enol and posted in the update #32. He designed a stair system based in Subject W’s pivot (wich is wider than the human one) and added perspective to them, giving the feeling of depth necessary to avoid the character standing in the air.

 

I’ve spent a great part of the last month trying to make them work, and they’re still a little bit clunky. The problem was that the player, Subject W, it’s a not kinematic entity and responds to real physics, this combined with very steep stairs and all the code behind which makes the player move, jump, land properly, pass through platforms and so on, made what looked like a simple task into a nightmare.

It’s not the first time we’ve had problems because something done months ago doesn’t work with something that you never thought would cause issues, these things happen sometimes, but this time we made a really big mistake regarding planification. Whenever I’m working on a certain mechanic or system for the game I try to design it with every feature in mind, and I don’t start another task unless it’s finished. But I didn’t realized we were adding slopes when I made the movement components.

Certain aspects of the movement and the numerous possible collisions needed to be changed to work with slopes because they are a very particular case.

The math behind the slopes is, in theory, simple enough to implement. This first image shows the forces that are applied to Subject W at any moment, obviously if not moving or jumping its velocity is gonna be zero.

With this information we can deduce that to counteract the gravity the terrain needs to apply a certain friction to the velocity on x of Subject W. This friction is also modified by the normal of the slope in relation to Subject W, because a slope rotated 45 degrees is not the same as one rotated 10 degrees, which is much easier to climb.

In the end the velocity on x for Subject W while on a slope at any given time is:

velocity.x = velocity.x – (hit.normal.x * friction)

And this is the final look of the colliders applied to the stairs:

 

This wasn’t the only issue to tackle, we also faced the need to design the input around this element, one easy to understand for the player. So far this is the solution that we came up with:

 

If you walk straight Subject W will obviate the stairs, passing through them.

If you jump in front of a stair flight Subject W will land on it.

 

Walking, crouching, running and jumping work the same way as they do on the ground.

 

If you move towards the bottom of the flight floor level the character will continue moving on the ground.

 

If you stay in a half space landing and want to go up you’ll have to jump.

 

If you stay in a half space landing and want to go down you simply move the character in that direction.

 

You can also get down of a stair flight by pressing down+jump.

___

This is the best system we came up with, considering the character movement and the gameplay mechanics already designed and used. We’ve eluded the use of diagonals because they do certain movements in Paradise Lost (if you press down+left Subject W will dock, and adding a new/different feature only for the stairs will be confusing for the player). We are considering to add visual prompts to help players notice the actions that they can make in certain spots of the stairs, but they’ll probably obstruct the designs and look a little bit overloaded.

As you can see development issues can appear anytime, and with a complex game like this with tons of features that involve specific game mechanics is easy to overlook stuff or fall into something that you thought will be made in no time.

In any case we hope that you liked the update and also be of interest to other developers that are having similar issues with their projects. Till the next one!