Don't wanna be here? Send us removal request.
Text
Project 2 Part 6 - 3D Modelling in Maya
With the level greyboxed out I need to start creating assets that I will use to populate the level to help create a more authentic feel of Victorian Whitechapel. I am going to do this using modular assets so I can create as much variety as possible with the minimum amount of time spent creating assets. This is because 3D asset creation can be time-consuming, especially when it comes to UV-ing and texturing so the more modular I can make the environment the quicker and easier it will be to assemble it.
I have begin in Maya creating a couple of buildings with modular dormer windows for the roof section as well as a couple of different windows and a door. The progress so far can be seen below. I will add a few more variations on the windows for the body of the buildings and I will need to create another couple of buildings and probably some walls and a gate to separate out the back-court areas to round everything out.
Once I have a decent amount of assets modelled up I will begin the process of UV-ing the individual components and importing them to Substance Painter where I will make use of its extensive library of default materials and Substance’s community library to detail the building components for use in the finished level.

0 notes
Text
Project 2 Part 5 - Implementation Begins
This week I badly needed to start getting things done in UE4 and in Maya. So, I first began greyboxing out the level using UE4′s primitives to get and idea of the kind of layout I wanted to use. This will then give me a template that I can begin replacing with the 3D assets I produce using Maya and Substance Painter to flesh out the level.
One of the main things I wanted to implement was a proper organic, graded landscape for the buildings to sit on the help give the idea of descent I talked about in the previous blog. To do this I decided the quickest way was to familiarise myself with the landscape tools in UE4. I feel this will give me the kind of results I’m looking for and, combined with some careful use of tiled 3D assets I can hopefully better-realise my vision of Victorian Whitechapel.

Above is my draft attempt at a city environment. As you can see I’ve tried to adopt an organic approach to laying out the level with the alleyway I will use as the main focus connecting two streets with back-court geometry of some walls and outhouses. This takes inspiration from two sources. I did extensive exploration work using Assassin’s Creed Syndicate to explore a fully-realised version of Victorian Whitechapel to get a feel for the street layout. I also used a period-correct map of Whitechapel (below) for reference as well.

0 notes
Text
Project 2 Part 4 - Design Concepts
I’ve been working on design maps and some detail sketches to get an idea of how I want the level to look and feel. Choosing Whitechapel as a location rather then other parts of Victorian London affords me a bit more latitude in terms of how much detail I need to put into the buildings. It is much less opulent than other parts of central London in terms of architectural detail. After reading an article by an architectural historian on The Guardian’s website I have noted that the architecture of the period was notable for its wide variety of approaches to designing buildings and spaces. This means that Whitechapel’s architecture should have a bit of piecemeal feeling to it with every building feeling a bit different. With it being one of the most impoverished areas of London at the time it should also be very grimy, dilapidated and dotted with additional makeshift structures. There is also a great deal of influence leftover from the Medieval period in terms of the layout of the side-streets of most of London. This means the buildings are very close together and the alleys are very tight and confined. Below is a sketch I’ve done exploring some of the kind of details I will need for the buildings in the level.

All of this will play into my aims to create a dark and foreboding atmosphere. The level I aim to create will be an alleyway with the tightly grouped buildings making the player feel confined and oppressed. To add to this I want to create a sensation of sinking so the geographical gradient of the level should slope down and away from the player. This feeling of descent should add to the player’s uneasy feeling and help enhance the atmosphere.
Below I have three top-down layout sketches I’ve done exploring how I want the space to flow.



