Project WAM: Learning How Games Tick, Unreal Engine 4, Blueprints, and Learning How to Get Off My Ass

 

Hello! My name is Earvin Ramos and I’m an amateur independent developer looking for work. I’m currently taking ideas and trying to expand my portfolio with more works, with this project being the first. Now, one may ask: “Why? Aren’t you a sound person? Why are you learning Mudbox?” Well, I like making things. At first, I thought it was just music and audio, but I realize I like to create in general. I like creating things and seeing them come to life, so developing inside of an engine and seeing my own creations come to life is amazing. It inspires me and makes me feel like I can keep going, and if it’s expanding my skill base and makes me worthwhile as a developer then “two birds one stone.” It keeps me from going crazy while I look for work, and it helps keep my output lively so I don’t feel like I’m stagnating or succumbing to depression. This is what is “getting me off my ass” so to speak. I need this so that I don’t feel like I’m stuck doing nothing.

So that fact brings me to my first fully independent project. I’ve done some small indie work with friends, and prototyped/made various tools and things before on various platforms independently/with some help. Project WAM, however, is my first thing from the ground up. The basic premise is simple: most games nowadays don’t use fixed cameras anymore. Game developers seem to be focusing on third person camera that tracks and follow a player on some kind of spring arm, or a first person camera entirely. Now, this is not to say that either perspective is bad: these are the basic building blocks of gaming. However, I miss fixed cameras. There are layers to the idea that make it incredibly rich as a perspective to see a gameworld from.

Why Fixed Cameras? Get With The Times!

To quickly summarize the latest “fixed camera” showings I’ve seen that influence how someone interacts with a game, I present a game that has released in the past few years: Republique.

Republique uses its camera system to a thematic focal point: the voyeurism that is inherent to the “fixed camera” mode of perspectives is hard coded into Republique. Rather than feeling like we’re following a character and, via emotional proxy, ARE that character, fixed cameras allow us to feel that we are connecting to a character while retaining our identity and autonomy as a participant. In Republique, rather than feeling like we are Hope per say, we always remain “ourselves.” In fact, this is weaved into the narrative. We are a third party who, through the miracles of hacking, can now assist Hope in escaping. Now, this isn’t always present: When you’re playing Resident Evil, do you feel as if you’re a survivor of the Arklay incident or Raccoon City?

Yet, we still feel intrinsically tied to these characters on an emotional level: Resident Evil 2 is a game I still connect with to this day. Though I personally don’t feel like my actions are what caused Leon and Claire to survive their nightmare, I still feel like I bore witness to it. Again, I feel like I participated in the story without being an active force. Though I am in control of Leon/Claire, it still feels like they are moving and I am witnessing to. Through the action in the game, I feel tied to it. I fear when I’m limping around on Danger, and I see Mr. X coming down the corridor. And this is the beauty of fixed cameras: Because my view into the world is fixed, this adds layers and layers to the gameplay. The feeling of being out of control of the world around me with the only thing I’m in control of is Leon/Claire, this concept creates an amazing duality of feeling strong and powerful, yet weak and powerless.

However, the main idea is this: Fixed cameras allow an uncanny, quantum voyeurism to exist in the fabric of the game that employs them. You are the fly on the wall, the Seer, the Watcher, and yourself.

Now, some might say that harms “immersion,” that being the fly on the wall is not the point of gaming. We want to be Nathan Drake, or Ryu, or Commander Shepard, or whatever we want to be. To some, games are about wish fulfillment: because we can not attain this status or identity normally through our lives, gaming acts as the medium that transforms our identity from that which we are to that which we wish to be. I think it’s a little bullshit, especially when it comes to survival horror. This is why Resident Evil 7 is so warmly welcomed by the fan base after 5 and 6. As the characters became more veteran and the action-moviesque production that went into the game got more and more the thematic focus, everything that scared us about the original games was so clearly lost. Now 7 doesn’t fully go back to its roots, but it taps into the same ideas. Though we tap into Ethan as our “identity” in the game, because he is so much like ourselves we connect with him instantly. Not in the idea of being male, but in the idea of being a powerless human being that stumbles into a hellish nightmare. Now, why does that sound familiar?

In any case, that’s why I feel like starting this project: to explore the idea of fixed cameras, how it shapes and influences gameplay and interactivity, and how to tap into what scared us so well in the past yet is largely ignored by the games of the present.

Working with Unreal Engine 4 and Blueprints

With that spiel done, let’s move on to what you are probably more interested in: how I’m going about implementing things in Unreal and its Blueprints system. Blueprints, as I’ve said many times to many friends as I’m learning, is “for BABIES.” Now, this isn’t a negative: Blueprints is fun, easy to use, and great to work with. Also, I’m not claiming to be an expert on it either. I’m not a programmer, I’m just a creative that likes to program. After, for various reasons, learning C# and dabbling in Unity, I felt like retreating back to something easier. The visual scripting of Blueprints fills this need for me. Thus, if you see me doing stupid things, or saying things incorrectly, or doing things inefficiently, please cut me some slack. Or, better yet, teach me how to improve. We all learn from each other into this new digital Youtube-tutorial age, so the more we learn from each other the better.

