How static code analysis helps in the GameDev space

image1.png


The gaming industry does not stand still and is developing faster and faster every day. Along with the growth of the industry, the complexity of development also grows: there is more code and more bugs in it. Therefore, modern game projects need special attention to the quality of the code. Today we will talk about one of the ways to make your code better - static analysis, as well as how PVS-Studio helps in practice in the development of large (and not only) game projects.



" The most important thing I have done as a programmer in recent years is to aggressively pursue static code analysis. Even more valuable than the hundreds of serious bugs I have prevented with it is the change in mindset about the way I view software reliability and code quality. "- John Carmack



We have been working with major game developers for many years and during this time we have managed to do a lot of interesting and useful things for the game industry. This is not surprising given the list of our clients from the gaming industry. We provide active support to our clients: we help them integrate PVS-Studio into their own development process, fix errors found by the analyzer, and even make special features to order.



In addition, we do a lot of independent development of the analyzer in the GameDev direction, and we also popularize PVS-Studio by telling people about interesting errors that it found in various video games.



Naturally, not without interesting stories. Several of these stories will be discussed in this article.



PVS-Studio and Unity



image2.png


One of the ways we are promoting our product is by writing articles about reviewing open source projects. Everyone benefits from these articles: the reader can look at interesting errors in a familiar project and learn something new for himself, we get the opportunity to show PVS-Studio's work in real code, and project developers can learn about errors and fix them in advance.



Our first serious acquaintance with Unity began in 2016, when the developers of this game engine released the source code of several components, libraries and demos into their official repository. Naturally, we could not pass by such a "tasty" case and wanted to write an article about checking the laid out code.



Then we found that the Unity3D code (at that time the engine was called that way) is of very high quality, however, we managed to find quite a lot of serious errors in it for writing an article .



Two years later, another event happened - this time the Unity developers released the code of the engine itself and the editor to open access. And just like the previous time, we could not pass by and checked the source code of the engine. And for good reason: we also found a handful of interesting mistakes .



However, writing articles is far from everything. We continue to work on PVS-Studio, and GameDev is one of the most important areas for development for us. Therefore, we want Unity game developers to be able to get the best possible analysis of their projects.



One of the steps to improve the quality of the analysis of Unity projects for us was writing annotations for the methods defined in the Unity Scripting API.



Method annotations are a special mechanism used in PVS-Studio. It allows you to provide the analyzer with all the information it needs about a particular method. It is written in special code by the developers of the analyzer themselves (that is, by us).



This information can be of a completely different kind. For example: how a method can affect the parameters passed to it, whether it can allocate memory and whether it returns a value that must be processed. Thus, annotation allows the analyzer to better understand the logic of the methods, thereby allowing it to detect new and more complex errors.



We have already written a huge variety of different annotations (for example, for methods from the System namespace), and we were happy to supplement them with method annotations from the Unity Scripting API.



We started adding to the list of annotations with an assessment. How many methods are there? Which ones should be annotated first? There were a lot of methods in total, and we decided to start by annotating the most frequently used methods.



The search for popular methods was carried out as follows: first, we collected a pool of projects from GitHub that use the capabilities of Unity, and then, using a self-written utility (based on Roslyn), we counted the calls of the methods we are interested in. As a result, we got a list of classes, the methods of which are used most often:



  • UnityEngine.Vector3
  • UnityEngine.Mathf
  • UnityEngine.Debug
  • UnityEngine.GameObject
  • UnityEngine.Material
  • UnityEditor.EditorGUILayout
  • UnityEngine.Component
  • UnityEngine.Object
  • UnityEngine.GUILayout
  • UnityEngine.Quaternion
  • ...


Next, it remains to annotate the methods of these classes. We created a test project and dug into the documentation to get as much information as possible about these methods. For example, we tried passing null as various arguments to see how the program behaves.



During such checks, interesting undocumented information was periodically discovered - and we even found a couple of interesting bugs in the engine. So, when running code like this:



MeshRenderer renderer = cube.GetComponent<MeshRenderer>();
Material m = renderer.material;
List<int> outNames = null;
m.GetTexturePropertyNameIDs(outNames);


the Unity editor itself crashes directly (at least in version 2019.3.10f1). It is unlikely, of course, that someone will write such code, but the very fact that the Unity editor can be "knocked down" by running such a script is interesting.



So, the annotations are written. After starting the analysis, we immediately discovered new triggers. For example, the analyzer detected a strange call to the GetComponent method :



void OnEnable()
{
  GameObject uiManager = GameObject.Find("UIRoot");

  if (uiManager)
  {
    uiManager.GetComponent<UIManager>();
  }
}


Analyzer warning: V3010 The return value of function 'GetComponent' is required to be utilized. - ADDITIONAL IN CURRENT UIEditorWindow.cs 22



