-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRAOT.html
More file actions
170 lines (153 loc) · 11.5 KB
/
Copy pathRAOT.html
File metadata and controls
170 lines (153 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ilangeerligs.github.io | Portfolio </title>
<meta name="description" content="Check out my projects!">
<meta name="author" content="Ilan Geerligs">
<!-- Embed page for social media posts -->
<meta property="og:description" content="ilangeerligs.github.io description">
<meta property="og:title" content="Ilan Geerligs | Portfolio">
<meta property="og:type" content="website">
<meta property="og:url" content="http://www.ilangeerligs.github.io">
<meta property="og:image" content="http://www.ilangeerligs.github.io/img/logo.png">
<meta property="og:site_name" content="ilangeerligs.github.io">
<!-- Favicon -->
<link rel="shortcut icon" type="image/png" href="img/favicon.png">
<!-- Page Style -->
<link rel="stylesheet" type="text/css" href="style.css?version=1">
</head>
<body>
<!-- Navigation Bar -->
<div class="topnav" id="myTopnav">
<a href="index.html" class="rightVerticalLine">Home</a>
<a href="https://github.com/IlanGeerligs" class="icon leftVerticalLine">GitHub</a>
<a href="https://www.linkedin.com/in/ilan-geerligs-7375a9282/" class="icon leftVerticalLine">LinkedIn</a>
<a href="Resume.html" class="icon leftVerticalLine" onclick="myFunction()">Resume</a>
</a>
</div>
<!-- Header with Full-Size Image -->
<div class="hero-image" style="background-image: url('img/RAoT/RAOT_BackGround.png');">
<div class="coverDivFull">
<!-- <img class="coverArtFullRAOT" src="img/RAoT/RAOT_Large.png" alt="Cover Image" height="500" width="500"></img> -->
</div>
</div>
<!-- Description Section -->
<div class="descriptionDivRAOT">
<!-- Section -->
<h1>Roark's Attack on Titan Fan Game</h1>
<br>
<!-- <div style="font-size: 1.0em; font-family:Verdana, Geneva, Tahoma, sans-serif"> -->
<p style="text-align: center;">RAoT is a multiplayer, pvp-focused take on Attack on Titan. Featuring 14 playable characters, 3 unique weapon classes, and 10 game modes supporting up to 32 players and 4 teams.</p>
<p style="text-align: center;">The game is made in Unity and uses Mirror networking. You can download it on <a href="https://roarkdev.itch.io/raot">Itch</a> or <a href="https://gamejolt.com/games/raot/613147">GameJolt</a></p>
<!-- </div> -->
</div>
<br>
<br>
<iframe width="1120" height="630" src="https://www.youtube-nocookie.com/embed/eiOOnv-tKGE?si=ReLPTYK8gmEjNUBq" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<br>
<!-- Description Section -->
<div class="descriptionDivRAOT">
<br>
<br>
<!-- Section -->
<h1>What I Did</h1>
<br>
<p>I joined the RAoT team post-release in October 2021, and up until September 2022, I contributed to most of the post-release updates as the second gameplay programmer, besides the creator of the project known as Roark.
<br>I worked on a wide variety of tasks from performance optimization to ping compensation. Working closely with playtesters to find and resolve bugs and improve the game's competitive balance.</p>
<br>
<h3>Performance optimization</h3>
<p>When I joined the team the game was not very optimized, so trough using Unity's build in profiling tools I was able to find a lot of low hanging fruit on the CPU side.
These optimizations mostly involved adding culling to various systems on the players, such as occlusion culling for IK and animations, and distance culling for audio systems.
<br>On the GPU side I was also able to improve the performance significantly by enabling static batching on the map geometry. And by working together with our 3D artist to reduce the amount of materials used.
<br>All in all these optimizations halved the average frame time in full lobbies. Allowing us to increase the max player count from 16 to 32. Which still ran better than the 16 players did originally.</p>
</p>
<br>
<h3>Hit Detection</h3>
<p>High level players often complained that hits that should or shouldn't have hit were doing the opposite. Of course players report these types of issues in any competitive game, regardless of if there is actually a problem.
But in this case there was also a lot of video evidence. So i investigated all the weapons' hit detection and found some issues.
<br>First up the APG. To give some context, the APG fires like a shotgun, but it does not have individual pellets that need to hit, instead it's like an expanding cone,
but the "bullet" does have travel time and is implemented trough a single raycast chain which checks for an intersection with two spheres on the enemy player that expand with the bullet's life time.
This all works great but the issue was with when or when to not block a hit if a player is obscured by map geometry.
<br>
<br> Swords had an issue where you would pass trough players during your swing without hitting them. This happened because the sword hit detection simply checked if you overlapped the other player's hit box (sphere) every frame.
But at high relative speeds or when you have a gracing hit this can easily lead to tunneling. Add on top of that players with very high jitter, and you have a disaster.
To solve this, I implemented shortest distance between two line segments and checked that distance between the line segments of the local and enemy player's last and current frame positions.
This is effectively the same as doing the sphere overlap an infinite amount of times between the two frames.
</p>
<br>
<br>
<!-- Image -->
<img src="img/RAoT/SwordHitDetection.png"></img>
<br>
<br>
<br>
<h3>Ping Mitigation</h3>
<p>The biggest issue with this game, in my opinion, is ping. Because the player base is small, you are always playing with people across the continent and often
with people from other continents. And the combination between high ping and very fast movement results in getting killed by things that you dodged on your
screen. This is a nearly unsolvable problem unless you do server-side movement. However, I tried mitigating it a bit by adding player position extrapolation.
The game used the Mirror networked transform for syncing player position. This transform has a small buffer of received player positions to smooth out packet
jitter. I extrapolated from this smoothed position, but by using any positions already received, I was able to do so more accurately. I also took into account
the acceleration players were undergoing, making any smooth motion arcs (like swinging when cabled) perfectly extrapolate. But of course, any time the player
changes their rate of acceleration, the extrapolation will cause overshoot. Through lots of playtesting, we found that about 50ms of extrapolation was the best
tradeoff, but this is from the smoothed position which is about 33ms behind. A very small victory but it still slightly increased the amount of situations where
reactively dodging is viable. To solve overshoot causing players to clip into geometry, I added collision response to the extrapolation.</p>
<br>
<br>
<!-- Video mp4 -->
<video width="100%" controls="">
<source src="videos/PlayerExtrapolation.mp4" type="video/mp4">
</video>
<br>
<br>
<p>
In the video above, you can see the extrapolation in action. The small cyan cube represents the smoothed player position, and the small yellow cubes are player position packets that arrived in that frame.
I used the tool called <a href="https://jagt.github.io/clumsy/">Clumsy</a> to simulate bad network conditions locally for this test.
</p>
<br>
<h3>Camera Work</h3>
<p>The camera had some clipping issues and would sometimes behave strangely, so I reworked the camera object avoidance.
I ensured that all collision traces happened from a "safe" position to avoid false negatives.
I also altered the raycast fans that were used by remembering hits and tracing to that point to avoid issues with thin obstacles that fit between the fan rays.
<br>
Additionally, I created a better spectator camera with adjustable smoothing, which allowed for more cinematic shots. This was a big hit with content creators.
</p>
<br>
<h1>What I Learned</h1>
<br>
<p> This project was a very impactful learning opportunity for me. With a lot of firsts.
It was my first time joining a large existing project, my first time working on a released game with an active player base, and my first time working on a multiplayer game.
<br><br>
I learned a lot about writing clean and maintainable code just from looking at the existing codebase.
Additionally, I gained valuable experience in using Git beyond the basics, such as working with branches, making pull requests, and conducting code reviews.
Furthermore, I learned much about multiplayer networking, including how to mitigate latency issues.
I also learned how to profile effectively and optimize systems with the highest impact.
<br><br>
On the soft skill side I learned the importance of clear communication and keeping the team informed about what I was working on,
especially when working remotely without any standard meetings. Not doing so can lead to misunderstandings.
Furthermore, I learned the difficulties of developing a game for a passionate player base, and how a small but vocal number of players can have a big impact on the community and the team's morale.
</p>
<br><br>
</div>
<div class="contact">
<div class="contact-body">
<!-- Section -->
<h2>Contact</h2>
<p>Click the email address to send a message. I look forward to hearing from you.</p>
<p><strong><a href="mailto:ilangeerligs.00@gmail.com">ilangeerligs.00@gmail.com</a></strong></p>
</div>
</div>
<!-- Navigation Script -->
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
</script>
</body>
</html>