0 notes
Text
Project 2 Part 4 - A Realization
Up until yesterday I had been beginning to freak out a little bit about how much work I had to do and the amount of detail I would have to go into for this project. Victorian London is a difficult period to recreate in 3d art because of the sheer amount of ornate detail that went into everything from architecture to clothing to advertising to everyday items. I wasn’t sure my 3d art skills (which are vaguely competent) would be truly up to the task of reworking my level so it could better tell the story I was aiming for.
Then I watched the GDC lecture that Steve Gaynor (writer/designer) and Kate Craig (environmental artist) from the Fullbright Company did a few years ago on the making of Gone Home. My “Eureka” moment came when they were talking about how much detail they needed to put into the game to make it feel like a real, lived-in house. The answer was pretty simple. Enough. The human mind is has a very handy habit of filling in the blanks as long as people are given enough information. It’s why we can still read road signs that are partially obscured by tree branches and see what impressionist artists like Monet and Cezanne were depicting in their paintings.
In Gone Home, the reality is that the home the Fullbright Company created is a bit more sparse that a lived-in family home in real life might be. But, what they did successfully was to put in enough detail that players could imagine that this was a place that a family had lived in for many years. This is the “broken circle” concept at its very finest. Players could make the connection between what they were seeing and what they imagined in terms of what a lived-in home should look like.
This kind drew me back to another GDC talk I watched on the Art of Dear Esther. We wouldn’t have Gone Home without The Chinese Room’s Dear Esther arguably and so studying it is key to me figuring out how to achieve what I wanted to achieve. Dear Esther began its life as a mod for Half-Life 2 for an academic project. When they decided to build it as a standalone game the logical option was to build it using the Source Engine because they already had a ton of resources made for it.
There were problems with this approach though. The Source Engine is quite limiting, even at the point when they were making it, and so Robert Briscoe, the lead artist on the project, decided in order to give more detail to the game he opted to use a mildly impressionistic approach to the art style. This way he could use the art style to more carefully evoke the feelings that they want the player to feel in a more organic way.
This led me back to my concept and thinking what my themes are. These are:
Duty
Redemption
Mental Illness in the Victorian period
For these I want the game to hold a sense of foreboding, especially in the scene I’m building. Fog is a key feature of Victorian-era London. The Industrial Revolution really wrought an incredible amount of havoc on London and the “pea-souper” smog that shrouded the city at the time is the perfect vehicle to add a the kind of sense of mystery and foreboding that I want to create for the player.
Given that mental illness is a key point I want there to be a slightly hazy feel to the level and so I think that a good option for me to adopt an impressionistic approach to the game’s art style. Using dark tones and details that you can’t quite make out will put the player on edge from the very outset and set the overall tone for the game (were I to continue working on it of course).
Anyway, It was this realization that I could create an environment that tells the story I want to by giving, just enough detail that the player feels how I want them to. In putting a certain amount of guided interpretation into the player’s hands it will hopefully help them immerse themselves better in the experience.
youtube
0 notes
Text
Project 2 Part 3 - Design Principles Research
My mistake with the last project was just throwing a level together as I imagined it in my head without considering any kind of level design principles properly. There was no sketching either to help me visualize things first. These big mistakes.
I’ve been a lot more methodical this time around. I have had a deep dive into the resources that the GDC YouTube channel has available on environmental storytelling. Much of what I have learned is that designing 3D levels for first or third-person games with a moveable camera involves designing the level with the rule of thirds in mind. This means laying out the level in such a way that everything frames in the thirds of the screen.
After the rule of thirds much of what influences level design are architectural and interior design principles. For my purposes using the right architecture will be crucial to creating the right atmosphere. It’s a Whitechapel alleyway and it’s a crimescene. This means that I’ll be wanting tight spaces and high walls and buildings to give a claustrophobic and ominous feeling.
I spent time analyzing the opening level from Deus Ex: Mankind Divided which tells a fantastic story with the environment showing how the world has moved on from the events of the previous game using purely the environment (with a little cutscene exposition) and building up to the main centrepiece event at the end of the level.
The half-finished architecture emphasizes the grandiose intentions of the Dubai setting while also showing the kind of impact that all of the augmentations malfunctioning at once caused on the world. For me, it is one of the best scene-setting opening levels in recent years and the way the environment tells the story is very much key to this.
Destiny 2 has also been a great source of inspiration. A large part of how Bungie builds the world of Destiny is through environmental storytelling. The worlds they’ve created right from the opening moments in the Cosmodrome on Earth where you are revived in the rusted wreck of a car in a whole traffic jam of abandoned vehicles just outside a massive broken down wall sets the scene for a player of a human civilization trying to recover from a cataclysmic event many years ago.
The Lost Sectors of the Moon and Europa and the original Venus location in the first game do a fantastic job of this showing players hidden areas of the game that were once great scientific installations. They use the architecture to hint at a past that was hopeful and triumphant in its achievements.
With these examples in mind this week I hope to identify exactly the kind of characteristics I need to focus on to build my level back up better. And I shall also start to sketch ideas and maps of how it should look.

