On Monday morning, I began the week at the studio, where (after a while) I copied a few scripts over to a new Unity project for prototyping the new version of the movement, removing unnecessary sections of the code. I then continued working on the script for the new movement, generally referring to how I was doing things with the old version and considering the differences I’d need to account for. Then, in the afternoon, George sent me a Unity package that contained the scene for the brass civilisation, as well as all of the necessary assets. When I imported it into the project I’d made (with all of the game objects placed with the same properties as the older movement prototypes), it imported a blank scene with the same name as the scene I was working with, overwriting it and completely clearing a chunk of my work. In future, I’ll have to be sure to immediately rename any scenes I’m working with if I’m to be importing or exporting any packages. Not only did it clear the scene I’d been working with, but the new scene that George intended on giving me had inconsistencies with its source version, with the bounce lighting in the wrong place and all of the colliders in the scene moved to blank, unnamed game objects with reset transform values, separate from the objects they’re meant for. This meant that none of the mesh colliders were even assigned meshes, and I couldn’t really locate what the colliders were meant for due to the reset transform values. Basically, everything was wrong, but I at least didn’t lose the scripts I’d been working on (as they weren’t overwritten).
The only explanation for the inconsistencies that we could think of was that George was working with, and exporting from, a newer version of Unity than I had, so I had to update mine for the sake of parity. We also determined that we needed to set up version control and have a disposable test build to make sure things don’t break when importing packages in future. As Unity required nearly as much storage as I had left on my SSD, I wanted to back all of the Unity projects up, in case uninstalling Unity or transitioning them over to the newer version irreversibly ruined them, though Adam had my flash drive and wasn’t in. Thankfully, Bernie lent me his portable HDD to back my work up, which was much appreciated. I briefly spoke to George about which work he wanted me to focus on for the day (as this whole situation had disrupted my work on the movement system), and he said to prioritise setting up GitHub for version control. I quickly gave everyone the login details for the social media accounts, uninstalled Unity 2018.2.18f1 and downloaded Unity 2019.2.0a4 using Unity Hub (by George’s recommendation). I then signed up for GitHub Education, which was surprisingly very easy to do.
After this, I spent a while talking to Bernie about how I wanted him to be drawing the waves for me to code them, showing him how I plan it all out on Desmos Graphing Calculator, and explaining that he can either draw the waves fully (not having to worry about them being made up of sine waves) or simply mark where he wants the peaks and troughs to be. Then, after updating some account information on GitHub, I downloaded and set up GitKraken (to act as a front end for our GitHub-based version control). Afterwards, with Unity 2019 installed, I tested that the mechanical prototype works well with it, and it did, having seemingly changed nothing about it. Then, Ella and I described to Bernie the need for a satisfying number of beats in the loop that he was working from, describing the numbers we’d find satisfying based on the song’s time signature (settling on 32 beats), and I said that I’d intended on mapping out how long each portion of the wave is in terms of beats (declaring each beat as a multiple of π). After that conversation, I imported George’s package into a new, disposable Unity project, and everything seemed to be imported perfectly, meaning the issues from earlier were almost certainly due to a discrepancy in Unity versions. Bernie then showed me the grid that he was making to draw a wave on, asking whether it’d be fine for the spaces between fixed intervals on the x-axis to represent beats, and I explained that I’d rather the fixed intervals themselves be the beats.
At this point, I deleted the disposable Unity project to test out the package importing, and created a new project for the vertical slice of the brass civilisation, so that I could use it as a test case for the GitKraken implementation. Eventually, I went through all of the steps of a tutorial for implementing a Unity project’s version control with GitHub via GitKraken, ending up with the project fully implemented with version control support, and that’s a process that’ll take a bit of getting used to. I then had a chat with George about the environment for the brass civilisation, speaking about where the camera would be and where it’d face, as well as the locations for the jazz player and the starting position of the player. Then, I made a new scene for developing and testing the new movement system, using the initial white box for the violin civilisation (before testing the movement with the new, more complex settlement), copying over the values and object placements from the original movement scene. Bernie also gave me the wave that he’d drawn (which you can see below), so that I could program it into the mechanical prototype project. At this point, I headed home, feeling unhappy and struggling to get any work done. I started translating Bernie’s wave into sine wave values with Desmos Graphing Calculator, but reached a point of feeling incredibly unhappy and couldn’t continue, heading to bed instead.
On Tuesday morning, I headed to the studio again, and after trying to think about ways to implement the movement system, I felt like I’d be able to make more progress translating Bernie’s wave into values instead, so I continued with that. There were some awkward sections of the wave that took far longer than other areas to find their wavelengths and offsets, so that was a bit of a hassle (I decided to try simplifying any awkward areas as much as possible later on). For a while, we then had a discussion about the project with James. After we explained what we’d been working on and towards, James explained how he felt about the game. He said that if the player moves onto the next environment after each civilisation’s single interaction, there isn’t much point in having a large environment, and he told us that there needs to be “more game” in the game. He suggested that the wave matching minigame wasn’t actually adding anything to the game, and said that it’s no different from standard dialogue trees, so we should consider scrapping it entirely and doubling-down on our game being a linear traversal of environments. Also, questioning why we’re targeting such a large scale, James said that it’d make sense to have a number of different environments if the musical interaction mechanic is different for each area, but if all interactions use the same line following mechanic, then he said that he wondered why they couldn’t all be in the same place. He suggested cutting areas to make sure we can design a different interaction for each of the areas we have, as he felt that the interactions aren’t meaningful if they’re not distinct. James told us that we should come up with a meaningful interaction or ditch it entirely, and when I said that our environments weren’t designed to support exploration, he said to just focus on coming up with ways to establish meaningful connections. You can see all of my notes from the discussion below.
After speaking with James, we had a team discussion to determine what we’d be working on and how we’d respond to James’ feedback. While you can find all of my notes from the discussion below, we essentially decided that we’d finish up what we were working on over the rest of Tuesday and Wednesday, so that Thursday and Friday could be used to design new mechanics and refine the wave-based interaction. George said that if the harmonisation interactions are the main part of the game, they need to feel great, so we could either continue to work with the wave mechanic as it was, completely redesign it or design a handful of small mechanics, and it was the last option that we settled with. We also took into account the possibility of scrapping the mechanic entirely and making the game a “walking simulator,” but we agreed that it wouldn’t make for a good one. After lunch, I spent some more time working out the values for Bernie’s wave before we headed upstairs for a lecture.
Our guest speaker for the day was the artist and designer Brendan Dawes, who spoke to us from his home over a Skype video call. While not a games designer, Brendan has designed a number of interactive experiences, and his general advice as an artist and designer was still very applicable to our practice. He talked us through his work, his processes and a number of general tips to help our creative processes, and it really was a great talk. While I won’t list everything he said here, you can find all of my notes below. Some of the main things that he said were to make sure we do a lot of small, personal, experimental work, holding onto these experiments to use them later; to make sure we revisit the “scarps on the cutting room floor,” allowing for beautiful mistakes to happen and not worrying about being inexperienced at first; to put our personal work out there for people to see and use; to properly document our work and our creative processes; to make ourselves memorable to clients, as well as to show them a level of confidence; to make our own tools to work with; to not worry about showing things that aren’t perfect to you, as others might like them, and to generally avoid worrying about things looking ugly early on in a project; to create environments and systems for people to play within, and be surprised by what they do with them; and to allow ourselves to be bored, as ideas come from boredom. I also asked him whether he feels it’s best to refine old, experimental code or just reuse it and treat it as serviceable, and he said that he likes to constantly improve his code, saying that the experimental snippets he creates are like bookmarks of ideas, and agreeing that there’s a satisfaction to honing the ideas.
After the talk was finished, Bernie sent me the music to go with the wave he’d drawn, and I saved it in my documents before continuing to generate the sine wave values for the wave. While I was doing this, Bernie had been having Sid test the different prototypes for the game’s wave mechanic, so Bernie spent some time explaining to me the feedback that Sid had given. He said that Sid liked the score being displayed, and it made him want to keep replaying to do better, but that could have been down to the minimal nature of the prototype, with a lack of visual feedback and context. We then discussed the possibility of allowing the player to replay interactions after successfully synchronising, accepting that score isn’t what the game is about, but that there are people who’d want that from it. After this, I resumed translating Bernie’s wave. Then, I spent a while speaking with Bernie and Sid about how the play window of the wave could be adapted during interactions, wondering whether we should have a positive feedback loop or a negative one. We questioned whether we should focus on factoring-in the player’s gradually increasing skill level, or instead on representing the building of understanding. Bernie suggested that the window could begin as increasingly small in each interaction, requiring to be gradually increased more each time, factoring-in both the increase in player skill and the idea of building a level of understanding. After this discussion, I headed home.
At home, I continued translating the wave into values, and eventually finished doing so (it genuinely took ages, due to the complexity of the wave), at which point I began programming the values into the mechanical prototype’s wave management script as a new wave. It took some time, but I eventually finished doing this and tested whether the wave was being drawn properly. It wasn’t. Instead, it was being drawn at inconsistent intervals, and all of what was drawn had positions of zero, and I assumed that all of this was because a number somewhere was being set to infinity. After looking through the code briefly, I gave up trying to fix it and headed to bed, accounting for the fact that it was pretty late at that point.
On Wednesday morning, I headed to the studio and continued trying to fix the error that was preventing the wave from working. I wondered whether it could have been an issue with too many calculations happening at once, so I switched all of the calculations to check the wave’s current value against a series of ranges (to determine which values to apply to the sine wave) to a single calculation, stored as a variable. Then, I nested the if statements into four initial if statements, so that I could cut down on the number of conditional calculations, and when that didn’t seem to affect anything, I nested the nine if statements within each of the initial four into sets of three if statements, which also changed nothing. After I’d spent a while looking over the code and finding nothing that would be logically erroneous, Adam came into the studio and helped me out. He had me comment-out portions and add debug log messages into parts to find where the errors were, and when we saw that it generally wasn’t working, he helped me to check that I’d typed all of the condition ranges correctly according to my initial notes (which I had). When I saw that there seemed to be no logical reason for the values to not be setting properly, I decided to try to add an ‘f’ to the end of the few numbers that weren’t commented-out, and this change made that portion (being the first part of the wave) work. In hindsight, this was because I was dividing numbers that were classed as integers into non-integer values, so they had to be defined as floating point values (even if the variables were defined as floating point numbers) to be properly divisible. Then, before lunch, I re-enabled the code that had been disabled, and began adding ‘f’s to the end of every integer I’d declared a value as.
After lunch, I finished adding all of the ‘f’s, and the wave was mostly fixed, aside from one of the areas that wasn’t lined-up vertically properly. After that, I started feeling extremely unhappy, and wasn’t capable of doing anything for a while. Adam then came in and told me that, as well as the visible play window growing through synchronisation, the wave’s shape could get gradually flatter and easier to match. He asked whether that would be possible to program, and I said that it would be. Then, for a large chunk of the afternoon, I continued to be incredibly unhappy. With some (much appreciated) help, I ended up feeling substantially less unhappy, and eventually headed home from the studio. After having dinner, I compared the area of the wave that wasn’t lined-up properly against Bernie’s drawing to determine its range. I found that I was missing the sine wave values for a portion of the wave, so I used the Desmos Graphing Calculator to calculate the values for that portion, and after adding these values in, the wave worked fine. I then set the wave sizes of the different waves in the initial value setting subroutine of the wave management script, so that I could set them individually without just adapting the value in the inspector. Then, I spent some time thinking of how I’d program the trails of the waves, taking notes of what I thought of on my phone. Eventually, I found that I felt too exhausted to be able to think straight, so I headed to bed.
On Thursday morning, I went to the studio and continued thinking about how to implement the wave trails. By coming up with values on the whiteboard for the loops and conditions I’d thought about the prior night, I tried to nail down patterns and values, coming up with the idea of an incrementing value that displaces the points of the trail away from the cursor when the wave is out of range. Once I’d documented my thoughts and realisations on my phone, I got my lunch, after which I continued to think everything through. I figured-out a few more details for the conditions for setting values, but still had some specifics concerning the actual values being set to determine. However, I felt it’d be best at this point to get on with the planned mechanical design work with George, saving the rest for afterwards.
George and I discussed ways in which to approach the mechanical design, and we decided to look for consistent elements to utilise across the musical interactions. We settled on differentiating different characters by colours, and representing synchronisation through the gradual blending of these colours. We also decided upon having a consistent It/Tag element, where the player would first synchronise with the other character, and then the other character would synchronise with the player, following the player’s patterns. George felt that this could happen with the wave mechanic by having the player’s wave take the lead after synchronisation, and have the character’s wave interweave with and try to match the player’s, gradually doing so. We also determined that we’d have different mechanics inspired by different shapes and motions. Since the wave mechanic was about vertically responding to a laterally moving wave, I felt that other movements could be represented as well. When I think of sound, I don’t just think of the standard sine waves, but also circular ripples, and the idea of a circle felt to me like it kind of matched the rounded shapes of brass instruments (and their circular bells). I came up with the idea of the player having to move a cursor around the circumference of a circle in order to bounce/deflect shapes that fall towards the circumference from the inside and outside of the circle, timed to land on the beat and encourage the player to do both gradual and wide, rhythmic motions to bounce them. For “Triangle Man,” I didn’t want to be so obvious as to literally use triangles, but while thinking of triangles my head immediately jumped on the idea of a triangular grid. I then thought that both the player and the character they’re synchronising with move around the indices of the grid constantly in-time with the beat of the music, first extending one length in a direction to occupy two triangle sides, and then having the back end catch-up to occupy a single side before moving again. However, I couldn’t decide upon whether the player should have to catch the other character, though I did know that I wanted the player to be doing the same patterned motions as the other character (as the other character constantly repeats the same sequence of directional movements).
After we’d discussed our ideas, Adam came into the studio, we expressed our ideas to him and he gave us some feedback. The main thing that he wanted us to consider was how the mechanics could be integrated with the world, so that it wouldn’t feel like the traversal and the synchronisation are two separate experiences (like in a minigame collection, such as Mario Party). We already considered that we could have the wave matching mechanic be represented as wind in the air, and Adam suggested that the triangle grid mechanic could be represented by fireflies or stars that collect when the “Triangle Man” hits his triangle. When I suggested that the circular bouncing mechanic could utilise the clock face of the brass civilisation’s clock tower, Adam felt that it could be better to consider what could be done with the clock tower’s bell. The point was that he felt that the synchronisations should be represented as shared spiritual experiences, reflective of the connection that’s meant to occur during them, and I feel like that makes sense. Adam also drew a number of thumbnail sketches as we were explaining our ideas to him, and these sketches can be seen below. Once Adam left, George and I looked at Bernie’s notes and mechanical designs that he’d compiled and sent over, and spoke about how we should go about splitting-up songs for the interactions (deciding to have a fixed opening for getting to grips with the mechanics, a centre that loops until the player has synchronised with the character and a fixed final section in which the player is free to do what they like and the character synchronises with them), as well as defining a number of universal rules for the interactions. George then headed home, and once I’d finished reading Bernie’s notes and looking at his designs, I did the same.
After I’d continued thinking about how to implement the wave trails, I eventually felt that I had enough things considered to begin programming them. However, I first needed to program the looping of the waves, so that I wouldn’t have to reprogram the trail creation when I did. Therefore, I implemented a couple of Booleans to check and signify whether a wave is meant to loop and, if so, whether it already has. The looping completely broke Bernie’s wave, so I went back over the code, added mentions to the wave offset value, added brackets for the denominators in remainder calculations and found a case in which I was multiplying where I should have been calculating a remainder. Bernie’s wave was now looping, but it wasn’t displaying anything for the first cycle before it had looped, which I fixed by removing wave offset additions from the remainder calculations. I also made it so that the score and cursor management scripts accounted for looping, and moved the score value resetting from the score management script to the wave management script (so that it could be reset at the same time as the wave/loop). With everything seemingly working as intended, I then made the cursor only move when the wave is being played. Then, after checking and appending my trail implementation notes, I made the cursor management script store the current vertical displacement value of the character’s wave, so that this value could be used to create the trail. Then, I followed my notes to program the trail drawing for the player’s trail, and copied the code for the player’s trail to create the character’s trail, calling both of the subroutines in the cursor management script (to make sure they were being called in the correct overall order). Then, after determining the trail values as initial values in the wave management script, I tested whether the trail generation was functional. It wasn’t working, and after a couple of tweaks (factoring-in how it didn’t look like the number of points in the line was increasing), I took note of the time and headed to bed.
On Friday morning, I went to the studio and continued trying to fix the code for the trail, placing debug log messages within conditions to see whether they were satisfied. It seemed like they were being satisfied too much, with conditions to increase and decrease the number of points in the trails both being satisfied, cancelling each other out. I made the line draw by inverting a calculation for the condition for reducing the number of points, but it still wasn’t correctly setting the x positions of the points. After I helped Fred out a bit with his project, Mind the Film came into the studio and began their workshop session on documentary film production. When they went around the class asking people what their projects were, I explained what our team’s game is. Then, they spent some time explaining the process of film production, going over a range of topics and explaining a lot of specifics. They also came up with and explained a number of potential B-roll sources for our documentaries. After lunch, I briefly looked at the code, removing the need for the wave to be past a certain point for the player’s trail to be drawn. Then, Mind the Film resumed their workshop, demonstrating and explaining how to conduct interviews, and showing us various post-production techniques for colour correction and the like. Throughout the workshop, I took quite a few notes, so rather than going over everything that was explained, you can see all of my notes below. I appreciated the duo showing up to help us for the day, though, even if I’d started to feel quite unhappy during the afternoon.
Once Mind the Film had finished speaking about the post-production process, George and I explained our ideas from the prior day to Ella and Bernie. Neither of them opposed any ideas, but they wanted to see everything working to get an idea of it all, especially having reservations about the triangle mechanic. Then, for a while, we explained to Bernie how the coloured ripples that would be generated in the overworld by the player and NPCs (gradually blending colours towards a midpoint if they play together) would work. Adam then came to us and reiterated what he’d spoken to George and me about the day before. He also prompted us to crack-on with social media posts and sorting out a website or development blog for the game, while I was kind of scanning the trail management code for potential issues. I was still feeling unhappy, and decided it’d be best to head home. After looking-up the best ways to approach hashtags for social media, I came up with some messages and hashtags for Ella to post her image to the game’s accounts with (though she’d already come up with a message for the Instagram post). Then, I continued trying to fix the trail code, adding a condition to prevent it from referencing an index in the trail’s points that might not exist. However, I ended up feeling extremely unhappy and getting nothing else done before heading to bed.
My work didn’t resume until Saturday evening, when I thought of (and took note of) a different way in which to handle the trail generation code. I considered how the values of the different positions in each trail would have to be set from left to right while playing (so that values aren’t overwritten before they’re passed on), and from right to left when not (simply adding the counter value of the for loop to the displacement value I’d mentioned earlier, multiplying all of this by the x distance between points for the x value, and keeping the y value the same). I then programmed this implementation for the player and tested it, and it worked like a charm, so I copied the player’s trail code over for the character’s, changing variables where necessary. I then made it so that the the character’s trail is only created when the wave is in the correct range for the trail to be generated, adding conditions to set the value of a Boolean. The trail was being successfully created, but at a different rate to the movement of the wave, which created a weird discrepancy between the wavelengths of the wave and the trail. Also, it was moving in the wrong direction when the wave was out of range, which I fixed by remembering to subtract the x position from the starting position of the trail. Then, I prevented the code from referencing points in the lines that don’t exist, made the trails reset their numbers of points when the current wave is changed and adjusted the left position of the trails for Bernie’s wave, so that it reaches the edge of the screen. After making these changes, I disabled the cursor’s sprite renderer to see how it all looked when it was just the wave and the trails, and I thought it was pretty cool. After this, I called it a night and headed to bed.
This brings me to Sunday, of which I spent a chunk writing this blog post. In fact, as I write this, it’s currently the early hours of Monday, but I want to make sure Monday’s clear to be working on the trails and general things associated with the wave mechanic. The plan for the week is to refine the wave mechanic prototype in preparation for Monday’s testing session (to which people will hopefully show up…), and then to generally chip away at the movement mechanics while focusing on getting the Reflective Journal work sorted (since we’ve cast this week aside as a team to get that out of the way). This is unless I’m told to work on making functional tests for the other mechanics, or on further refining the wave mechanic, but I suppose I’ll see how it all goes. I’ll be sure to let you know in next week’s post.