My participation in the development of Uncharted 4
After the release of Uncharted 4, I can already tell you about what I worked on in this project. I mainly developed AI for teammates in single player mode and multiplayer assistants, and also worked a little on gameplay logic. I will omit those aspects that did not get to the finished game and some minor details.
So, we proceed:
Before I begin, I would like to tell you about the post system used by the NPC. I did not work on the core logic of this system, but helped write the client code that used it.
Posts are discrete positions in the NPC navigation space, mostly created by development tools and manually placed by designers. Depending on our needs, we could create different post selectors to evaluate different post types (for example, stealth post selector, combat post selector) and choose the post with the highest rating to send NPCs there.
Teammates following the player
The system of following companions for the player is taken from The Last of Us .
The basic idea was that teammates choose positions around the player that they should follow. These potential positions diverge from the player and must satisfy the following checks for the freeness of the straight-line path: from player to position, from position to projected forward position, from projected forward position to player.
In contrast to The Last of Us, Uncharted 4 has such an aspect as rock climbing. To build rock-climbing into the player-following system, we added a rock-climbing posts selector that selects the points to which partners must move when the player climbs over rocks.
This task was more difficult than we expected. It was not enough to simply order the partners to use the usual following logic when the player does not climb, and to change posts when the player crawls along the wall. If a player quickly switches between normal state and rock climbing, companions begin to oscillate between these two states. Therefore, we have added a hysteresis: partners can now change the state only when the player has changed the state and has moved far enough in this state. In general, hysteresis is a good technique that allows you to avoid “behavioral jumps”.
Teammates Going Ahead
We wanted the teammates to show the player the way in some moments of the game. This system was taken from The Last of Us and improved: the designers used splines to outline the common paths that should be followed by partners leading the player forward.
If there are several paths at the level of several paths, the designers arranged several splines and turned them on / off using the script.
The position of the player is projected onto the spline, and the player’s support point is located in front, at a distance adjusted by the designers. When this follower anchor point passes the control point of the spline, labeled as a waiting point, the partner starts moving to another waiting point. If the player decides to go back, the partner begins to return only when the support point of support is too far from the most distant waiting point, passed during the last movement forward. Thus, a hysteresis is again formed, which allows to avoid an abrupt change of states.
We also built in the tracking system dynamic speed. Based on the distance between the partner and the player, along the spline are located the “velocity plane”. NPCs can use three types of movement: walking, running, and sprint. Depending on the plane of speeds in which the player is located, the partner chooses the appropriate type of movement in order to maintain the necessary distance to the player. In accordance with their vision, designers can enable and disable the speed plane. In addition, depending on the distance to the player, the speed of the animation of the movement of the partner slightly increases or decreases to avoid a sudden change in the speed of movement when switching between types of movement.
In The Last of Us, a player can move relative to his partner, while still remaining in cover. This is called general shelter.
In The Last of Us, Joel is farther from the shelter wall than Ellie or Tess, and this is logical, because they are smaller than Joel. But for Nate, Sam, Sally and Helen, this would look unnatural, because they are almost the same height. In addition, Uncharted 4 is a much faster game, and if Nate stretches his arms, moving behind the obstacle, it will destroy the smoothness of the movements. Therefore, we decided that the partners would simply rest on the wall of the shelter, and Neith would slightly bend around them when moving.
Here we used very simple logic. If the player’s projected position, taking into account its speed, falls into a rectangular border around the partner’s shelter post, the partner completes the current behavior behind the obstacle and presses against the shelter wall.
Medical assistants in multiplayer mode require a completely new behavior, which is not in single-player mode: they must resurrect fallen friends and copy the behavior of the players behind cover.
Doctors are trying to imitate the behavior of players behind cover and to be as close as possible to the player, so that if a player is injured, be near and resurrect him. If the closest ally is injured, they will also resurrect the ally, provided the player is still alive. If a player is equipped with a RevivePak mod for doctors, then before they run to the allies for resurrection, they will try to throw RevivePak at allies (several simultaneous resurrections speed up the resurrection process); when throwing RevivePak, the logic of throwing grenades is used, in particular, checking the freeness of the trajectory and playing the animation, only grenades are replaced by RevivePak.
Grass for stealth
New mechanics Uncharted 4 is also a covert movement in the grass. To implement it, we needed to somehow mark the environment so that the gameplay logic of the player would know if the player is in the grass. Initially, we wanted the artists to use the background for marking grass collision surfaces in Maya, but found that communication between artists and designers slows down iterations too much. Therefore, we have come up with another way to mark areas with grass for stealth. Especially for designers, a new grass tag for stealth was added to the editor, so that they could accurately mark the navigation polygons that the player should consider grass for stealth. Thanks to this additional information, we were also able to evaluate the secrecy posts depending on whether they are in the grass or not. This turned out to be useful for teammates,
Since, unlike The Last of Us, Uncharted 4 does not have a listening mode, we had to somehow inform the player of impending threats, so that it would not strain the unknown location of the enemies. Using data on the perception of enemies, we added color threat indicators that tell the player that the enemy will soon notice it as a distraction (white indicator), perceive it as a distraction factor (yellow indicator) and fully aware of its presence (orange indicator). In addition, we made the threat indicator amplify background noise to increase the tension, and emit a loud signal when the enemy fully understood the presence of the player, as in The Last of Us.
This is the last major part of the gameplay, in the development of which I participated, before the game went to gold. Usually I do not attend formal meetings at Naughty Dog, but several months before the “gold” we held at least one meeting a week under the direction of Bruce Straley or Neil Drakmann . Meetings were devoted to AI games. Almost after each of these meetings, there was something in the research system for modification or processing. Before releasing the finished game, we went through many stages of iterations.
There are two aspects that distract enemies and encourage them to research: the presence of the player and the corpses. When the enemy discovers a distracting factor, he tries to attract the closest ally in order to investigate his cause together. A closer enemy becomes a researcher, and the second - an observer. The enemy who discovered the distraction could become a researcher or an observer, and we prepared two different sets of dialogues for these cases (“There is something there. I'll go check.” And “There is something there. Go check.”).
In order to make the beginning and completion of the study more natural, we adjusted the timings of the movement of enemies and the reduction in the indicators of anxiety indicators so that a pair of researchers would not perform mechanically the same actions at the same time.
If the corpse is a distracting factor, then the researcher can find out about the presence of the player and order everyone to start looking for him, irrevocably leaving the restful state. The discovered corpse is also marked so that the player has the opportunity to understand what betrayed him.
On some difficulty levels, several studies behind each other force the enemies to explore more aggressively, which increases the chances of finding a player hiding in the grass. At the Crushing difficulty level, enemies are aggressively investigated constantly.
Views in dialogs
This is also one of the last aspects that I dealt with in the project.
Looking at conversations is a logic that forces characters to respond to conversations, such as looking at other people and making gestures. In The Last of Us, the designers manually annotated all in-game dialogues for months, marking moments of looks and gestures. We did not want to repeat this. We had several scripted conversations that we had already manually marked, but we needed a system that could handle the dialogs without annotations. Animators were given options to adjust the speed of head rotation, the maximum angle of head rotation, the length of the gaze, the pause time, and so on.
Saving the speed of the jeep
From the early stages of development, we had a problem with the jeep race in the level with the city in Madakaskar: if the player’s jeep blew and he lost speed after hitting the enemy’s wall or car, the player was thrown away from the convoy and he failed to pass the level.
I came up with such a solution: temporarily limited the angular speed from above and the change in linear velocity when colliding with walls and enemy machines. This simple solution turned out to be quite effective - it became much more difficult for players to fail the passage because of drifts.
Destruction of vehicles
In Uncharted 4, player-driven cars first appeared. In previous games of the series, only NPCs could drive cars, and these cars moved along spline rails. I helped in the work on the implementation of the destruction of transport.
There are several ways to destroy enemy vehicles: kill the driver, shoot the car, ram the enemy motorcycle with your jeep, hit the enemy's jeep with your own to bring it. Depending on the cause of the destruction, the animation of the destroyed transport and its passengers was chosen. The animation mixes with physically controlled ragdolls, so the destruction animation seamlessly transitions into a physically simulated crash.
To destroy motorcycles with a battering ram, a bounding box in the XZ plane and a point of contact were used, allowing you to select one of the four directional kill animations by the battering ram.
In the case of jeeps, it is checked whether the deviation of the rotation of the jeep from the desired direction of movement does not exceed the threshold value of the drift.
When playing the destruction animations, there is a chance that the destroyed transport may pass through the wall. A sphere cast (a sphere projected as a ray) is used from the ideal position of the machine along the rail, if it were not destroyed, to the position where its body is actually located. If during the generation of sphere cast the contact is fixed, the machine shifts in the direction of the contact normal by a fraction of the penetration value, therefore the process of eliminating the passage through the wall occurs gradually over several frames, thus avoiding an abrupt change of position.
We have created a special type of vehicle destruction, called vehicle death hint. These are context-sensitive animations of destruction that interact with the environment. Animators and designers position these animations along the “rails” of the spline and indicate the entry windows to them on the splines. If the vehicle is destroyed within this window, the corresponding destruction animation begins to play. Initially, this function was created as a tool for implementing an epic explosion of a jeep for a demo presented at E3 in 2015.
Bayer filter for dithering
We wanted to get rid of clipping geometry, when the camera is too close to the objects of the environment, mainly to the foliage. Therefore, we decided to shade the pixels in the pixel shader based on how close the pixels are to the camera. We could not use transparency, because it is too expensive, and there are too many foliage. Instead, we used dithering , combining the distance from the pixel to the camera and the pattern in the form of a Bayer filter — some pixels were completely discarded, which created the illusion of transparency.
Our original Bayer filter was an 8 × 8 matrix shown on this Wikipedia page . I decided that it was too small and led to the creation of artifacts in the form of stripes. I wanted to use a 16x16 Bayer filter, but I could not find it anywhere on the Internet. Therefore, I tried to reverse engineer the Bayer 8 × 8 filter pattern and noticed a recursive pattern. I could just study it and write down a 16 × 16 matrix manually, but for the sake of interest I wrote a tool capable of generating Bayes matrices of the size of any power of two.
After switching to a 16 × 16 Bayesian filter, the artifacts with stripes were significantly reduced.
Explosion sound delay
In fact, this is a very minor detail, but I would like to mention it. A couple of weeks before the demo at E3 in 2015, I noticed that the explosion of the tower is seen and heard at the same time, which was illogical. Nate and Sally are very far from the tower, so they must first see the explosion, and then hear it. A team of artists added a slight delay of the explosion sound to the finished demo.
Localization in Traditional Chinese
I included the text and subtitles in traditional Chinese just two weeks before the release of the game on gold, and found errors in the translation. Most of the errors were literal translations from English to Traditional Chinese, which did not fit the context. I decided that I would not have time to go through the whole game on my own, while looking for translation errors in parallel. So I asked a few people from the testing department to play in different parts of the game in traditional Chinese and watched the recorded videos of the passage. This turned out to be quite an effective step; I managed to fix all the detected translation errors, and the localization team was able to fix them before the deadline.
This is almost everything that I have been working on for Uncharted 4 of what is worth mentioning. I hope the article was interesting for you.