The GetComponent method even by its name implies the return of a certain value. It is logical to assume that this very value should be used somehow. Now (thanks to the new annotation) the analyzer knows that such an "orphan" call to this method may indicate a logical error, and warns you about it.



This is far from the only trigger that appeared in our set of test projects after adding new annotations - I will not give the rest so as not to make this article too large. The main thing is that now the development of Unity projects using PVS-Studio allows you to write much safer and cleaner code without bugs.



If you want to read in more detail about our work with annotations for Unity methods, you can do it in our article: How the PVS-Studio analyzer began to find even more errors in Unity projects .



Unreal Engine 4



image3.png


When, back in 2014, the developers of Unreal Engine 4 released the source code of the engine to the public, we simply could not get around this project and also wrote an article about it . The engine developers liked the article and fixed the bugs we found. But this was not enough for us, and we decided to try to sell the license for our analyzer to Epic Games.



Epic Games was interested in improving its engine using PVS-Studio, so we agreed on an agreement: we fix the Unreal Engine code on our own so that the analyzer does not issue any warnings for it, and the guys from Epic Games buy our license and in addition reward us for the work we do.



Why did you need to fix all the warnings? The point is that the maximum benefit from static analysis can be obtained by correcting errors as soon as they appear . And when you check your project for the first time, as a rule, you get several hundreds (and sometimes thousands) of warnings. Among all these analyzer warnings, warnings issued for freshly written code can easily get lost.



At first glance, this problem can be solved quite easily: you just need to sit down and fully bypass the entire report, gradually correcting errors. However, this method, while more intuitive, can take time. The method of using suppress files is much more convenient and faster.



Suppress files are a special function of PVS-Studio, which allows you to "hide" the analyzer triggers in a special file. In this case, hidden warnings will not appear in subsequent logs: they can be viewed separately.



Having received a large number of triggers after the first check, you can add all detected triggers to the suppress file in a couple of clicks, and then, at the next check by the analyzer, you will receive a clean log without a single trigger.



Now that old warnings are no longer logged, you can easily spot a new warning as soon as it appears. We wrote the code -> checked it with the analyzer -> saw a new warning -> fixed the error. This is how you get the most out of your analyzer.



At the same time, do not forget about the alarms that are in the suppress file: they all, as before, may contain warnings about serious errors and vulnerabilities. Therefore, it is worthwhile to periodically return to these warnings and reduce their number.



This scenario is convenient, of course, but the developers at Epic Games wanted their code to be fixed right away, and they turned it over to us.



And we got to work. After checking the project code, we found 1821 one level warning of Level_1 and Level_2. Parsing such a volume of warnings requires serious work, and to facilitate this whole process, we have set up continuous code analysis on our CI server.



It looked like this: every night the current version of Unreal Engine 4 was compiled on our server, and the analysis was automatically launched immediately after the build. Thus, when our guys came to work in the morning, they always had a fresh analyzer report on hand, allowing them to track the progress in correcting warnings. Plus, such a system made it possible to check the stability of the build at any time by manually running it on the server.



The whole process took us 17 working days. The schedule for correcting warnings is as follows:



image4.png


In fact, this graph does not fully reflect our work. After we fixed all the warnings, we waited for another two days for them to accept our latest pull requests. All this time, the automatic check of the latest version of Unreal Engine continued to work for us, which, in turn, continued to be replenished with new code. And what do you think? During these two days PVS-Studio found four more errors in the code! One of them was especially serious and could potentially lead to undefined behavior.



Of course, we also fixed these errors. Now the developers of Unreal Engine have only one thing left: to configure their automatic analysis in the same way as we did. From that moment on, they began to see warnings every day that were issued for the newly written code. This allowed them to fix bugs in the code even at the moment of their appearance - at the very early stages of development .



You can read more about how we worked on the Unreal Engine code on the official Unreal Engine blog or on our website .



Analysis of various games



image5.png


Did I mention that we check various open source projects and write articles about them? So, we have just a whole lot of similar articles about game projects! We've written about games like VVVVVV , Space Engineers , Command & Conquer , osu! and even (very ancient article) Doom 3 . We've also compiled the top 10 most interesting bugs from the video game industry.



We've also checked out perhaps most of the well-known open source engines. In addition to Unity and Unreal Engine 4, projects such as Godot , Bullet , Amazon Lumberyard , Cry Engine V came under our sightand many others.



The best part of all this is that many of the bugs we described were subsequently fixed by the project developers themselves. It's nice to feel that the tool you are developing is bringing real, visible and tangible benefits to the world.



You can see a list of all our articles, one way or another related to the development of video games on a special page of our blog.



Conclusion



This concludes my short article. I wish you clean and correctly working code without bugs and errors!



Interested in the topic of static analysis? Do you want to check your project for errors? Try PVS-Studio .







If you want to share this article with an English-speaking audience, please use the translation link: George Gribkov. How static code analysis helps in the GameDev industry .



All Articles