Text
Day 47 - Local Multiplayer
Tonight we’re going to take on the hefty task of setting up local multiplayer functionality within our game. Keep in mind I’m kind of winging this and hoping I can get it to work for our project.
First we’re going to create a game instance blueprint and we’re just going to add an integer which will dictate the amount of players to spawn in the game.
Then we’re going to create a widget that will set this integer to the proper player amount.
We’ll cast to the game instance here and set the variable as we click on each button.
Then we’re going to go into our game mode blueprint and save that variable for a new function.
This new function will handle the adding of players. We’re going to run a for loop starting at index 1 (the game will always spawn player one at index 0), then we create those players.
After that loop finishes, we are actually going to spawn the characters.
For now, we’re going to do some non-modular hard coding just to get the functionality in (and hopefully working). We’ll spawn a different character, alternating based on the player count.
Then we just need our player controllers to possess these characters and we’re all set.
It took me nearly 4 hours but I got it.. I’ll show the pictures tomorrow!
0 notes
Text
Day 46 - Random Points
We’re gonna take a look at the function random point in bounding box and its uses within a game (specifically the one I’m making on the side right now). I know there’s got to be a cleaner way to do this for the game, but I’m just going to start sloppy until I can come up with something better.
So first we’re going to create a blueprint with a box collider in it and place it in the world.
This box is actually going to act as the bounding box from which we will be spawning icicles. We’re going to start by creating a function to start a timer which will have the functionality.
This will be called from whatever wants to spawn the icicles (in this case, the boss). Then we’re going to get a random point within the box.
We’re going to take that point and line trace straight down to the ground (there’s a reason for this).
So here’s the event we’re calling on a timer. Tracing down to the floor and if we hit it...
We’re going to get the location of the hit and check if it’s the first hit location of the event timer. If it is, we’re going to add it to an array of vector locations. If it’s the first addition to the array, we’re gonna go straight to spawning a telegraph and an icicle.
If it’s anything beyond the second, we’re going to compare that vector location to each other vector location in the array.
If it’s within a certain unit distance of any other vector location of any item in the array, we break the loop and re-run the trace to find a new location. If it’s outside of that unit distance, it adds the vector location to the array and spawns the telegraph and icicle.
The reason I added all this extra functionality instead of just spawning a bunch of icicles in random locations is because if I did that, icicles would clump up and wouldn’t get a solid coverage of the playspace. So this check ensures that each icicle spawn has at least a minimum distance between it, and each other spawned icicle.
Pretty cool, right?
See you tomorrow!
0 notes
Text
Day 45 Mutliplayer Cont. Again
Today we’re going to be adding additional functionality to the game. We have created the base class and the assassin class yesterday, so today we’re going to be adding functionality to manage its abilities which includes an ultimate system.
First thing we’re going to do in the assassin class is add a cooldown to their basic ability.
Then once the ability has been spawned, we will run a timer that flips a bool after a set amount of time has elapsed.
Next we’re going to have to create some way to increment an ultimate variable so we can use our ultimate if we have enough of the resource.
In this case, a player’s ult charge will increase when they deal damage, as well as on a static timer. So for the cherry bomb we’re going to run a trace, if we hit the boss, we’re going to be adding an amount of ult charge based on damage.
Now we’re just going to create a UI widget that is bound to our normalized ult float.
We’re going to have to cast to the player so we can get access to its variables.
Then in the details of the progress bar we’ll go ahead and bind to that float.
We just need to add this widget to the viewport now. We’ll pop into the player controller and create that widget (this way it is for each instanced player).
Then we’re going to add it to viewport in the game mode, when the player is added to the game.
So our ult bar will show up on screen now-- all we need now is a way to check if the player has enough ult charge to cast, then reset it upon use. Easy enough with a couple floats that you can reset back to zero when it is used.
And like that, we are shooting our projectile, slowly accruing ult charge (as denoted by the yellow ult charge bar).
I want to do something special for the shuriken tomorrow before I start working on the other characters and how to get multiple of those characters into the game at once from a main menu.
See you then!
0 notes
Text
Day 44 - Multiplayer Cont.
Sorry I had to cut it short, I ended up going down the rabbit hole and worked for nearly seven hours without stopping. Couldn’t really work in the rest of what I was doing so I’ll just show y’all the rest today.
So the first thing we need to do is setup some functionality to add new players to the game. We’ll do that by creating a custom function in the Game Mode. We’re going to get the controlled pawn then spawn in our player character in its place.
We’re going to create a reference in the level blueprint to the camera so we can reference it to set it as the active camera for each respective player.
Then we’re going to have that spawned player possessed by the appropriate pawn and set its camera.
Now we’re going to want to call this spawn character function, so we’re going to place it inside the player controller.
In this case we’re going to say you can press 1 on your keyboard or the start button to spawn in. Now we’re going to add some functionality to the game mode (this would be moved to the game instance, if the amount of players is chosen on the main menu).
From here we can easily pop up to 4 players in by pressing 1 or Start on the respective input device. From here we’re just going to create some basic health for the player. We’ll go ahead and create a widget.
In this widget we’ll add a progress bar (making sure to leave room for four). Then under event construct we’re going to get the player’s health so we can properly display it over this progress bar.
Once that’s done we need to create the widget within the player controller so that each instance of the player controller can have its own instance of the widget.
Then we just need to add it to the viewport after a player is added to the game and we’re all set.
Works like a charm.
See you tomorrow!
0 notes
Text
Day 43 - Multiplayer Project
Today we’ll be setting up a project with local multiplayer. This project will be the basis of a game that will be worked on at the least, 18 days. Do expect some additional posts on this short term project. If it ends up being cool or fun.. who knows, maybe we’ll work on it even longer.
So first we’re going to start with a fresh third-person project.
Then we’re going to go ahead and setup a basic arena.
Then we’re going to add a camera with a top down iso view.
And we’re going to connect that so it is our active camera when we press play. We’re going to to this in the level blueprint.
Then we’re going to set up some basic movement and keybinds.
Then we’ll add some inputs for movement. Here we’ll have some generic twin stick control.
From here we’re going to add a dodge, which is going to check the normalized velocity of the player to determine which direction the player should dodge towards (this will be based on the direction they are moving). This will be ran through a timeline.
And the rest I’ll show you tomorrow!
0 notes
Text
Day 42 - Ray Trace Distance Field Shadows
Distance Field Shadows are a great way to get soft shadows from dynamic lighting. Today we’ll be discussing how to turn them on!
First you’re going to need to head into your project settings and find the ‘Rendering’ subsection. There you will located ‘Generate Mesh Distance Fields’. Go ahead and tick that box.
Once that box is ticked, the engine will prompt you for a restart.
There are a few distance field options that you should make note of here.
Eight Bit Mesh Distance Fields reduces the bitrate from 16 to 8 bit, which reduces memory use-- though this setting may cause artifacting if you have thin or large meshes.
Compress Mesh Distance Fields will save you memory without losing any quality. Though it may cause load time increases if level streaming is being used since the meshes need to be decompressed at runtime.
Once you have restarted, you will be able to display your mesh distance fields. Simply click on the ‘Show’ button in viewport, go to ‘Visualize’ then ‘Mesh DistanceFields’, and tick the box.
From here you will see something that looks like this.
You will want your static meshes to be more gray and less white, as more white means more raytraces were needed to calculate distance fields. Now, in order to use distance field shadows, we need to enable it on specific lights that will utilize rather than standard shadow projection. First we’ll need to go into specific lights and make sure they are set to movable.
Before
Then we’ll want to scroll down to the ‘Distance Field Shadows’ area and tick the only box.
After
Immediately you can see a difference in the softness of the shadow, giving it a more realistic impression on the world.
Distance Field Shadows are a great tool for generating these soft, dynamic shadows that update in real time as you move light actors.
Keep in mind distance fields cannot be used for skeletal meshes or animated actors (as well as material based animation).
In the case of our chest here, if we find that a distance field mesh is not high enough quality we can increase its resolution individually within its mesh.
You’ll be able to see its distance field resolution in the top right of the mesh editor window.
A distance field mesh can be a maximum of 128x128x128 or 8Mb of VRAM. In order to increase that, we’ll need to pop over into the ‘LOD 0′ ‘Build Settings’ subsection. There you’ll locate ‘Distance Field Resolution’, which we will increase from 1 to 4.
This will directly increase the resolution of distance field, making it less pixelated.
With this knowledge, go forth and create beautiful things!
Until tomorrow!
0 notes
Text
Day 41 - Do N
Today is a bit of a cop out because I’d resigned to working on In Passing most of this weekend to ensure that most of the items on the backlog could make their way into the project. So we’re just going to talk about a basic piece of flow control.
‘Do N’ is really useful if you want to allow for something to happen only N times. For example, let’s say you want a player to be able to shoot a gun 30 times before having to reload.
Just like so, you could control how many times a player can do X action under a conditional reset. Super useful, right? Now let’s hope I remember it...
See you tomorrow!
0 notes
Text
Day 40 - The Door Problem
A couple of days ago we watched a GDC talk about interviewing for game design. In that talk, a blog post that broke down just what game designers (and other developers) do. This is a pertinent subject, as people do and will continue to ask what I do. Even people who have been playing games for most of their lives aren’t quite sure just what designers do. Admittedly, it probably doesn’t help that the definition of a role changes can vary based on the studio!
So let’s talk about 'The Door Problem’ by Liz England.
I think you get the idea here. Systems can range from combat to NPC shops to player movement. A mechanic would be an element of those systems. For example, in combat, you may have a dodge, shoot or an escape mechanic. Each mechanic needs to have a set of rules that consider affordances and govern its functionality.
In this example, a door is a mechanic within a greater system. Doors can serve many purposes. They can be a way to elude enemies, serve as a progression inhibitor (go find the key or kill the boss) or a simple environmental adornment.
You can also see how a mechanic can impact other systems (like player parties). This all has to be accounted for. It is a game designer’s responsibility (at least according to Liz England of UbiSoft Toronto) to work out the rules attributed to this door mechanic.
She then goes on to describe how other roles at her studio deal with the door problem.
You can begin to see the scope of work that a single mechanic creates in a Triple A environment.
The amount of parties and breadth of work that can get involved in this problem is exponential based on the complexity of the mechanic or system.
Some of this would not apply to a door but as an example, can be extrapolated to mechanics and systems of other games.
And the list goes on. The point is, the job of a game designer is to consider any and all forms of interactions with a mechanic or system and how it integrates into the overall experience.
This one is just a bonus. It just goes to show that you can pour your heart and soul into a mechanic for it to be missed. Though that’s not always a bad thing. If a door is easy to use and intuitive.. will it really be all that memorable? Do you really want the player to remember the doors in your game, or is a really just a way to get from point A to point B? I guess it depends on the game.
Until tomorrow!
0 notes
Text
Day 39 - Death Fog
I’ve been wanting to create some death fog (definitely not lifted from Divinity 2: Original Sin). I’ll just be issuing it some basic orders to bring it some life.
First we’re going to need to create a material in the volume domain, blend mode additive.
Then we’re going to create a basic texture that will represent the color of our fog, as well as a static color within a vector parameter. We will blend these and plug them into a multiply node with a scalar parameter (we’ll be planning to create a material instance later).
We’ll then take the absolute world position, particle position and particle radius to create a sphere mask where the volumetric fog will reside. We’ll add a couple scalars for control later and plug that sphere mask into a multiply.
We’ll multiply the blend, position and particle functionality together and plug that into the albedo.
Lastly, we’ll take a fog texture and pop it into a multiply and plug that into the extinction to control the shadows.
We’ll go ahead and create a material instance of this.
Then we’ll create a particle system to attach that to. In the required section, we will connect the material instance we just made.
And add a cylinder for the particles to spawn in.
Then we can adjust the values to taste in our material instance.
And there you have it, some juicy green fog.
Don’t step in it.
See you tomorrow!
0 notes
Text
Day 38 - Interviewing
A talk by Richard Carrillo (of UbiSoft Toronto) just came out today called ‘Interviewing for Game Design’ on the GDC YouTube channel so I figured we’d check it out and maybe take some notes. I’m sure there will be some helpful tips for nailing the interview process which I will surely need.
Richard noticed there a lack of consistency among interview results for candidates based on the people who interviewed them. So he wanted to know what questions other senior team members were asking that led them to the occasional opposing response to candidates. So Richard decided to watch and be involved with some of the interviews to see what was being done differently.
Standard GoTo’s
Experience
Resume Trap - Did they really do it?
Generally interviewers would pull out the resume, ask about interesting items on it and start probing along the way. Interviewers will spend some time determining whether they did what they actually said they did. Even if it has been determined that the candidate did all those things, it still doesn’t say if they’re a good designer.
Game Ideas
Game Designer vs. Game Enthusiast
Game designers don’t come up with game ideas. It is not our job to pitch. A game designer’s job is to pick all the different ideas up from other games and other members of the team and combine them into systems that work.
Richard also noticed that there is one burning question that begs to be asked during an interview but rarely is.
“Are you a game designer?”
A candidate can have experience, a process and ideas but that does not make someone a good game designer. Richard spent much of his time deliberating over how to ask candidates this question.
Richard put up a slide that separates what game designer’s do and don’t do (based on his studio and experience). He continued to hammer home that everyone has game ideas but what designers do is create systems, own the player experience, solve problems and create engaging gameplay loops.
Just to step out of this for a moment of meta discussion. This very topic is something that I have been struggling internally with. I wonder just what (form) of designer I am, as there are multiple types of designers (systems, level.. etc). It is comforting to hear that I am solidly on the game design side as my mind generally resides with each left side element. I actually struggle with level design and creating engaging spaces in the world, but I thrive on creating deep, interesting systems that keep the player coming back for more. Focusing on the overall experience is where I am most comfortable so it is exciting to hear that I closely align to UbiSoft Toronto’s definition of a game designer.
Richard then segues into questions that can be asked during interviews that answer how familiar and how thorough their understanding is with the aforementioned principles.
He found that this question comes up a lot and the purpose of it is essentially, “I want you to talk until I hear something interesting.” Use this as opportunity to talk about a system in particular.
WARNING: LONG GAMER SYSTEM RANT
In my case, one of my favorite examples of a game that I love that had some disappointing systems is Diablo 3. It was an incredibly fun and well made game, but the blood shard system needed some work. With this system, you would obtain a variable amount of currency from end game activities and this currency would be used to ‘target gamble’ on a particular item. I felt with how infrequent equipment upgrades were, not giving the player a bit more control over when their rewards were received created a poor experience. We already have a variable amount in how many blood shards are received-- I would have much preferred that specific items could have their own blood shard cost, or that a separate currency could be acquired to target these specific pieces. This would create a more fixed reward schedule that runs parallel to the game’s normal entirely chance-based drops-- giving players something to look forward to, even if nothing of use has dropped in some time. I am cognizant of the fact that a system like this may decrease the amount of time players may play the game, as they may reach that critical mass in equipment sooner.
Which leads me to my next system critique for Diablo 3. I didn’t intend to detour this far away from our post topic. I’m sorry, but I love the series. Like, really, really love it and it broke my heart that it didn’t live up to my (no doubt astronomical) expectations following Lord of Destruction.
Part of what made Diablo II great was your ability to show off all the great items you had-- and that you could give them all away if you wanted. Not that you would, but you could. Diablo III implemented a (to me) rather puzzling restriction on items. Only the people in your game at the time that you found a specific item were eligible to receive that item from you (and only for a limited amount of time). In my eyes, part of the allure of ARPG/Hack and Slash power fantasy is becoming filthy rich. Amassing some wild fortune of items or currency that can be lorded over others-- much like real life. We take some amount of pride in our accomplishments and having the ability to profoundly affect someone else’s journey through Tristram profoundly on a charitable whim felt great (I imagine it is akin to being Mr. Beast giving away thousands of dollars to random people). Or perhaps even gifting a friend your entire estate when you decide you’ll come back next ladder reset. This grounds the experience. Without (at the very least) free trading, the game may as well be a single player ARPG. I can take a stab at why they implemented this loot system. They had planned the game around having an auction house and that was supposed to cut out the middle man of trading. It very well could have been that the experience was designed around having access to the best items in the game at any time, at the click of a button, had you the currency. A currency (gold) that was acquired steadily as the game was played so you always had some inevitability towards an upgrade, even if loot drops were not in your favor. You know what, I’m going to go out on a limb here. I think Diablo III was ahead of its time. I think an auction house is a great idea for a game about hoarding and peddling loot. I think trading was a miserable experience for the average player. I think today’s gamers would be much more accepting of this (especially if we skip the real money auction house fiasco).
ANYWAY...
The issue Richard had with that question was it was too open ended and left you open to the candidate discussing a game you’ve never heard of, or going off on subjective tangents.
He found that the best way to rephrase that is as follows:
Bonus: See if they understand the implications of adding or removing that mechanic.
Here is that question in an interview.
Richard claims he doesn’t care about the answer. He wants to know what is going through your mind and how you problem solve. He is interested to know what steps you take.
He had asked this question in interviews to candidates and had received a myriad of responses like some of these (minus the last one):
The responses do not denote critical thinking about how removing that mechanic would impact the systems.
So here are some good answers (minus the first one):
The second answer shows that you are aware of how this would effect the system. The third shows that you are stepping through it as the player to understand the experience more closely. Both extremely valid ways to approach this.
In summation, this covers an understanding of systems and game loops in question form, but leaves problem solving and player experience out.
So we move on to the next question.
This is a very open-ended question, that may or may not be considering the candidates process. However there is a good answer to this. Interviewers are generally looking for something specific. They want to know about your experiences and how you have approached designing NPCs in the past and why. What factors would you consider?
A good way to phrase this question, if you wanted to understand process is this:
Some bad answers to this would be:
Clearly these candidates did not understand what being a designer entails. You are given a set of restrictions and you need to adhere to those restrictions and design a fun and engaging encounter. Be careful using to much reference to other games and not relating back to the product you’re discussing.
Which leads us to good answers:
And a great answer:
How can you get this encounter to cause less problems for stealthy playstyles? A candidate came up with a revelation that the tank was controlled by people and those people would occasionally leave their tank for a break. This creates an opportunity where both stealthy and guns-blazing playstyles have options. To me, this is a situation where you think outside of the box and find a solution that fits narratively and has mechanical implications. Bonus points if you come up with a solution-- in this case an NPC behavior system, that can be used throughout the entirety of the game instead of just an idea for this one encounter. Reusing assets! Modularity!
So what are our takeaways with this question?
Some general things to keep in mind as a candidate:
It is absolutely crucial that you play a wide variety of games. Game design isn’t a hobby. It requires you to be able to pull experiences from a swath of games for inspiration or even cautionary tales.
Truly understand what game design is. Take a loot at Liz England’s blog post ‘The Door Problem’.
When interviewing, remember to think out loud.
Richard says “ideas are like Legos in a sea of Legos.” You will be surrounded by people who have ideas, just like you. Your job is to find which of those legos in the sea come together to make the best experience.
I hope this has been as eye opening for you as has been for me.
See you tomorrow!
0 notes
Text
Day 37 - Math Functions
Okay hear me out. I need this learning real bad. The more I work on games, the more I hunger for knowledge of all the math functions so the functionality I come up with is not limited by what I know-- but rather what I can imagine. Let’s frickin’ hop right in.
Sine of Time
By running time through a sine and absolute value node we are getting the positive range on a sine wave affected by time. When we take a constant 3Vector node and multiply it by a value, we are essentially telling the material to move on the ‘Z’ axis by the multiplied amount. It is the z axis because we are only assigning a value to the ‘B’ in ‘RGB’, which represents the XYZ axis. Plugging all of this into the world position offset will get the material to bounce up and down in place.
Keep in mind this will not affect collision. We can also apply this same functionality to colors, which allows us to lerp between two different colors.
Time
We can get time to show up as a material that can be applied to a plane.
Just a few simple nodes and you’ve got this.
Additionally, you can use a frac (fractional) function to use only the fraction portion of a float.
Floor
Floor will do the opposite of fraction and return only integers.
Which can be helpful if you want to keep track of fractional amounts but only want to display integers to players.
Ceiling
Can’t have a floor without a ceiling, right? Ceiling does the same thing as floor, but it rounds up. For example: If we plug 4.1 into a print string it will spit out 5.
If we plug in 9.9 it’ll spit out 10.
This can be helpful if you have fractional damage in a game but want to round up in some cases.
Fmod
Stands for ‘Floating Modulus’. It will take two inputs, divide one by the other and return the remainder. You may be wondering... well what would you use that for? That’s a good question. The immediate example that comes to mind for me is overkill.
So if we divided 50 by 8, we would get 6 with a remainder of 2.
So what if we.. divided a monster’s remaining health by the damage of your last hit. If you did more than 25 times its remaining health in damage, it would explode into little giblets.
There’s a lot you can do with functions both in and out of materials. I’ve still got a lot to learn but today was a good start!
0 notes
Text
Day 36 - Tips and Tricks!
We’re going to have a fun one today with tips and tricks within Unreal. There will hopefully be some tools in here that can improve workflow for you because they definitely will for me!
Paste Here You may or may not have noticed the ‘Paste Here’ function while duplicating actors in your level. Essentially it will paste whatever is in your clipboard at the last location you clicked within the viewport. You can set that keybinding up in the editor preferences (there is no bind by default).
Vertex Snapping You can snap the vertices of an actor to the nearest vertex by holding ‘V’ while moving it. The only downside here is that it will only snap from the pivot point. However, the pivot point can temporarily be adjusted in the viewport by selecting the pivot and moving it with alt+middle mouse button.
Advanced Searching You can search for specific objects with advanced search methods. For example, if I type in ‘vertices < 100′ I will find all objects with less than 100 vertices within the project.
Vector Inputs (basic calculation) Interestingly, you can use the vector inputs on each actor as a basic calculator.
So if I wanted to take this cube and size it up to the power of 6, I could do that.
That’s one long boi.
Color coded folders You can color your folders as you please!
Just use the standard color wheel to pick one.
Stylish!
Thumbnail Editing Let’s say we want to adjust the thumbnail of this static mesh in the content browser.
We would just go to view options in the content browser and tick ‘Thumbnail Edit Mode’
Now we can use our left and right click to swipe and zoom around the mesh to choose the appropriate thumbnail.
Bulk Editing You can bulk edit actors by selecting them in the content browser, right clicking and going into ‘Bulk Edit via Property Matrix’.
You can then select a property from the right side that you want to be able to edit and pin it.
Once it’s pinned, you’ll be able to see the selected objects have that option as editable.
Quick Find Let’s say I wanted to find this pretty chalice in a level but I’m not sure where it is due to a complicated folder structure.
You can quickly locate any selected actor in the viewport by pressing CTRL+B.
Quick Light You can quickly add a point light to your level by holding L and clicking in the viewport. It will place the light wherever your mouse is located.
Viewport Camera Speed
You can control the viewport camera speed by scrolling your mousewheel up and down while holding right click down to move. This is an alternative to manually setting the viewport camera speed.
Validated Get
You can create a validated getter by right clicking a reference and converting it to a ‘Validated Get’.
Which saves you the trouble of having to do is valid checks like this.
Anyway, I hope that was hopeful!
See you tomorrow!
0 notes
Text
Day 35 - Speed Lines
Today we’ll be making speed lines, which is a popular form a visual feedback from countless video games. So without further ado, let’s hop right in!
The first thing we’re going to do is create a material in the post process domain.\
First we’re going to want to relocate our UVs (currently at 0,0) to the center of the screen, so we’ll do that by subtracting .5 from their position.Then we’re going to subtract
We’ll then normalize that so we can get a direction then add a panner so we get a nice animated effect.
The texture sample we’ll be using is just some default engine content (in this case ‘TilingNoise05′).
Then we’re going to take the texture coordinate we created, plug it into a ‘Radial Gradient Exponential’ material function then add a couple of scalar parameters and a power node so we can control where the gradient is.
We’ll then apply a ‘OneMinus’ to it to invert it.
At that point we’ll plug the noise texture sample and the gradient into a multiply node, which will combine the effects.
Which we will then multiply by a scalar parameter that we will control elsewhere in the project.
We will then take a texture parameter and a scene texture (with its scene texture id set to ‘PostProcessingInput’) and plug those into the A and B values of the lerp. Then we’re going to plug our multiply from earlier into the alpha.
At this point we will move into the player character and add a ‘Post Process’ component.
We will then create the dynamic instance of our material so we can adjust it at runtime.
Then we just need to set the functionality for this effect in the tick function.
In this case we’re just saying if our velocity is above a certain amount, adjust the alpha of this effect from a range of 0-1. We’ll be controlling that by just making us super jump when we press shift.
Which should look something like this!
See you in a minute!
0 notes
Text
Day 34 - Platformers
Today we’ll be talking about another Game Maker’s Toolkit video called “Why Does Celeste Feel So Good?” In this video Mark Brown puts to words what makes the moment-to-moment actions in Celeste so satisfying. Something that is critically important to platformers as a whole. If the player character does not feel satisfying... well, nothing else will salvage it.
First, Mark brings to light Madeline’s run.
He breaks apart a run into three segments. The acceleration, top speed and deceleration.
Acceleration - How long does it take you to reach top speed when holding down a directional button.
Top Speed - How fast do you move when at the peak of acceleration.
Deceleration - How quickly you slow to a stop after releasing movement input.
Mark goes on to say that getting the acceleration and deceleration values correct is particularly important.
He mentions how a graph like this, present in Mega Man XI can make your movement feel more “stiff and robotic.”
He follows that by bringing up Super Meat Boy where it takes quite some time to get to max speed and a short time to stop. This type of graph creates a more “heavy and lumbering” character.
He then mentions Super Mario Brothers 3 in which Mario has a significant acceleration and deceleration value, making him feel quite slippery.
And finally, in Celeste, the movement graph provides an ultra short acceleration and deceleration values. Which creates snappy and responsive movement.
Madeline’s reaches top speed in approximately 6 frames, which is 6 times faster than Super Meat Boy and reaches a stop in only 3 frames, which is 9 times faster than Mario.
The same process can be applied to jumps-- in which you consider the time to climb, how long you are suspended in air and for how long you fall. This gives us a total jump time, as well.
Super Meat Boy has a “long and lengthy” jump, which makes the character feel floaty.
While Yarny from Unravel has a short jump, with little hang-time, which makes him feel quite heavy.
In Celeste, Madeline has a short jump (only 36 frames), though you are given enough hang time to line up your precise landings.
These are only some of the elements that contribute to making the main character of Celeste feel so satisfying to control. For example, her ‘Air Friction’ is rather high. Making it so that if you stop issuing movement inputs, she will almost instantly fall straight down, which “makes it easier to precisely land where you want ...”
Coupled with the climb and dash, Celeste becomes a resource management puzzle platformer. With multiple tools at your disposal, it is up to you as the player to decide how you wish to complete each goal.
The first step to making a great platformer is making the character feel great to control. Insomuch that you could have fun just running around in an empty room.
Celeste is undoubtedly one of the best platformers ever made. There are many lessons to be learned from the game in how to set up a responsive, fun and mechanically deep player controller.
Here’s hoping I still have time to implement some of these lessons into my game!
Until next time.
0 notes
Text
Day 33 - Casting
We’re gonna have a bit of a performance post today. We’ll be talking about casting in Unreal. Which is essentially just getting a reference to another blueprint (scrip, etc).
Casting is something you’re absolutely going to have to do. One blueprint will have information that another will need. It is unavoidable. Understanding how to properly cast can increase performance tremendously. So a couple general things to keep in mind:
Don’t cast more than necessary
Casting can also have nearly no impact on performance, it depends on use
If you’re casting from a BP to the pawn class:
You are usually fine. The player class is loaded at all times.
Additionally, if you’re casting to other key framework classes, it’s also fine. These key classes include but are not limited to:
Game Mode
Game Instance
Player Controller
If you’re casting from a small BP to another:
If the blueprints contain minimal content and functionality, its performance impact is nearly negligible.
This is doubly true if both small blueprints are present within the same environment, as they are both already loaded.
Casting to central blueprints:
If you are casting to a blueprint that houses nothing but variables, no additional memory or loading overhead will be added.
Casting from a commonly used BP to a rarely used one:
If you are casting from.. say.. the player to an object that is only used once, in one level of your game-- it will add significant overhead. Especially if it is content or functionality heavy.
Casting between the framework classes:
Casting between these class would not impact your memory use, but may impact your compile times since it would need to compile all referenced blueprints in that framework.
This cast would fail, but the idea is there. If you cast to something rarely used-- it will impact your performance. Now if you casted from the rarely used blueprint to a framework class, it would be fine.
Let’s put this succinctly:
Situation dependent functionality that is occasionally present should cast to the core functionality that is always present.
Keep casts one way when possible as you want to minimize casting chain reactions.
An incredibly useful tip is to use C++ to bridge classes. It is much faster, cleaner and creates better workflows. This will help reduce the amount of casting that you are doing by making widely accessible variables.
Use parent/child classes as often as possible.
Use blueprint interfaces. They can bypass needing to cast, as blueprints that utilize a manually connected interface will be of a specific type, when you check that blueprint, you will know what type it is by the interface you set.
Use tags to denote the functionality of an object so you do not have to retrieve its class.
There are many ways to circumvent needing to cast. That does not mean you shouldn’t cast, just that you should be deliberate about where and how you cast. If you use these methodologies, you will get much more consistent performance in your projects! Good luck!
See you next time, space cowboy.
0 notes
Text
Day 32 - UI Controllable Sun
Today we’ll be looking at creating a UI element that controls the sun’s position. This is particularly useful for ArchViz but its functionality can be extrapolated to any type of scalable value so it can be changed at runtime.
First we’re going to need to enable a built in plugin called “Sun Position Calculator’. This will require you to restart.
Then you’re going to head over to ‘View Options’ in the content browser and tick ‘Show Plugin Content’ and ‘Show Engine Content’.
Now click on the folder icon in content browser directory so you can search folders.
Type in sun to locate the ‘Sun Position Content’ folder.
When you click on that folder, you will be shown the Sun Position blueprint. Go ahead and drag that into your level.
Once that is in your level, it will be driving your sun-sky system. This will control all sorts of settings like the following.
Now that we have this bad boy in the scene, we’re going to create the UI element that allows us to control it.
So go ahead and create a widget blueprint. The first thing we’re going to do in the designer is drag a slider in.
This slider will act as our control mechanism for the sun’s position.
Once this is done, we’re going to hop into the graph so we can set up its functionality. We’re going to have to get a reference to our sun controller, so to do that we’ll just get all actors of class once when this widget is created.
Then we’ll store that reference for later. Next we’re going to need to add the event for ‘On Value Changed’ that is attached to the widget slider.
Then we’re going to take that value that it spits out (which is on a scale of 0-1) and we’re going to use a ‘Map Range Clamped’ node. This will let us remap that 0-1 to a different range. In this case we’ll make it from 7 in the morning to 8 at night. Then we’re going to get that reference from earlier and set its hours based on that value from the slider. Lastly, we’ll have to call the update sun function.
Once that’s done all we’ll need to do is add the widget to the screen so can manipulate it. To do that let’s just head into our level blueprint and add it to viewport.
The last two things we need to do are ‘Set Show Mouse Cursor’ so the player can interact with the UI element AND we’ll have to set the light source to ‘Movable’, which will let us update it without building lighting.
Once all that is set up we have a functional slider.
And as we slide through it, it will update the sun’s position.
So you can see how really anything can be mapped to a UI element and manipulated in real time with this method (Pretty much all UI based functions like audio settings, difficulty, etc).
Until tomorrow!
0 notes
Text
Day 31 - Puzzle Games
So I was going to go over quaternions today but I realized after spending nearly 20 minutes watching videos on it that I still could not grasp it. The concept is far too galaxy brain for me at the moment. So we’re going to talk about design theory again! Yay! So what goes into a puzzle game? We’ll be reviewing the youtube video ‘What Makes a Good Puzzle?’ from Mark Brown that covers just that.
The Rules
Each puzzle game has its own unique rules. These rules are really just limitations are used to create puzzles. Generally the novelty and depth of the primary mechanic within a puzzle game will dictate how complex it can get. So the more outlandish the mechanic, the crazier the puzzles can get. For example, perspective matters with Antichamber. Momentum and depth perception matter in Portal 2. Mental projection matters with time traveling in Braid-- you get the idea.
It is crucial that players aren’t attempting to figure out what to do when they sit down to play, but rather how to do it.
The Catch
Puzzles generally begin with a logical contradiction. For example, you need to pass a hallway. In this hallway there are turrets that will kill you if you walk by it. Turrets can be disabled by depressing a button. But you can’t depress a button AND move through the hallway-- so you look for another way. In that same room there is an object that can be placed on that button to keep it depressed and voila! Puzzles start with a contradiction like this that leads the player to analyze the environment and their tools in creative ways.
The Revelation
The revelation comes about when you are presented with a puzzle that requires you to think outside the box. Considering the mechanics of a game in a different light grants you a new understanding and thus a new tool in your toolbox to solve puzzles going forward. The delicate balance of this must be considering when you ask the player to do something that may not inherently be obvious-- which can cause frustration. While what you’re asking the player to perform may be a direct product of the game’s mechanics, if not hinted at properly, they may never make that connection.
The Assumption
Misdirection is a useful tool when designing puzzle games. Players can be forced to think in different and creative ways when you set up a puzzle that seems obvious on the surface but actually requires divergent thinking. Oftentimes if a new concept or mechanic needs to be introduced, they can force you to learn these them by giving you a starting point, then asking you to reverse engineer it and find the concept through creative thinking.
The Presentation
The presentation of the puzzle goes a long way in leading the player to the correct assumption. The placement of puzzle elements can subtly allude to the actions the player should take. Too many extraneous, non necessary elements can cause frustration and the more minimalistic the puzzle is less likely to cause confusion.
The Curve
Puzzle games build on the concepts they teach you and ramp up in difficulty as the game progresses. Square Enix Montreal uses a set of four criteria to determine how difficult a puzzle is.
The number of possible solutions
The number of steps required
The number of options the player can choose from
The number of mechanics the player needs to be familiar with
In Summation
A good puzzle is derived from a game’s rules and has a catch that, at first, makes the puzzle seem impossible. The developer then uses an expected player assumption to lead the player to a solution or revelation about the mechanics. Making sure to balance the challenge so that it is not too easy (the player can stumble into completion through assuming), or unrewarding (the revelation was not satisfying) is no menial task. One thing is for sure-- developing great puzzle games is a tricky craft.
See you tomorrow!
0 notes