0 notes
Text
Project 2 Part 2.
Ideally these blogs will be completed weekly but another project has distracted me from completing the first blog at the right time so this week I have done 2 blogs to get me up to speed.
I have identified several good sources for research. Christopher Totten’s book An Architectural Approach to Level Design has a solid chapter on environmental storytelling which has been helpful so far in getting me started. I have also been exploring what resources the GDC have available on YouTube. So far I have had a first look at Environment Design as Spatial Cinematography: Theory and Practice by Rockstar North’s Miriam Bellard, How to Tell Stories and Guide Players Through Level Design by Thirty Flights of Loving designer Brendon Chung, The Art of Dear Esther – Building an Environment to tell a Story by LittleLostPoly’s Robert Briscoe and Ten Principles for Good Level Design by Square Enix Montreal’s Dan Taylor. They have all proven useful and I will return to them this week to put together a proper outline of what I can take from them to help improve my level design for the better.
I am also in the process of identifying games that will help me understand good environmental storytelling. Returning to the BioShock series and Dear Esther will be incredibly useful for cues on good environmental storytelling, as are Arkane’s Prey and Dishonored. Destiny also has some engaging ways in which it uses level design to aid in world building. Assassin’s Creed Syndicate, Vampyr and Sherlock Holmes: Crimes and Punishments will help me get a handle on how to visualize Victorian London in a game space. The most recent Hitman games are fine examples of how to create vibrant and engaging play spaces. Dead Space and Dead Space 2 are also very successful at conveying the games events through thoughtful level design. Alien Isolation is another title on my hit list. In theory the From Software’s Souls games and Bloodborne are worth exploring as well but the grindy nature of their gameplay makes them less tempting to use for research because they are just insane timesinks. It might be a good excuse to finally play The Last Of Us II though.
There is a danger of going too far down a gameplay rabbit hole and never actually loading up the Unreal Editor or Maya so I will be important to move on from games that feel limited as sources. Choosing titles that I have more experience of (ie previously completed or spent a significant amount of time playing already) like BioShock, Dear Esther, Destiny, Dishonored and Dead Space will help.
This week’s work will be a combination of note-taking on GDC videos and gameplay sessions. The aim will to be able to present a clearer idea of the principles and design strategies I will be able to employ. I will also begin assembling a collection of reference images on Victorian architecture using the mood board I created for the initial project as a jumping off point.

3 notes
·
View notes
Text
Project 2 Part 1.
It’s a new year and it’s time for a new project. This time I’m moving on to level design and focusing specifically on environmental storytelling. Good environmental storytelling is what drew me game design in the first place. System Shock was my first introduction to a digital world that told it’s story through the actual environment you explored. Citadel Station felt like a real place and the signs of the calamity that had befallen it were strewn all over the environment painting a brutal picture of the station’s fall. It was captivating.
My new project will expand on a level design I began working on for my 3D Level Design module in second year. The concept came about as a result of me mainlining Ripper Street while crunching my coursework for the first half of my second year at Abertay. The plan was to build a crime scene set in Victorian London. Capturing the mood is incredibly important and while the original project was functional I focused very little actual time into it’s design and as a result the level I created was functional my pretty lacklustre.
My plan therefore is to redesign this level. I will engage in research on engaging level design that uses environmental storytelling exploring GDC talks, academic writing, design blogs and playing through games that give me a good idea of successful environmental storytelling. It is my hope that, equipped with the right knowledge I can make the image of the level I have in my head become a reality by expanding what I know about level design and employing techniques that have been successfully used by some of the industry’s best storytellers.
Secondary to this aim I am hoping to improve documenting my concepting and ideation process. This blog will play a large role in that process and will serve as a record of what I have done to achieve my goals.
Below is a screenshot from the original project.