My first goal in setting up Project WAM is simple: Navigation. Building prototypes from the ground up, as I’ve learned before in my experiences, is key to getting a game started. Start with core functionalities that make a game “a game,” then from there, you add the bells and whistles. Too many people think “Wow, I want to make a game kind of like Pub-guh but with THIS element instead of this and you do THIS instead of that and oh my god I have the next hit on my hands!” I’ve learned that this is truly not how it works. I forget where I read it from, but one lesson I’ve learned is that you have to make sure things are fun to play as a game. You’re making a game, first and foremost. Don’t write novels in your design documents and work on the socio-economic idiosyncracies of warring states in your universe if you don’t even fully know how your attack system is going to work. So, even though I personally have ideas in mind of what I want the overarching impression of the game to be, I started at the basics: Navigation.

Navigation

Dealing with Navigation is super important, you have to be able to move. However, UE4 is incredibly simple: for your player character, you no longer have to set up a pawn and have the player control it. Now, most of the functionality of this, specifically to create a standard character that the player controls using the Character Blueprint. With basic functionality in mind (such as jumping, walking, crouching, etc.) in place for you already, the Character Blueprint template is a great way to get started. However, I found myself needing a bit more functionality than that. In essence, I needed to make a full tank control style with multiple states, so my Blueprint was expanded:

Movement Blueprint 6/2/2017

(If you need to, you should be able to right-click and open the image in a new tab for its full size view)

Now, this is a basic movement blueprint I have set up to track and control 3 different states of non-rotational movement. They are: Walking Forward, Running, and Walking Backward. They all have a variable speed and weave into each other in different ways. It is tied to the input axis of “MovingForwardBack”, which is mapped to W in the positive and S in the negative. To quickly explain the flow (which I significantly decluttered for this), it first checks if the character is Aiming, a functionality I’m planning for but haven’t fully implemented. This is the True portion of the IsAiming Branch. When I am aiming, it turns the IsMoving and IsWalkingBack flags false. That was super important to debugging my animation states when I had to add this functionality after I was done setting up my animation states.

