Hello and welcome to my second Role Analysis assignment! For this role analysis, our theme was “do something in a new engine”, as we wanted freedom to do whatever interested us but we also wanted to ensure that it would result in all of us being more well rounded. I have decided to learn more about Unreal Engine for this assignment.
To begin with, I wanted to just learn some of the basics of the engine. Installing it already proved quite difficult, less due to the engine and more because of C++ creating many issues. However, once I worked through that and I could open a project, I decided I would start with learning about blueprints and creating a simple character controller. I started with this video: https://www.youtube.com/watch?v=2xqecl73UG0
The video showed me there was simply a character blueprint, so I made one of those and hit my first road block. I do not have a skeletal mesh and I planned on just using some sort of cylinder or capsule for my character controller. I could make a cylinder in the game view but could not figure out how to make that mesh accessible within the character blueprint to set as the character’s mesh. I ultimately decided to just try and drag the character blueprint into the scene and use the “attach to” option when right clicking to attach it to a capsule I had made in the scene.
I adjusted the transform’s position of both the character and the capsule and it at least appears to have worked. I moved on hoping that was indeed the case. I followed the video making input axes and setting up the base functionality. Then I got to a point where I needed to add the character I had made so far into the gamemode as default pawn class. I did not have a gamemode of my own and the defaults did not make sense to me, so this was my next road block. This documentation helped me learn how to make a gamemode and then I was able to do what I needed: https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/HowTo/SettingUpAGameMode/
I continued through to adding a camera to the character and this is where I learned that simply attaching my character to the capsule did not yield the effect I wanted with making the character look like a capsule. However, after adding the spring arm and the camera to the character blueprint I realized that I could just add the sphere within the blueprint itself and not have to enter a value for the skeletal mesh at all.
This achieved the look I was going for! From this point forward the tutorial was easy to follow (with pauses) and I had no more hiccups. This yielded me a character I could move around and a camera I could control! Next, I wanted to move on to my secondary goal, which is to recreate my previous role analysis within this engine. To begin this portion of my role analysis, I figured I would try to make a cube that could accept inputs E and R on the keyboard and use them to change color.
Within project settings I added two new action mappings for the player pressing E or R:
Then I made an Actor blueprint (the description of this blueprint made it sound like the kind I needed) and added a cube to it, then added my two new action mappings:
Then I made two custom materials for Green and Red, the colors I would be using for E and R respectively. The goal is to make it green when attracting and red when repelling. Here is the logic for making the cube green (the same is used for repel accept for making the material red):
And… it did not work. I compiled and saved everything but when I started the gameplay scene with the new magnet object in front of the player, no button presses would affect the cube at all. I changed the logic to a simpler version:
But still no effect. I then started trying to use Print statements to see if the input was even being accepted. Within the Magnet object it did not work, so I tried in the Character blueprint just to see if it would work at all and it did accept the input! So I needed to figure out why that was.
After a considerable time spent searching the internet for tutorials on what I was trying to do (with no luck), I decided to just go component by component through the Magnet object and see what I found. I ended up finding the Input component which at first glance seemed to accept input (block input was disabled). However, I noticed that auto receive input was set to disabled anyways! I changed it to Player 0 and…
It works! However, that’s not all my first role analysis did. Now, I need to add the magnetic forces around the cube and I can move on to my next project in the new engine(I am recreating the functionality, I won’t recreate the whole map I made the first time for testing)!
My immediate goal with recreating the magnetic effect from my previous role analysis is to follow the same principles I did before and simply add force towards or away from the magnet object onto the player. Unreal seems to have a couple ways of adding force to objects, so that doesn’t seem to be a big issue. The main concern I am finding is that I am not sure how to calculate the direction from the player to the object (so I can use that or reverse it for adding force towards or away from the object). However, first things first I suppose! I added a collision sphere to the cube and unchecked “hidden in game” so I could see the magnet zone without needing any other objects attached to it.
Then I tried adding some logic found in this video: https://www.youtube.com/watch?v=Fijq5z0K8Co
To try and find when an object begins to overlap. I could not find the same node the person in the video used though for a while until I realized I had not attached the collision zone to the root node. Once attached, I was able to find “On Component Begin Overlap” and could continue with my test. My next challenge was that I created this logic:
And it seemed to work, kind of, but only on the initial overlap of the player and the collision zone. I say kind of because it still did not add force to the player object even if it printed true. As far as I can tell, the player object would need to have “simulate physics” on in order to add force to it, but if I turn that on then the character controller portion stops working.
I spent a bit more time trying to figure this out before deciding I just needed to take a step back and figure out how to, at any time, find the overlapping objects and find out if one of those objects is the player. Then, if I press the button and the overlapping object is the player, get something to say true. I started with just trying to find if the player is currently overlapping the area. I landed on this logic allowing me to take my first step (and even after placing the nodes, it took some fiddling to get it to actually work):
The resulting functionality is that every tick, the game checks if the player is overlapping the collision sphere or not and then prints true or false. This is what it looks like in the editor:
So, the magnet can officially sense when the player is overlapping the sphere, step 1 done! Now, I want to be able to trigger this on a button press. I am not sure if this will function how I want it in the long run, but my initial guess is to just replace the Event tick node with one of (or maybe both of) my E and R inputs. I tried this:
And the result was:
Success! In this gif you see me press E and R each twice inside and outside of the zone, and it properly checks and gives the correct output! Alright, step 1 done. This portion was greatly aided by these resources:
https://forums.unrealengine.com/t/getting-object-reference/427312
So, I can finally tell when the player is overlapping the magnet area and trigger it on E or R. Now, I need to figure out how to use that power to attract or repel the player from the object. My previous troubles with simulate physics persist, so I need to find a way to add force to the player without losing the movement control. After some research (https://forums.unrealengine.com/t/how-to-control-the-character-and-use-simulate-physics-at-the-same-time/463179), it seems like my best course of action will be remaking my player class/actor and giving it custom movement. That way, I can have a controllable player character that can also be impacted by physics and physics commands. I found this video which seemed to include most of what I would need to create: https://www.youtube.com/watch?v=k0JTL3YG8Go
I followed the video and got the movement to work! Here is the logic I ended up with at the end of the video (having added a little from my previous camera controls and beginning to start a jump mechanic).
However, when I tried to turn on simulate physics, once the cylinder hit the ground it would no longer move. I tried keeping simulate physics and turning off gravity and well when I jumped:
So, I must find a middle ground. I remember that in the video the person mentioned that the Sweep check box on Add actor world offset helped with collisions so I tried turning it off and turning gravity back on. Luckily, this allowed the cylinder to move around again! And, even better, the cylinder still collided with the squares on the inside of the magnet zones which is what I was concerned would go away if I turned off Sweep.
So, I have a functional character controller now, albeit a little more rough than before, but it works with physics. There are still a couple problems, however. The character’s movement is decided purely by global movement, so when I turn the camera it continues to move in the same direction as before which is quite unintuitive. Additionally, when I run into the boxes, the cylinder object itself can get tipped over and affected by physics, making the movement act even stranger.
The cylinder tipping over was fairly easy to fix, I went into the actor and on the cylinder object I just froze the rotation of X and Y axes so it would not tip over. I figured out which axes needed to be frozen with trial and error, and unfortunately picked this one last, but it works!
So, one problem remains, trying to get the object to turn along with the camera. And… Well it took me a very long time. I tried all sorts of variations, so I am just going to post a screenshot of one of the variations I attempted to give an idea of the type of thing I was trying witch slight variations (like changing from relative to local to world etc)
I realized after moving on from this idea that the forward backward and the left right aren’t even matching, but it can display how lost I was during this process. Eventually I began trying to do some math with the camera forward vector, which started SLIGHTLY affecting the movement based on the camera’s position, which was a start at least.
It still just really didn’t want to work, though. I got to a point where I really figured some sort of vector manipulation would be the key. It was at this point I transitioned to this logic:
And it was getting quite promising! Every movement button (WASD) had essentially the same effect (although W,A and S,D were forward and backward respectively) but it WAS based on the rotation of the camera! So, I was quite close to unlocking the type of movement I so desperately wanted. First, I made it so that A and D would actually make the cylinder move side to side instead of doing the same thing that W and S were doing by changing the logic to this:
Swapping the X and Y values rotates the vector! Now, you may notice that the Z (height) value is still being considered and that is indeed causing some issues with the cylinder moving EXACTLY away from and towards the camera including the height, which I do not want. The solution to this is to once again split the vector input/outputs on these nodes and only feed in the X and Y values into the Add Local Offset node, like this:
Also, after this step I realized that the vector for Right/Left was not quite working right. Some rotations worked right and some rotations worked opposite of how it should work. After some brushing up on vector math and cross products (https://en.wikipedia.org/wiki/Cross_product), I realized I needed to negate the Y value for it to work 100% of the time:
Now, finally, the custom movement is done! There are still some issues, like for example if you move diagonally (holding W and A or S and D, etc) then you move faster than just one direction at a time. If this was going to be a more robust game then this is something that would need to be addressed, but for the purposes of this role analysis, it will be ok. Especially since this system has already taken me way longer than expected, I think figuring out how to fix that would be a waste of my time in terms of getting more comfortable with Unreal.
For this role analysis, the last thing I now need to do is to take that previous logic of sensing player overlaps and using it to add force to the player in the proper directions (attract or repel from center). First, I adjusted the old logic to now work with the new player character since it is a pawn now. I changed the type of the actor it is looking for and put the CustomCharacter in instead of the old character. Seen here:
And, the previous functionality works. So, now instead of printing debug statements I want some force to be added. I know there is a difference between Add Force and Add Impulse, so I tested each of them to find the right “feel” without having the logic for deciding the direction of the force. The general structure now looks like this:
But I am having trouble getting a reference to the character object in a way that will allow me to add the force to it.
After looking over previous screenshots and how I was attempting to add force earlier, I realized that I was using the incorrect Add Force! I did not realize there was a difference, but I swapped to the kind that says “Target is Primitive Component”. I also swapped to Add Impulse, as you’ll see in the next screenshot, but the problem of swapping to the properly labeled one is the same for both Force and Impulse. I ALSO reorganized my code a little bit to be a little more linear as I am starting to pick up some of this visual scripting. With all of those changes, here is the new code and a gif of the results!
Zoomed out to see new flow:
New specifics for impulse:
I am nearly there! Force is being applied to the object with both keys. Now, I just need to make it a continuous force (might need to swap back to Add Force instead of Add Impulse) and I need to make it actually attract and repel and not just apply force in 1 direction.
I got the Force to apply continuously (as long as the button is held) by simply adding an Event Tick Node like this:
But something I realized was that because of the way I was storing the player character, the impulse could be added from inside or outside of the affected zone now. To fix this, I added a boolean to track if it is currently overlapping as an additional check, and made sure to check this boolean before adding the force:
And with that the force is only added when inside the area of effect! This will be seen in my final gif when I can also get the directionality of the force correct.
Time to get the direction! I am hoping to do some vector math like how I did for the camera to function. Lucky for me, one google search led me to this site https://blueprintue.com/blueprint/o7lswigq/ which has essentially shown me that all of the math I need to do exists in Unreal already! So, I just copied this structure as well as normalized it, then I split all the values so I could multiply each one to become a good amount of force (I maybe could have skipped splitting, but oh well). It looks like this:
While testing this (it works), I noticed that the behavior of my Currently Overlapping boolean is a little strange. I realized it is because all of this code on top doesn’t get called until I have pressed E or R so there is no reference to the player object for it to compare and set the boolean. I did some MORE restructuring which ended up with my logic like this:
The main difference is that I realized the push and pull logic on the right hand side is all connected to that Event Tick node so that it could all run independently, so I just took the place where it got the reference for the player and put it after the collision begins node. It all works properly now, and I might say that by the looks of my logic getting cleaned up, I am starting to get the hang of this.
I digress, it is time to wrap this thing up! I added the same logic for calculating the direction vector for attract and just multiplied by a negative number to get it going the opposite way as repel. I tweaked some numbers (and remembered to uncheck Vel Change for both of them) and…
It all works as expected!
This project was a rollercoaster for me. I hope that it is clear that this writeup follows my LEARNING process. Towards the end I was definitely making much better decisions and doing much cleaner work than the beginning. I also started in a new engine without really following any large guides. I had a couple in there, but I was really piecing together guides as I went towards a larger picture, which in many ways (as we saw) was much harder. In the end, however, I feel much more confident in this engine and I hope for my next role analysis I can use it again with much quicker success. Thank you for reading!