1 note
·
View note
Text
What have I learned?
Initially I have learned that I am still pretty bad at scripting in C# for Unity. However I am more confident in my coding abilities than I was before. I believe I could comfortably build a prototype for something I wanted to try out myself fairly quickly as long as the mechanics I was using were not too complicated.
I’ve also learned that creating a jump mechanic (and I would assume this would apply no matter if the game was a 2D platformer, a 3rd-person 3D game or a first-person game) is about creating a jump system that feels intuitive.
Creating an intuitive control system is very much about testing. I have spent a lot of time in my test arena playing with the adjustable parameters for the jumps before allowing other people to test the game. I only gave the test-build out once I had settled on jumping parameters that felt to me like they worked.
How did I gauge this? Well, I played Titanfall 2, Destiny 2 and Mirror’s Edge and jumped around for hours in order to get a feel for how other studios had managed to get a solid feel for their jumps. Then, when I went back to my prototype it tried to adjust the gravity modifiers and jump heights until the jumps performed the way my fingers had been programmed to respond after playing other people’s most satisfying jump mechanics.
I think that toggling the Glide would have been extremely satisfying if I had managed to get it working however I probably wasted too much time trying to get it working when I could have been balancing all three jump types to make them feel better. I do believe that, for me at least, each mechanic feels fun and is satisfying.
There are a couple of additions that I think would help improve the feel of all three jump mechanics. I think that the right sound effects would go a long way to improving the feel. Perhaps the sound of a thruster firing with each boost would help. Screen shake would also improve the feel of the jump from launch to landing along with some carefully calibrated rumble.
In the context of the wider games industry, I believe jump mechanics are something that gamers take for granted. They are a core experience whether you’re playing some intense PvP like Apex Legends, diving into a deep co-operative raid with jumping-puzzle sections in Destiny or exploring ancient ruins in Tomb Raider or Uncharted. All too often jumping is taken for granted and players do notice when a game’s jump mechanic, no matter how important it is to a game’s core pillars, is not as satisfying as it could be.
In that way I feel that exploring such a seemingly simple mechanic is a fully worthwhile endeavour and has allowed me to expand my understanding of how key it is to nail the fundamentals of your game design before moving on to more complex mechanics.
0 notes
Text
Testing
Once I had got all three jump mechanics working I needed to test the game.
I managed to rope in a couple of willing participants to test the jump mechanics. I have built the prototype with the Xbox 360 controller in mind as that was what I had on hand. However, my testers only had mouse and keyboard available.
I had mapped each jump to a different face button on the 360 controller (X,Y,B) however I felt I could not give the same jump experience mapping the jump to three different keys on the keyboard, especially as “space” is the traditional jump button for keyboard and mouse players due to it’s handy proximity to the right thumb in a WASD control scheme.
What this meant was that, in order to provide a consistent jump experience for all three jump types I had to create three test builds each one with a different jump mechanic mapped to “space”.
One mistake I made though was forgetting that I had inverted the y-axis controls as I am one of those weirdos and hadn’t switched them back for the test builds.
I used the following survey on SurveyMonkey to gauge the tester’s preferences.
1. Did you notice a tangible difference between the three jump mechanics? Yes/No/Not Sure 2. Which jump mechanic did you like the most?
Triple-Jump
Boosted Double-Jump
Glide 3. What made this mechanic your favourite out of the three? (Text box answer.) 4. Which jump mechanic did you like the least?
Triple-Jump Boosted Double-Jump Glide 5. What made this mechanic the one you liked least? (Text box answer.) 6. Did the control scheme play a factor in your preference Yes/No
7. Please use this box to add any other notes you have on the jump mechanics. (Text box answer)
The results I got back, although slightly influenced by my inverted y-axis mistake, showed that the two testers preferred either the Glide or the Boosted Double-Jump over the Triple-Jump mechanic. It also showed that being able to time the jumps played a factor in how the testers responded. I suspect they would have had an easier time with all three jump mechanics if they had access to a gamepad.
0 notes
Text
Boosted Double-Jump
This type of jump was also pretty simple to implement. All I needed to do was adapt the code I used for the triple-jump to limit to a double-jump instead and make sure that the gravity and jump height on the second jump were adjusted to feel like the second jump was bigger and faster. Again, the pertinent code is emboldened. Also, this isn’t the entire player controller script. There are a few functions related to death and checkpoints that have been omitted.
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerMovement : MonoBehaviour { // Variables to collect movement inputs. private float xMovement; private float zMovement;
// Adjustable parameters for movement and jumping. [SerializeField] private float playerSpeed = 15.0f; [SerializeField] private float gravityModifier = 1.5f; [SerializeField] private float glideGravityModifier = 1f; [SerializeField] private float glideJumpHeight = 9.0f; [SerializeField] private float boostJumpHeight = 6.0f; [SerializeField] private float boostGravityModifier = 1.25f; [SerializeField] private float jumpHeight = 3.0f; [SerializeField] private int jumpLimit;
// Information needed to be passed into the script from other components or game objects. [SerializeField] private CharacterController playerController; [SerializeField] private Transform groundCheck; [SerializeField] private float groundDistance = 0.4f; [SerializeField] private LayerMask groundMask;
// Private variables for use in the logic. private Vector3 allMovement; private Vector3 fallVelocity; private Vector3 defaultRespawnPoint = new Vector3(0f, 2f, -3.5f); private Vector3 checkpointRespawn; private Vector3 currentCheckpoint; private bool isCheckpoint1 = false; private bool isCheckpoint2 = false; private float gravity = -9.81f; private int jumpCount = 0; private bool isGrounded; private bool isGliding = false; private float defaultGravityModifier;
void Start() { defaultGravityModifier = gravityModifier; currentCheckpoint = defaultRespawnPoint; }
// Update is called once per frame void Update() { // Grounding check code begins here. isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
// This does the grounding check. if (isGrounded && fallVelocity.y < 0f) { // This stops the player from continuing to accelerate due to gravity once on the ground. fallVelocity.y = -2f;
// This resets the jump counter if to zero allowing the player to jump in the air a number of times up to a user-defined the jump limit. jumpCount = 0;
// Resets isGliding and the gravity modifier when the player is grounded. isGliding = false; gravityModifier = defaultGravityModifier;
}
// This is where the game gets the input for movement xMovement = Input.GetAxis("Horizontal"); zMovement = Input.GetAxis("Vertical");
// This translates the input into movement. allMovement = transform.right * xMovement + transform.forward * zMovement; playerController.Move(allMovement * playerSpeed * Time.deltaTime);
// This implements gravity so the player falls when in the air.
if (isGliding) { fallVelocity.y += gravity * glideGravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + glideGravityModifier); } else { fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + gravityModifier); }
//Time to toggle the glide. if (Input.GetButtonDown("Jump3") && isGliding && jumpCount >= 1) { fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + gravityModifier); isGliding = true; }
if (Input.GetButtonDown("Jump3") && isGliding == false && jumpCount >= 1) { fallVelocity.y += gravity * glideGravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + glideGravityModifier); isGliding = false; }
// Jump. Jump(); BoostJump(); Glide();
// Leave the game. Quit();
} // Good old-fashioned triple-jump. void Jump() { // This is the logic for jumping allowing for the possibility of multiple jumps in the air up to a user-defined jump limit. if (Input.GetButtonDown("Jump1") && jumpCount < jumpLimit) { Debug.Log("Jump1"); fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1; } }
// Hybrid boosted double-jump void BoostJump() {
if (Input.GetButtonDown("Jump2") && jumpCount < 2) { Debug.Log("Jump2"); fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1;
if (Input.GetButtonDown("Jump2") && jumpCount == 2) { Debug.Log("Jumpier2"); fallVelocity.y = Mathf.Sqrt(boostJumpHeight * -2f * (gravity * boostGravityModifier)); jumpCount = jumpCount + 1; } } }
// Gracefully jump and glide in the air. void Glide() { if (Input.GetButtonDown("Jump3") && jumpCount == 0) { Debug.Log("Jump3"); fallVelocity.y = Mathf.Sqrt(glideJumpHeight * -2f * (gravity * glideGravityModifier)); jumpCount = jumpCount + 1; //isGliding = true;
} }
0 notes
Text
Triple-Jump
This jump mode was quite easy to implement in comparison to the glide. All I needed to do was adapt the initial jump functionality code to include a condition locking the player to a specific number of jumps while the in the air. A simple if statement managed to do the trick. All code related to the triple-jump is emboldened.
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerMovement : MonoBehaviour { // Variables to collect movement inputs. private float xMovement; private float zMovement;
// Adjustable parameters for movement and jumping. [SerializeField] private float playerSpeed = 15.0f; [SerializeField] private float gravityModifier = 1.5f; [SerializeField] private float glideGravityModifier = 1f; [SerializeField] private float glideJumpHeight = 9.0f; [SerializeField] private float boostJumpHeight = 6.0f; [SerializeField] private float boostGravityModifier = 1.25f; [SerializeField] private float jumpHeight = 3.0f; [SerializeField] private int jumpLimit;
// Information needed to be passed into the script from other components or game objects. [SerializeField] private CharacterController playerController; [SerializeField] private Transform groundCheck; [SerializeField] private float groundDistance = 0.4f; [SerializeField] private LayerMask groundMask;
// Private variables for use in the logic. private Vector3 allMovement; private Vector3 fallVelocity; private Vector3 defaultRespawnPoint = new Vector3(0f, 2f, -3.5f); private Vector3 checkpointRespawn; private Vector3 currentCheckpoint; private bool isCheckpoint1 = false; private bool isCheckpoint2 = false; private float gravity = -9.81f; private int jumpCount = 0; private bool isGrounded; private bool isGliding = false; private float defaultGravityModifier;
void Start() { defaultGravityModifier = gravityModifier; currentCheckpoint = defaultRespawnPoint; }
// Update is called once per frame void Update() { // Grounding check code begins here. isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
// This does the grounding check. if (isGrounded && fallVelocity.y < 0f) { // This stops the player from continuing to accelerate due to gravity once on the ground. fallVelocity.y = -2f;
// This resets the jump counter if to zero allowing the player to jump in the air a number of times up to a user-defined the jump limit. jumpCount = 0;
// Resets isGliding and the gravity modifier when the player is grounded. isGliding = false; gravityModifier = defaultGravityModifier;
}
// This is where the game gets the input for movement xMovement = Input.GetAxis("Horizontal"); zMovement = Input.GetAxis("Vertical");
// This translates the input into movement. allMovement = transform.right * xMovement + transform.forward * zMovement; playerController.Move(allMovement * playerSpeed * Time.deltaTime);
// This implements gravity so the player falls when in the air.
if (isGliding) { fallVelocity.y += gravity * glideGravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + glideGravityModifier); } else { fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + gravityModifier); }
//Time to toggle the glide. if (Input.GetButtonDown("Jump3") && isGliding && jumpCount >= 1) { fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + gravityModifier); isGliding = true; }
if (Input.GetButtonDown("Jump3") && isGliding == false && jumpCount >= 1) { fallVelocity.y += gravity * glideGravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + glideGravityModifier); isGliding = false; }
// Jump. Jump(); BoostJump(); Glide();
// Leave the game. Quit();
} // Good old-fashioned triple-jump. void Jump() { // This is the logic for jumping allowing for the possibility of multiple jumps in the air up to a user-defined jump limit. if (Input.GetButtonDown("Jump1") && jumpCount < jumpLimit) { Debug.Log("Jump1"); fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1; } }
// Hybrid boosted double-jump void BoostJump() {
if (Input.GetButtonDown("Jump2") && jumpCount < 2) { Debug.Log("Jump2"); fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1;
if (Input.GetButtonDown("Jump2") && jumpCount == 2) { Debug.Log("Jumpier2"); fallVelocity.y = Mathf.Sqrt(boostJumpHeight * -2f * (gravity * boostGravityModifier)); jumpCount = jumpCount + 1; } } }
// Gracefully jump and glide in the air. void Glide() { if (Input.GetButtonDown("Jump3") && jumpCount == 0) { Debug.Log("Jump3"); fallVelocity.y = Mathf.Sqrt(glideJumpHeight * -2f * (gravity * glideGravityModifier)); jumpCount = jumpCount + 1; //isGliding = true;
} }
0 notes
Text
Glide
Once I’d got the basic jump working (See the Eureka post) I wanted to start exploring the three different jump mechanics that I had in mind.
I started with the glide mechanic because it felt like the one that was most complicated to implement. Initially I believed that I could toggle the glide mechanic while the player was in flight to play with how the jump arc would look.
This proved incredibly difficult. The approach I tried using a jump counter variable to limit in conjunction with the boolean that would say whether or not the player was grounded. The jump counter variable would also be useful for implementing the triple and boosted double-jumps.
This wasn’t enough to help toggle the glide on and off. I also added a boolean variable called isGliding in order to determine whether or not the player was indeed gliding.
The best way to control the jump was to adjust the gravity acting on the player and pushing them back to the ground again. It seemed that, in conjunction with a jump counter and the isGliding variable this would be a simple case of getting the jump input and testing to see how many times it had been pushed while the player was still airborne in order to know whether to toggle the gravity between normal and glide.
Unfortunately, no matter how or where I thought to implement this in the player controller I could not get the jump gravity to toggle while the player was still in the air. (|The code below is the code I finally settled on and it contains logic from my attempts that doesn’t seem to interfere with the way the glide jump works now.)
Finally I settled on ditching the toggling control completely and just coding a single long, floaty jump with plenty of in-air control. When jump is pressed gravity is dialed down from what it would normally be. I’ve also serialized key variables so I can tweak the jump mechanics in Unity rather than having to dive back into Visual Studio every time I want to adjust the jump. Below is the final player controller code with all of the jump mechanics in it. I’ve emboldened the code specific to the glide jump.
The logic in there that I have put in place to allow the player to toggle the glide does give feedback into the debug console but doesn’t seem to have any tangible effect on the jump.
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerMovement : MonoBehaviour { // Variables to collect movement inputs. private float xMovement; private float zMovement;
// Adjustable parameters for movement and jumping. [SerializeField] private float playerSpeed = 15.0f; [SerializeField] private float gravityModifier = 1.5f; [SerializeField] private float glideGravityModifier = 1f; [SerializeField] private float glideJumpHeight = 9.0f; [SerializeField] private float boostJumpHeight = 6.0f; [SerializeField] private float boostGravityModifier = 1.25f; [SerializeField] private float jumpHeight = 3.0f; [SerializeField] private int jumpLimit;
// Information needed to be passed into the script from other components or game objects. [SerializeField] private CharacterController playerController; [SerializeField] private Transform groundCheck; [SerializeField] private float groundDistance = 0.4f; [SerializeField] private LayerMask groundMask;
// Private variables for use in the logic. private Vector3 allMovement; private Vector3 fallVelocity; private Vector3 defaultRespawnPoint = new Vector3(0f, 2f, -3.5f); private Vector3 checkpointRespawn; private Vector3 currentCheckpoint; private bool isCheckpoint1 = false; private bool isCheckpoint2 = false; private float gravity = -9.81f; private int jumpCount = 0; private bool isGrounded; private bool isGliding = false; private float defaultGravityModifier;
void Start() { defaultGravityModifier = gravityModifier; currentCheckpoint = defaultRespawnPoint; }
// Update is called once per frame void Update() { // Grounding check code begins here. isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
// This does the grounding check. if (isGrounded && fallVelocity.y < 0f) { // This stops the player from continuing to accelerate due to gravity once on the ground. fallVelocity.y = -2f;
// This resets the jump counter if to zero allowing the player to jump in the air a number of times up to a user-defined the jump limit. jumpCount = 0;
// Resets isGliding and the gravity modifier when the player is grounded. isGliding = false; gravityModifier = defaultGravityModifier;
}
// This is where the game gets the input for movement xMovement = Input.GetAxis("Horizontal"); zMovement = Input.GetAxis("Vertical");
// This translates the input into movement. allMovement = transform.right * xMovement + transform.forward * zMovement; playerController.Move(allMovement * playerSpeed * Time.deltaTime);
// This implements gravity so the player falls when in the air.
if (isGliding) { fallVelocity.y += gravity * glideGravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + glideGravityModifier); } else { fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + gravityModifier); }
//Time to toggle the glide. if (Input.GetButtonDown("Jump3") && isGliding && jumpCount >= 1) { fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + gravityModifier); isGliding = true; }
if (Input.GetButtonDown("Jump3") && isGliding == false && jumpCount >= 1) { fallVelocity.y += gravity * glideGravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime); Debug.Log("isGliding" + isGliding); Debug.Log("Gravity Modifier" + glideGravityModifier); isGliding = false; }
// Jump. Jump(); BoostJump(); Glide();
// Leave the game. Quit();
} // Good old-fashioned triple-jump. void Jump() { // This is the logic for jumping allowing for the possibility of multiple jumps in the air up to a user-defined jump limit. if (Input.GetButtonDown("Jump1") && jumpCount < jumpLimit) { Debug.Log("Jump1"); fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1; } }
// Hybrid boosted double-jump void BoostJump() {
if (Input.GetButtonDown("Jump2") && jumpCount < 2) { Debug.Log("Jump2"); fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1;
if (Input.GetButtonDown("Jump2") && jumpCount == 2) { Debug.Log("Jumpier2"); fallVelocity.y = Mathf.Sqrt(boostJumpHeight * -2f * (gravity * boostGravityModifier)); jumpCount = jumpCount + 1; } } }
// Gracefully jump and glide in the air. void Glide() { if (Input.GetButtonDown("Jump3") && jumpCount == 0) { Debug.Log("Jump3"); fallVelocity.y = Mathf.Sqrt(glideJumpHeight * -2f * (gravity * glideGravityModifier)); jumpCount = jumpCount + 1; //isGliding = true;
} }
0 notes
Text
Exploring the mechanics.
I really love the idea of first-person platforming and exploration. I also really like the different jump mechanics that Bungie has implemented in Destiny so I wanted to see how to build those different jumps and explore how they would work in a simple 3D environment.
Below is a sketch outlining how the different jump mechanics flight profiles would look. This is basically the image I held in my head when sitting down to adjust the code in the player controller.

