top of page

Object Inspection System I C++ | UE4

(We went Back)

You might have played the game We went back on Steam. There is a crucial mechanic inside the game which lets you inspect objects with user-friendly smooth rotation shown beside this in a gif.

As a gameplay engineer on the team, I loved creating this mechanic and I am so glad to share it with you guys.

This article is explaining how I created and constructed the logic behind the smooth object inspection.

InspectionWWB.gif

Image 1.1

A note to the Readers..

"This was my effort to figure out and implement this mechanic and I do not claim that this is the most efficient or easy way as there are many ways to implement this and there might be a more efficient way than this too."

Before we begin I assume that you are familiar with Unreal engine and using blueprints, you are aware of vector math in 3D  mathematics. Especially dot product and cross product.

Let's start with understanding the coordinates first.

In the following image, there is an object and a camera targeted to look at the object. Two views are represented one top-down and other camera look view which is at the right bottom of the screen.

Make sure you understand the basic co-ordinates here in both views and how they relate. The Y-axis in the normal views and Z-axis in the camera view both are considered in the screen direction(popping out of your screen)

InkedBasic2_LI.jpg

Image 1.2

Which axis of the object do we want to rotate so that it rotates properly when you move your mouse on a 2D surface?

As I said we want to rotate it with a mouse, and a mouse has two-dimensional movement, Vertical and horizontal. Look at the following image which is the gameplay camera view, to understand what axes will we need to rotate.

Axis.jpg

Image 1.3

Here the green line shows vertical and horizontal mouse movement that we discussed. Now, look at the red lines representing the movement where Y is vertical and X is horizontal. Here for the sake of understanding lets call them Y and X. Here we ignore Z-axis for now. Also if you understand properly the Z-axis is representing the direction of the camera ie if we go into z-direction you will find camera.

Therefore it makes clear that we want to rotate the x and y-axis of the object to rotate it properly.

 The Implementation                                                                              

Tools used:

  • Unreal Engine 4.23.0

  • Visual studio

All assets showed in the pictures on this blog are property of Dead Thread Games LLC

 Blueprint implementation                                                                   

In a normal UE4 map, I just put a camera and an object as you can see in the below image. For demonstration, we will just jump into the level blueprint and get the references to get started.

Unreal Engine provides a lot of ways to rotate an object and I used the one showed in the picture here.

Also, it is pretty easy to add rotation with Unreal Engine's super convenient tools where you don't need to worry about going into too deep to calculate quaternions or other methods of storing rotation.

'Object_Polaroid' here is the object in the scene, which is just a blueprint with static mesh.

Make sure you change the mobility property to movable otherwise it won't rotate.

Rotation.PNG

Image 1.4

How do I calculate the rotation amount?

As we discussed in image 1.3 we want to rotate X and Y-axis.

To get those axes I will calculate the Z-axis(camera direction first) and then apply some basic vector math to get X and Y-axis.

DirectionZ.jpg

Image 1.5

As shown in the above image I need to calculate the z-direction. For that, I will use the basic way fo finding the direction which is substracting the vector(location) of one object from another and then normalize the vector.

gettingDirec.PNG

Image 1.6

Here I subtract the camera's location from the object's location and get the normal vector. Now we have Z-axis or direction, let's calculate the X and Y axis to rotate the object.

I will use the basic 3d math formula to get perpendicular direction Y by switching the two coordinated of the Z-axis as shown below. In the below image in a two-dimension imagine if we have one axes (x (1,0)) We can get the Y-axis easily by just switching the coordinates and negating one if we need reverse direction.

This also depends on the coordinate system you are following.

Yrota.PNG

Image 1.7

IMG_5548.jpg

Image 1.8

In image 1.7 we break the normal vector(the z-direction vector that we got earlier) and switch axis to get the Y-axis showed in Image 1.8 which is our vertical rotation axes. This is how we get the Y-axis.

Now time to calculate Z-axis. We know that the cross product of two vectors(A and B) gives us a vector(C) that is perpendicular to both of the two vectors(A and B).

In short A X B = C ; where C is perpendicular to A and B(at 90-degree angle)

And in three dimensions, all axes are perpendicular to each other which means Z is perpendicular to X and Y.

So if we calculate X cross Y as per image 1.8, then we will get axis-Z.

Following the images and back to our coordinate system, we use do the cross product of  Y and Z axis to get the X-axis which we were looking for.

Axis.jpg

Image 1.9

Hori.PNG

Image 1.10

So now that we have axis Y and X as per image 1.9, we will use the mouse rotation value showed in image below which also represents the angle of rotation.

mouseAxis.PNG

Image 1.11

As shown in image 1.10 we will calculate the rotation amount for both Vertical(Y) and Horizontal(X) axis and that will give us two different rotators ( a rotation value) which represents the amount of rotation we need to add into our object.

combine.PNG

Image 1.12

At the end, we just need to combine the rotators that we calculated earlier and add(combine) them to 'Object_polaroid's actual rotation. UE4 has built-in functionality to combine those rotators and then we set the rotation in the last node which you can see in the above image.

Note: All rotations are relative to the world. We don't deal with any local rotations here.

Note: The order of rotation parameters matters here when combining actor's rotation, we have to use parameter A as actor's rotation and then B as the rotation we want to add into that. If we switch the orders, then the rotation won't be added properly and it will result in incorrect rotation.

Following is how the full blueprint event looks like.

FullBP.PNG

Image 1.13

Whenever the object is in inspection mode, I call the above function on event tick and update the rotation every frame.

C++ implementation

 C++ implementation                                                              

Following is the code snippet wring the same function in C++.

The 'm_rayCastActor' is a type of AActor* that we are inspecting.
 

First, we will get the directional vector by subtracting the camera location from object's location. And just like I explained in Blueprints, we will get the horizontal and vertical directional vectors

 

Now we will create two rotators( horizontal and vertical) by using kismet library function and rotate the axis with the amount of rotation passed to the function(mouse movement amount i_Verticle and i_Horizontal)

 

At the end, we combine those rotators and apply the rotation to the object.

One thing to be very aware of here is that the order matters when you combine the rotators. The first parameter geometry system is the target when you combine rotators if you flip them then it will result in incorrect rotation.

Therefore we need to use ActorRotation as the first parameter.

Bonus: You can also draw debug lines including the Kismet/KismetSystemLibrary.h and using the following function. This is very useful when you are debugging to make sure the axis vectors you are creating are correct.

Following is the whole function code snippet for the similar things I achieved on Blueprint.

Please include the following headers in the .cpp file where you are writing this function.


Kismet/KismetMathLibrary.h ( for using Mathamaticasl functions)

Kismet/GameplayStatics.h ( for getting player camera manager or player )

Kismet/KismetSystemLibrary.h ( for drawing debug line )

Feel free to copy and use the above code.

 

Thank you so much for reading. I hope it was informative. I am very new to writing blogs and guides and this was my first attempt to actually write a public blog like this. Pardon me if there was something that was confusing or explained in a wrong or incorrect way.

Any kind of suggestions are most welcome :)

-ROHAN PATEL

A Video game developer

bottom of page