Dev Diary 38: Subtitles, Frustrations & Playtesting

Currently, the state of Lab 77 is as follows:

  • 200 of 205 bugs have been squashed. All five remaining bugs require more testing.

  • Music and sound design implementations are being worked on.

Starting off where Dev Diary 37 left off, the implementation of subtitles. This started off with some further research into Wwise and implementing that through code in Unity. Unfortunately, this proved a complex challenge as I discovered more and more how lacking the Wwise documentation is. As a developer, it is frustrating when the official documentation does not give you any information of how to use methods beyond saying something along the lines of "This is a callback function, it is used to call back an event". If anything, that line is more informative than the documentation, and the forums are not much better. Granted, there are some answers but there is rarely sufficient information to implement said answer.

Eventually, I was able to find a decent option for a callback that I could use called AK_Duration. However, implementing this was more of a headache than it should have been, largely due to the incredibly lackluster Wwise documentation which meant that it took too much time to find out how anything worked. This meant I spent a lot of time going in circles between forum posts and such, all of which had different pieces of the puzzle but none of which had the full set. Thankfully, after some help I was able to implement the AK_Duration callback and get the fDuration value which is the time in milliseconds, for some reason, as a float.

In case anyone else runs into this issue and wants to solve it in code, what I did was this:

Image of the Callback function written in C#.

Now as far as I was able to tell, in_cookie does nothing but is still needed as Wwise expects it to be there. For this specific use case, what you need is in_type, which is the type of the callback, and in_info which is a C# object that you'll want to cast to AkDurationCallbackInfo for this specific use case. Admittedly, the following if statement is not necessary for my particular implementation as I only intend to use the AK_Duration callback, however it is not impossible that I change this in the future. As such, I wanted to make sure I don't create problems for myself if I do make changes. This brings us to the data I wanted, t, which is fDuration from in_info divided by one thousand, as it is in milliseconds and I need it in seconds due to using Time.deltaTime for the timer. I also decided to add 0.5 seconds, to give you a bit more time to read the subtitles. Admittedly, I may end up tweaking this number after more testing but that is a problem for future me. This ended up being a really nice implementation that took way too long to implement.

Additionally, the decision was made to move the randomisation of the voice over lines to be handled in code. This was done to simplify the process of displaying the correct subtitles, and as figuring out how callbacks worked took so long I didn't want to go through that process again in case I did something wrong with another callback. Doing this meant having to re-do some work both in Wwise and in code, which I normally am strongly against doing, but in this instance re doing it got me out of a sunk-cost fallacy. As a point of note, the intention is to have most of the voice over lines randomised according to the difficulty the player choses. This is to add flavour to the game world and expand a bit on the lore of the game, though most of the lore can be accessed through the collectible notes. I should also mention that the voice over does not read from the notes, as that would have been too much voice over, and likely would have messed with the flow of the game too much.

After the Wwise implementation was complete I moved on to the next part of my to-do list: testing and data gathering. I realise I haven't talked much about the setup for this before, but I have a branch on GitHub (admittedly this branch is in it's fifth version) that I use for setting up a playtesting version. This simply adds a little bit of code to the manager that records the number of placements per level, on easy mode so as to have unlimited available placements, and then writes that data to a CSV file after I click the "Exit" button on the main menu. This setup is very simple to make now, hence the fifth iteration of the branch as mistakes were made in the past, and it allows me to easily gather the data I need though I still need to set aside the time to do it.

Thankfully, I remembered to properly record the data after my first playthrough this time (for reference, see this). I also "only" recorded five bugs, four of which were really minor things and one of which was the complete lack of any audio in two levels. I did worry that this had something to do with the subtitles as it first happened on the first randomised voice over instance, but as it didn't happen on any other voice over instance in that playthrough that theory was nullified. I did manage to resolve this issue quite easily though as I had managed to forget to add the AkAudioListener component to the main camera in two scenes, which had caused the lack of audio. Admittedly, I should have caught this before making the build, but at least it is resolved now. After doing two rounds of playtesting I also decided to make yet another minor level redesign of level 52 to improve the flow of the level and thankfully this did not mess up the data as the level is still completable with the same number of placements.

Going forwards I have a few more items left on the to-do list:

  • Create a final playtesting version

    • Use that version for final tests

  • Complete the trailer

  • Resolve any outstanding bugs

  • Release the game.

  • That is all for this Dev Diary, more to come in two weeks time.

-Olav

P.S. If you ever want to leave comments or feedback for these dev diaries, they do also get posted to Patreon and Reddit.

Next
Next

Dev Diary 37