Creating a camera tilt gauge

ui tutorials

2/10/2025

Mihail Todorov

A camera tilt gauge is a valuable UI element in many games, helping players stay oriented when navigating uneven terrain, flying vehicles, or controlling a dynamically tilting camera. Whether you’re designing a racing game, a flight simulator, or an action-adventure title, a well-designed tilt gauge can improve player awareness. In this guide, we’ll explore how to create a functional and visually appealing tilt gauge using UI elements and game logic.

Setting up the gauge

First, let’s create the basic HTML structure for our camera tilt gauge. We’ll use a combination of HTML and CSS to design the gauge.

1
<div class="side-scroll">
2
<div class="scroll-item">
3
<div class="dash"></div>
4
<div class="dot"></div>
5
</div>
20 collapsed lines
6
<div class="scroll-item">
7
<div class="dash"></div>
8
<div class="dot"></div>
9
</div>
10
<div class="scroll-item">
11
<div class="dash"></div>
12
<div class="dot"></div>
13
</div>
14
<div class="scroll-item">
15
<div class="dash"></div>
16
<div class="dot"></div>
17
</div>
18
<div class="scroll-item">
19
<div class="dash"></div>
20
<div class="dot"></div>
21
</div>
22
<div class="scroll-item">
23
<div class="dash"></div>
24
<div class="dot"></div>
25
</div>
26
<div class="scroll-item scroll-item-active">
27
<div class="dash"></div>
28
<div class="dot"></div>
29
</div>
20 collapsed lines
30
<div class="scroll-item">
31
<div class="dash"></div>
32
<div class="dot"></div>
33
</div>
34
<div class="scroll-item">
35
<div class="dash"></div>
36
<div class="dot"></div>
37
</div>
38
<div class="scroll-item">
39
<div class="dash"></div>
40
<div class="dot"></div>
41
</div>
42
<div class="scroll-item">
43
<div class="dash"></div>
44
<div class="dot"></div>
45
</div>
46
<div class="scroll-item">
47
<div class="dash"></div>
48
<div class="dot"></div>
49
</div>
50
<div class="scroll-item">
51
<div class="dash"></div>
52
<div class="dot"></div>
53
</div>
54
</div>
1
.side-scroll {
2
height: 29vh;
3
overflow-y: hidden;
4
width: 3vh;
5
position: absolute;
6
display: flex;
7
flex-direction: column;
8
top: 50%;
9
transform: translateY(-50%);
10
}
11
12
.scroll-item {
13
display: flex;
14
align-items: center;
15
margin: 1vh 0;
16
height: 1vh;
17
}
18
19
.scroll-item-active .dash {
20
width: 1.4vh;
21
}
22
23
.scroll-item-active .dot {
24
animation: dot 0.5s forwards;
25
}
26
27
.dash {
28
width: 1vh;
29
height: 0.1vh;
30
background-color: white;
31
position: relative;
32
transition: all 0.2s;
33
}
34
35
.dot {
36
width: 0.7vh;
37
height: 0.7vh;
38
border-radius: 50%;
39
border: 0.35vh solid #faeac3;
40
margin: 0 0.2vh;
41
}
42
43
@keyframes dot {
44
from {
45
width: 0.7vh;
46
height: 0.7vh;
47
}
48
to {
49
width: 1.2vh;
50
height: 1.2vh;
51
}
52
}

To create a balanced design, we’ll add side-left and side-right classes to the side-scroll elements to position them on either side of the screen.

1
.side-left {
2
left: 3%;
3
}
4
5
.side-right {
6
right: 2%;
7
align-items: flex-end;
8
}

Additionally, we’ll reverse the order of the dots and dashes on the right side to create a mirrored effect.

1
<div class="scroll-item">
2
<div class="dot"></div>
3
<div class="dash"></div>
4
<div class="dash"></div>
5
<div class="dot"></div>
6
</div>

Controlling the gauge

To control the gauge, we’ll implement some JavaScript functions: one to handle the camera tilting upwards and another to manage the downward tilt.

1
const scrollContainers = document.querySelectorAll('.side-scroll');
2
3
scrollContainers.forEach((container) => (container.scrollTopVH = 5)); //We need to move the scrollContainers a little bit in the beginning so they match the camera level
4
5
function scrollDown() {
6
scrollContainers.forEach((container, index) => {
7
container.scrollTopVH += 0.2;
8
9
if (container.scrollTopVH >= 8) {
10
const activeDot = container.querySelector('.scroll-item-active .dot');
11
activeDot.getAnimations()[0].currentTime = 0;
12
container.scrollTopVH = 5;
13
}
14
});
15
}
16
17
function scrollUp() {
18
scrollContainers.forEach((container, index) => {
19
container.scrollTopVH -= 0.1;
20
21
if (container.scrollTopVH <= 2) {
22
const activeDot = container.querySelector('.scroll-item-active .dot');
23
activeDot.getAnimations()[0].currentTime = 0;
24
container.scrollTopVH = 5;
25
}
26
});
27
}

In the code above, we adjust the scrollTop property of both scrollContainers. We then check if the scrollTop exceeds a certain threshold (or falls below it when the camera tilts up). If it does, we reset the scrollTop and the animations, creating a seamless infinite loop.

There are a few things to note. The numbers used for the checks were tested specifically for this UI, so they may need to be adjusted for different use cases. Additionally, we take advantage of the scrollTopVH property available only in Gameface to avoid additional JavaScript operations and save on performance.

Integrating with Your Game

In this example, we’ll integrate our camera tilt gauge into a sample game created with Unreal Engine. We’ll demonstrate the implementation using blueprints, building upon the logic of the Third Person base game in Unreal.

For detailed instructions on integrating Coherent Gameface with Unreal Engine, refer to our previous articles.

Sending the data from our game

To achieve this, navigate to the ThirdPerson character blueprint and find the EnhancedInputAction event listener.

Next, we’ll cast to our CoHTML object. In this example, we’ll use a plane, but it could also be a HUD.

Next, we’ll use the Y value from the event to determine if the camera is tilting up or down and then send the corresponding event to our UI.

Receiving the data in our UI

With our JavaScript functions in place, we can now use the engine.on function to listen for the events and execute these functions accordingly.

1
engine.whenReady.then(() => {
2
engine.on('cameraUp', scrollUp);
3
engine.on('cameraDown', scrollDown);
4
});

In conclusion

A camera tilt gauge enhances player awareness by providing real-time feedback on camera orientation. By using rotation-based calculations, UI animations, and smooth transitions, you can create an intuitive and responsive gauge for your game. Experiment with different styles and placements to best suit your game’s aesthetics and gameplay mechanics.

On this page