0 notes
Text
A Bit More Explanation
I have a very odd creative process.I tend not to sketch or write things down. Instead everything goes on internally until I finally start doing what I’ve been planning. This is probably a very bad habit to have. It also means that when I do create a sketch or write something down I tent to forget about it.
I have realized that, in blogging about my development progress I’ve kinda skipped talking about a step and it’s probably the most important part of the whole project - iterating on the jump mechanics.
Given that this project is about iterating and exploring a game mechanic to not talk about the iterative process would be incredibly daft and detrimental to the whole exercise.
So, I’m going to squeeze in a last couple of blogs today detailing my journey of experimentation with the different jump mechanics I have built in order to clear things up a bit and make the “final” project make more sense.
0 notes
Text
More Jumping
I’ve had varying levels of success implementing the three jump mechanics I’ve wanted to use. The triple-jump and boosted double-jump have been implemented fairly simply without too many issues. I have been messing around with them in the test-level I’ve created and I’m pretty satisfied that they actually work and can be tweaked to feel more satisfying.
The glide has been a lot more awkward. How I though this would work is that I implement a gravity modifier that allows me to set how the game applies gravity to the player while in the air. The idea was to create a toggling system to use the jump button to toggle between two different gravity modifiers while the player is still in the air. Using carefully placed Debug.Log messages I have got to a point where the logic I am using seems to be working but gravity modifiers don’t seem to be toggling.
In the end, I think I will just have to ditch the toggling mechanic for now and go with a simpler glide mechanic that uses a lighter gravity for the player, giving them more time in the air to control where they are going. This will be easy enough to do and then I can concentrate on iterating each of the jump mechanics so that they feel different enough to test them out in the wild with a couple of willing test subjects. That is this afternoon’s task - to simplify the glide, refine the other jump mechanics and create builds offering the use of all three mechanics to complete the test level.
0 notes
Text
Jump Mechanics
I have three styles of jump mechanics I want to experiment with based on my experiences with playing Destiny. I wanted to explore these jump mechanics because the Destiny community is so polarized over which of the three is best. There are two camps - Titans and Hunters who prefer a more traditional style of jump based on double/triple jump or boost jump and Warlocks who love the glide mechanic associated with their class which is more akin to flying.
The mechanics seem to work as follows:-
Warlock - Destiny’s Warlock jump is more like flying. Pressing jump again while in the air toggles the glide on and off. Double-pressing jump on the ground will give a full boost jump and then the glide can be toggled on and off while in the air until the glide timer runs out. I’m not sure I have the programming skills to fully emulate this style of jump, especially toggling the glide on and off mid-jump but I can create a jump that is more like the the Warlock glide by adjusting the jump height and gravity while in the air. This should provide a comfortable glide-style jump to navigate the test level.
Hunter - The Hunter’s jump is a traditional double or triple jump (depending on the choice made within the player sub-class). Most players tend to favour the triple-jump. I can fully implement this style of jump fairly easily as It just requires an adjustment on my jump limit variable. Again the jump height and gravity can be tweaked as well to adjust the feel of the jump.
Titan - The Titan class uses a hybrid double-jump boost feature. It seems to operate somewhere in between the way the Hunter jump and the Warlock glide works. Titans can toggle their jump boost during the jump but it is less forgiving than the Warlock glide. Implementing this mechanic may require additional coding work that I may not have the knowledge to fully explore how to implement it.
The best way to implement and compare the different jump types I believe would be to map each jump to a different button on the joypad in order to allow them to be compared.
0 notes
Text
Eureka! My Jump Works Now.
So, I was using a basic first-person controller that had been demonstrated in lectures but, I could not for the life of me figure out how to limit the amount of jumps I could do. There was something missing somewhere.
I decided to try and fix the problem by starting again and coding it using an example I had found in one of Brackeys’ tutorials as a basis. After a few teething problems with the Brackeys code around my looking I managed to get it working and realized where I was going wrong.
The problem lay in how I was checking if the player had come in contact with the ground again after jumping. In the original code the grounding check code wasn’t actually implemented properly. Using the Brackeys example I realized that I needed to implement the grounding check and reset of the jump counter (should I want a double or a triple jump) separately from the if statement that is called when the player jumps.
Now I have managed to build a piece of jumping code that I can easily manipulate in Unity to adjust the jump height, gravity and jump limits to allow me to fine-tune the jump mechanics to find a satisfying jump mechanic.
Here’s the code:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerMovement : MonoBehaviour {
private float xMovement; private float zMovement;
[SerializeField] private CharacterController playerController; [SerializeField] private float playerSpeed = 15.0f; [SerializeField] private float gravityModifier = 1.0f; [SerializeField] private float jumpHeight = 3.0f; [SerializeField] private int jumpLimit;
[SerializeField] private Transform groundCheck; [SerializeField] private float groundDistance = 0.4f; [SerializeField] private LayerMask groundMask;
private Vector3 allMovement; private Vector3 fallVelocity; private float gravity = -9.81f; private int jumpCount = 0; private bool isGrounded;
// Start is called before the first frame update void Start() {
}
// Update is called once per frame void Update() { // Grounding check code begins here. isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
// This does the grounding check. if (isGrounded && fallVelocity.y < 0f) { // This stops the player from continuing to accelerate due to gravity once on the ground. fallVelocity.y = -2f;
// This resets the jump counter if to zero allowing the player to jump in the air a number of times up to a user-defined the jump limit. jumpCount = 0; }
// This is where the game gets the input for movement xMovement = Input.GetAxis("Horizontal"); zMovement = Input.GetAxis("Vertical");
// This translates the input into movement. allMovement = transform.right * xMovement + transform.forward * zMovement; playerController.Move(allMovement * playerSpeed * Time.deltaTime);
// This implements gravity so the player falls when in the air. fallVelocity.y += gravity * gravityModifier * Time.deltaTime; playerController.Move(fallVelocity * Time.deltaTime);
// This is the logic for jumping allowing for the possibility of multiple jumps in the air up to a user-defined jump limit. if(Input.GetButtonDown("Jump") && jumpCount < jumpLimit ) { fallVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); jumpCount = jumpCount + 1; }
} }
P.S. Looking around is in a separate script attached to the camera itself inside the parent player game object.
0 notes