After that, it checks if I am actually moving in any direction (the axis can be positive or negative, so you are moving if you are pressing either direction and making the axis not-zero. Interestingly, if you are pressing both W and S, the input zeros out and you aren’t moving. Thus if you are moving, in any direction, I track that using IsMoving.

One note of importance is how my Blueprint checks for which speed to use while moving the Character. The final speed that is applied to the character is a value called “SpeedApplied.” SpeedApplied is then filled in by other parts of the Blueprints. By using the final Add Movement Input function, I can use this final speed and directionality in conjunction with the preexisting Character Blueprint settings (like walk speed, etc) to move the character. I found this MUCH EASIER, as before I had written it using Actor transforms. This caused my Character to interact funny with falls, he’d topple over for some reason, etc. It was so frustrating that the only way to rid myself of it was to take out the old Actor functions and use the more “standard” Add Movement Input function.

Next is the IsWalkingBack check. If the input axis is less than zero, then you must want to walk backward. Why is this important to track? In my inspiration games for this project, walking backward is significantly slower than walking forward. It also has a different “oh god what is this in front of me” animation. It checks if the input axis value is less than zero, and if so it returns True and thus IsWalkingBack is true. This causes a set of SpeedApplied to be SpeedWalkingBack, and thus our new movement speed is the walking back speed.

If IsWalkingBack is False, then it moves to an IsRunning check. Running is simply holding down the Run button. Pressing it down makes IsRunning true. This is important for flow reasons. If the character is holding down the run button while you are WalkingBack, I wanted to set it up so it does NOT use the running speed at all. Using this as a flow modulation point ended up serving my purpose, as now it is impossible for the game to recognize running if you are walking back, so walking back always results in a slower speed despite the pressed state of the run button. If it is true, then it applies SpeedRunning and our new movement speed is the running speed.

If both IsWalkingBack and IsRunning are false, logically the only thing left to track is just plain walking. This is the plain SpeedWalking variable. This feeds into the scale variable of the Movement function, which bless Epic Games I didn’t have to write, and moves the character to this float speed.

The last thing of note is the direction of movement, the yellow Vector3. This I actually caught from a tutorial. Because I’m only working in 2D space, which is the Yaw, I only have to get the character’s Yaw rotation, make it the sole rotation, then get a forward vector of the Yaw (which is where the character is facing). This feeds into direction Vector3 of the Movement function.

And thus, movement! This reacts well and tracks all the states I need. The Booleans I used in hooking up my animations states with a cast (more on this in a later post), all variables are editable so if I want to change speeds it’s as easy as plugging in new numbers, and additional functionality should be expandable (I added IsAiming as another check today before I started this blog post).

rotation and Bools

And now, Gals and Ghouls, it’s time to talk about Rotation and Bools. Rotations had their own set of problems that I didn’t notice until I started to play test the prototype. Booleans help control flow and are simple enough that I was able to set them up.

362b9e0a768cfb4f8e29afd502d4d4c1

(Again, Right Click Open Image in a New Tab for full view should work)

Rotation is very simple. It is driven by the rotate Right-Left axis, with right being positive. Again, first I tried to use an Actor Rotation set, but that was very buggy and disgusting. I’ve instead changed it to Adding to the controller’s Yaw Input instead.

The game sets a boolean of IsRotation to show that the character is rotating. Rotation can be accessed from any state, so there are no limitations or branches. This, however, is specific to a tank-control style rotation. It rotates independent of the camera, only using the controller’s yaw instead of a viewpoint’s yaw. So, when you hit right, it moves the character to the right. When movement is applied, it also continually updates the yaw rotation as well, so you can do lines in the game as well as the forward vector of the character is always accurately in front of them.

Rotation is simple and elegant. Also of note, I have a Get for the World Delta Time. THIS IS IMPORTANT! For some reason, this rotation is tied to frame rate and I only learned this during my testing. My Editor viewport was running at 120, but when I tested in a standalone game setting, the game was locked to 60. Somehow, all my rotations were 50% slower. Thus, I tested it using t.MaxFPS in the viewport and lo-and-behold, the rotations were again inaccurately slowed down or sped up depending on the FPS. in order to get rid of this, I set the scale of the rotation to be influenced by the world’s Delta Time, multiplied by about 100, to get the scale in the right place again. Now the rotation is the same, independent of the frame rate

The booleans at the bottom are again, self-explanatory. While tied to the input actions (which have a pressed and released state), each one describes to the Blueprint if I am Running or Aiming. The intended functionality is that IsAim supersedes all movement (though not rotation), and Walking Back has priority over Running.

Setting up cameras and switching them

Now, this functionality is a bit trickier. How do you get it so that you switch cameras in the game when a character moves around the map? One approach I’ve seen is with barrier triggers. When you walk through a barrier, you trigger a camera switch. However, this screamed potential bugs at me. What if you somehow miss a barrier? Then the camera won’t update, and you’ll have a shitty view. Not that I completely avoided this, but it seemed a lot easier to do with a “barriers” set up.

The best functionality I saw was from getting colliders the size of whatever room/view you wanted, then tying the camera switch to when the player enters the collider. This functionality worked perfect for me, with minimal bugs that I can iron out by hand.

However, how do I get this up and running? In one room, there may be anywhere from 1 camera to 3 for a smaller room, and even more for larger ones. How do I keep track of them, and how do I avoid rewiring the same Blueprint over and over?

I learned how to do this with Actor Component Blueprints. By creating a script I can throw onto a collider, I can tie that collider to a camera and have the same switch code activate each time I switch cameras regardless of which collider was firing. Here’s what it looks like:

ef9261df0de1a405fae8780251c39cd4

This is the Actor Component Blueprint I use for Camera Switches. It starts at BeginPlay, and passes through after. So, there are two tracked variables which represent objects: The ColliderBox and the SelectedCamera. These are variable objects that I can select after I attach the script to another Actor in my scene (usually my collider box). I select which Collider I want and which selected camera I want, and this associates the two in the script.

The BindEvent binds it to a specified event that can happen with the Target (in this case, in an OnActorBeginOverlap event), and brings the event into the component script. This has a potential if there are more actors that can trigger collisions, but I can probably use the overlapped and other actor nodes for a check. I’ll work that in when it happens.

The great thing about making this a component script is that I can change the script once and have it apply to all components thereafter, so I don’t have to redo each object every time I add functionality.

Now, getting the player controller is kind of weird here but it’s required for this next function. Not sure why. In any case, once the overlap happens I can switch the camera to this one.

This functionality doesn’t work for the FIRST START of the game. Thus, I had to make a second component script that DOESN’T call for an event trigger at all, called it StartingCamera, and added it to the camera I want to be the starting view of the level.

68ef117016e51e0636a22c741f246a6f

So, with this functionality of the Component script in play, I can just select the script component, set which box (usually the same box I placed it on) and camera I can to function with, and that box will have the same switch function every time.

First Prototype


And so this takes me to about here in the prototyping phase: my first prototype release. This is after I had realized that Add Controller Yaw was frame based but before I added the Aiming flags. It shows off all the I had here actively in a game. Lighting is temporary and the game is simply blocked using UE4’s geometry tools and has some starter assets.

So what’s next for the prototype? I want to get item and landmark interactions down in the game. Inspecting, picking up items, maybe inventory, and other things like this will be up next. This hopefully shouldn’t be too bad. Fingers crossed!

Notice, again, I haven’t mentioned art style. I haven’t mentioned characters. I haven’t mentioned story. I haven’t mentioned the themes I want to explore. All of this is left open ended, and in that there is a beauty of possibility. When walking around this environment, I got some serious ideas of directions I can take this. I can use this as a starting point for an adventure game instead of the survival horror I had in mind in the first place. I got an idea for an art style I originally didn’t consider or recognize as a potential path. Keeping things simple and forgetting the small details to focus on the big picture of what makes this “a game” is giving me achieveable milestones that help keep my roadmap malleable and flexible.

Leave a Reply

Your email address will not be published. Required fields are marked *