After spending week 1 of this project entirely on the behaviour Blueprint, I moved on to making a more detailed model of the Robot based on my initial quick blockout. However I wanted to add some legs, just in case I want to add the ability to land and walk at some point. 1 - Modelling Before starting to model I did some quick sketches figuring out how the legs could work, but overall I kept the design fairly simple, since I didn't have much time to spend on it.
The model itself needs some optimisation. It currently has about 15000 tris, which I could reduce by baking some parts, like the "eye"/visual sensor.
I also originally planned to make the model more detailed, but didn't have the time, so I ended up not using them.
Since I wanted the legs to be animated I played around with some rigging and IK Solvers, again something that didn't get finished/ implemented in the hand-in version.
Experimental Leg IK
2 - Maxscript
Because I needed a small break from modelling and Litha had an issue with some Physics Simulation (it didn't work with her mesh), I wrote a small script to replace meshes with another one ( so that the Simulation could run with another mesh, that can then be replaced with her original one), just to see if I could do it. I came up with something very basic in about 30 min. We didn't have a chance to test it, yet.
Replace Objects Stript
3 - UE4
I also went around to adding rotation to the rotor. Essentially it has a defined rotation rate, but then compares current speed to maximum speed and adjusts the rotation rate based on that.
Rotor Rotation Blueprint
Figuring out how to rotate the eye to look at the player was slightly more tricky, because it doesn't rotate independently, but together with the robot's body.
In local space it would be very simple to limit the eye's rotation, by clamping it at the minimum and maximum rotation from 0.
However, since the player character moves in World Space, I had to figure out the eyes rotation in World Space as well. The solution to this was taking the Robot's body's rotation as the new 0, then adding/subtracting the maximum rotation angle and clamp the Look At Rotation based on those.
Look at Player
EDIT: Might have to change the way X and Y axis rotation is handled by using the robots local Rotation.
Going into the final 3 week project I wanted to work a bit more with Blueprints, so I chose one idea from the VFX Brief:
Small flying drone that follows
player, orientation controlled by velocity.
However, depending on the time, I would like to experiment with some other features for the drone/robot.
EDIT: The video's were made during week 3 of the project, so they have the current model instead of my placeholder one.
Placeholder Robot vs. Semi-finished Robot
1 - Location
I broke down updating the Robot's location into 3 parts, making seperate functions for each to keep it more organized, however, they still use each others results.
X/Y Location
Z Location
Avoiding Obstacles
1.1 X/Y Location
The way I currently update the XY-Location needs some improvement, I will go into the reasons whilst explaining, how it currently works.
Update XY-Location Overview
When updating the Location the function is currently checking, if the robot is supposed to follow the player. If not, then it decelerates from its current speed to 0 and waits until follow is enabled again.
If follow is set to true it checks, whether the distance to the player is below a certain threshold or an obstacle is in the way. Since I only want it to accelerate when both are false, using the logical "or" was the only way. I added a table to hopefully make this a bit more clear.
UE4 Logical OR
The logical OR only returns false, if both inputs are false, otherwise, since at least one input is true it, returns true.
Conditions
The acceleration is currently linear, I might see if I can change it to be exponential, maybe by using time passed since starting to accelerate or something similar.
For quite some time I also had the problem that I used a set value for acceleration, so depending on the maximum speed the robot wasn't able to stop in time and would get stuck in the player.
I was able to circumvent that by changing it from just adding a certain amount of acceleration per Tick to first of all multiplying acceleration by World Delta Seconds ( to make it frame rate independent ) and then by Maximum Speed squared ( which is then multiplied by 2 for deceleration, it seemed to work quite well ). That way the acceleration and especially the deceleration is exponentially greater, when the speed is higher.
Sorry about the bad quality, I will try to make a better video at a later point. The video also doesn't show the slower acceleration, that I changed to later.
Acceleration, Deceleration Setup
After figuring out the acceleration and changing the current speed, the current speed then gets clamped between 0 and Maximum Speed to prevent it from speeding up infinitely. I then multiply the normalized direction vector ( Magnitude = 1) by the current speed to get the velocity and update the Location by adding the velocity to the current world location.
Another small feature I added is adding the player velocity multiplied by an Alignment Multiplier to the Robot's velocity, so that it not only moves towards the player, but based on the player's velocity also head in the player's movement direction, which is quite nice, if the player is making sharp turns.
1.2 Z Location
Updating the Z Location has 2 parts as well. The first one is just a general up and down motion, to give a nicer floating effect. It uses two layered sine waves with different "wavelengths" and "waveheights" to create a slightly irregular Z motion.
Z Sine Motion
Furthermore I needed to make sure, that the robot stays above the ground at a more or less consistent height, so I made another function specifically for that.
It works, by linetracing straight down from the robot's location plus some offset on the Z Axis, so that it can move up terrain higher than its current Z location. However, depending on the current velocity the starting position moves along the velocity vector adapt to terrain height changes in time.
Stay above ground - Line Trace
Stay above ground Setup
Once the Line Trace hits something I can get the current distance from Robot to ground, compare it to the desired distance and adjust the Z location based on that.
1.3 Avoid Obstacle
The avoid obstacle section is definitely still a weak point in the movement system and needs quite a bit of polishing. Here I essentially had to make a choice between a 2D and a 3D approach, 2D meaning looking for unobstructed paths on the XY-Plane, whereas in the 3D approach the search happens in the XYZ Space. In the end I chose the 3D approach, because the 2D one requires at least one Direction on the XY-Axis to be unobstructed, because otherwise the Robot is more likely to get stuck.
After some research I found a thread on Stackoverflow, that explained several ways of equally distributing points on a sphere.
Link: https://stackoverflow.com/questions/9600801/evenly-distributing-n-points-on-a-sphere/44164075#44164075
Stackoverflow Code Examples
Also I found a great video on Youtube going into simulating swarm behavior, that used a similar approach in Unity, called "Coding Adventure - Boids" by Sebastian Lague.
Link: https://www.youtube.com/watch?v=bqtqltqcQhw
Points on Sphere Blueprint
Points on Sphere Visualisation
Essentially this function returns a set of vectors, that I can use to define the Line Trace Direction to check for unobstructed paths.
Per Frame the Robot goes through the following queries:
In Blueprint it looks like this:
Avoid Obstacle Blueprint Overview
Check for Obstacle
Find unobstructed path
As I said the system is not perfect by any means. Yes, it works in most cases, but sometimes the Robot's movement gets quite jittery, so I will have to see, if I can fix that somehow.
2 - Rotation
At the same time I was figuring out, how to update the Robot's Rotation. I decided to handle the rotation towards the player in World Space purely on the Z Axis and then I could handle the leaning/banking (X and Y Axis) based on velocity separately in Local Space. I also want the Robot to stop rotating once the distance to the player is below a certain threshold, I tried without it and crazy things happened.
Robot Rotation Blueprint Overview
2.1 Z Rotation
For the World Space Rotation I get the Rotation by using Find Look at Rotation on the with the Robot's Location and the Player Location ( again plus the Player's velocity multiplied by the Alignment multiplier ). I then use RInterp to update the Rotation over time for a smoother transition.
Z Rotation
2.1 XY Rotation
To create the banking/leaning into turns I compare the Z Rotation from the previous with the current Tick (X Axis Rotation).
For the Robot to lean forward when moving I compare Current speed with Maximum Speed and adjust the angle accordingly (Y Axis Rotation).
This was the last official week for the second project and I spend some time modelling some more assets and creating a small room.
Overall I am not happy with the outcome of this project. Yes, it probably fulfils the brief requirements, but nothing more. Maybe my goals were I bit too ambitious and I should have spend my time on just one asset and really polishing it, but I wanted to push myself with this project.
I will also definitely go back to this one and work on presentation, maybe adding some particle effects and textures.
After encountering the problem with the Rigid Body Simulation in Houdini and spending some time unsuccessfully trying to find a solution, I abandoned the idea, or rather left it as a stretch goal for the summative hand-in.
I then moved on to modelling a few assets for a small scene in Unreal.
1 - Swing Door and Sign
The first thing I worked on was modelling and setting up the Blueprint for a sign, that you can shoot of a wall. This was my first time working with physics constraints and after some fiddling with the parameters I got a decent result.
I added collision boxes to all the letters and on the upper corners of the sign and on overlap check, if it is the Player Projectile colliding.
Blueprint in action
I basically did almost the same for the swing door, only difference being the addition of an angular motor.
And it works ... mostly
2 - Chairs and table
Both door and sign where a pretty good warm up for moving to the table and chair. Both where a bit more complex, having more parts and being completely destructible.
I decided to build the in blueprint, rather than the destructible meshes, because of the issues I mentioned in the week 1 post and it gave me a bit more control. the downside was having to model all the pieces in 3DS Max, spending a lot of time fixing normals. However I managed in the end.
To simulate the destruction of those assets I again added collision boxes to check for collision with the projectile, but this time I had to figure out how to simulate physics, since for example the table legs consisted of multiple parts. I ended up parenting the meshes to the one above them, detaching the piece on impact and setting simulate physics to true.
I ended up taking out the ability to break the table top, it just felt a bit too dramatic...and unrealistic.
2.1 Table
2.2 Chair
Here is a clip of how it looks and works. I ended up replacing some chairs with static meshes, since a huge amount of BPs has an impact on performance.
With the new knowledge gained from the procedural crate generator I moved on to building a procedural bottle generator, so I'd have some more destructible objects.
Bottle Generator Overview
The interesting part hereby was assigning each edgeloop to a group via script, so that those get procedurally selected, instead of manually, which would only work for one specific configuration.
What I ended up doing is finding the correlation between edgeloop number and vertex numbers to define start and end point of each loop.
So the Start Point can be defined as: number of vertices in each loop ( total amount of points divided by number of loops ) multiplied by the loop number, and the End Point can be defined as: number of vertices in each loop multiplied by loop number minus 1, subtracted by one.
EdgeLoop Rule
Edge Group VEX
Those groups are then used to polybevel those edges to create a more rounded shape.
I then moved on to creating a fractured version of the bottle.
Fractured Bottle
Overall the bottle generator is very similar to the crate one, however I used some different nodes, like skin and boolean to create the shape.
In UE4 I did some quick tests with the bottles.
UE4
2 - Brick Wall
My original plan was to use Houdini to create a procedural brick wall and then bake a few animation sequences, similar to last years destruction project. However I ran into a problem, whilst working with the Rigid Body Simulation.
Brick Wall Overview
Again I procedurally generated the brick positions based on wall height and width as well as brick height and width.
Brick Location VEX
Brick and alternating end brick locations
When I moved on to creating the animation I started experimenting with Rigid Body Simulation settings, which worked fine until I glued the wall to the floor to stop it from falling over. That's when my collision object decided to stop interacting with the wall to which I was not able to find a solution.