• # Checking the Unity C# Source Code

General and Gameplay Programming

Recently a long-awaited event has happen - Unity Technologies uploaded the C# source code of the game engine, available for free download on Github. The code of the engine and the editor is available. Of course, we couldn't pass up, especially since lately we've not written so many articles about checking projects on C#. Unity allows to use the provided sources only for information purposes. We'll use them exactly in these ways. Let's try out the latest version PVS-Studio 6.23 on the Unity code.

## Introduction

Previously we've written an article about checking Unity. At that time so much C#-code was not available for the analysis: some components, libraries and examples of usage. However, the author of the article managed to find quite interesting bugs.

How did Unity please us this time? I'm saying "please" and hope not to offend the authors of the project. Especially since the amount of the source Unity C#-code, presented on GitHub, is about 400 thousand lines (excluding empty) in 2058 files with the extension "cs". It's a lot, and the analyzer had a quite considerable scope.

Now about the results. Before the analysis, I've slightly simplified the work, having enabled the mode of the code display according to the CWE classification for the found bugs. I've also activated the warnings suppression mechanism of the third level of certainty (Low). These settings are available in the drop-down menu of PVS-Studio in Visual Studio development environment, and in the parameters of the analyzer. Getting rid of the warnings with low certainty, I made the analysis of the Unity source code. As a result, I got 181 warnings of the first level of certainty (High) and 506 warnings of the second level of certainty (Medium).

I have not studied absolutely all the warnings, because there were quite a lot of them. Developers or enthusiasts can easily conduct an in-depth analysis by testing Unity themselves. To do this, PVS-Studio provides free trial and free modes of using. Companies can also buy our product and get quick and detailed support along with the license.

Judging by the fact that I immediately managed to find couple of real bugs practically in every group of warnings with one or two attempts, there are a lot of them in Unity. And yes, they are diverse. Let's review the most interesting errors.

## Results of the check

Something's wrong with the flags

PVS-Studio warning: V3001 There are identical sub-expressions 'MethodAttributes.Public' to the left and to the right of the '|' operator. SyncListStructProcessor.cs 240

MethodReference GenerateSerialization()
{
....
MethodDefinition serializeFunc = new
MethodDefinition("SerializeItem", MethodAttributes.Public |
MethodAttributes.Virtual |
MethodAttributes.Public |  // <=
MethodAttributes.HideBySig,
Weaver.voidType);
....
}

When combining enumeration flags MethodAttributes, an error was made: the Public value was used twice. Perhaps, the reason for this is the wrong code formatting.

A similar bug is also made in code of the method GenerateDeserialization:

• V3001 There are identical sub-expressions 'MethodAttributes.Public' to the left and to the right of the '|' operator. SyncListStructProcessor.cs 309

Copy-Paste

PVS-Studio warning: V3001 There are identical sub-expressions 'format == RenderTextureFormat.ARGBFloat' to the left and to the right of the '||' operator. RenderTextureEditor.cs 87

public static bool IsHDRFormat(RenderTextureFormat format)
{
Return (format == RenderTextureFormat.ARGBHalf ||
format == RenderTextureFormat.RGB111110Float ||
format == RenderTextureFormat.RGFloat ||
format == RenderTextureFormat.ARGBFloat ||
format == RenderTextureFormat.ARGBFloat ||
format == RenderTextureFormat.RFloat ||
format == RenderTextureFormat.RGHalf ||
format == RenderTextureFormat.RHalf);
}

I gave a piece of code, preliminary having formatted it, so the error is easily detected visually: the comparison with RenderTextureFormat.ARGBFloat is performed twice. In the original code, it looks differently:

Probably, another value of enumeration RenderTextureFormat has to be used in one of two identical comparisons.

Double work

PVS-Studio warning: V3008 CWE-563 The 'fail' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1633, 1632. UNetWeaver.cs 1633

class Weaver
{
....
public static bool fail;
....
static public bool IsValidTypeToGenerate(....)
{
....
if (....)
{
....
Weaver.fail = true;
fail = true;
return false;
}
return true;
}
....
}

The true value is assigned twice to the value, as Weaver.fail and fail is one and the same static field of the Weaver class. Perhaps, there is no crucial error, but the code definitely needs attention.

No options

PVS-Studio warning: V3009 CWE-393 It's odd that this method always returns one and the same value of 'false'. ProjectBrowser.cs 1417

// Returns true if we should early out of OnGUI
bool HandleCommandEventsForTreeView()
{
....
if (....)
{
....
if (....)
return false;
....
}
return false;
}

The method always returns false. Pay attention to the comment in the beginning.

A developer forgot about the result

PVS-Studio warning: V3010 CWE-252 The return value of function 'Concat' is required to be utilized. AnimationRecording.cs 455

static public UndoPropertyModification[] Process(....)
{
....
}

When concatenating two arrays discardedModifications and discardedRotationModifications the author forgot to save the result. Probably a programmer assumed that the result would be expressed immediately in the array discardedModifications. But it is not so. As a result, the original array discardedModifications is returned from the method. The code needs to be corrected as follows:

static public UndoPropertyModification[] Process(....)
{
....
.ToArray();
}

Wrong variable was checked

PVS-Studio warning: V3019 CWE-697 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'obj', 'newResolution'. GameViewSizesMenuItemProvider.cs 104

private static GameViewSize CastToGameViewSize(object obj)
{
GameViewSize newResolution = obj as GameViewSize;
if (obj == null)
{
Debug.LogError("Incorrect input");
return null;
}
return newResolution;
}

In this method, the developers forgot to consider a situation where the variable objis not equal to null, but it will not be able to cast to the GameViewSize type. Then the variable newResolution will be set to null, and the debug output will not be made. A correct variant of code will be like this:

private static GameViewSize CastToGameViewSize(object obj)
{
GameViewSize newResolution = obj as GameViewSize;
if (newResolution == null)
{
Debug.LogError("Incorrect input");
}
return newResolution;
}

Deficiency

PVS-Studio warning: V3020 CWE-670 An unconditional 'return' within a loop. PolygonCollider2DEditor.cs 96

private void HandleDragAndDrop(Rect targetRect)
{
....
foreach (....)
{
....
if (....)
{
....
}
return;
}
....
}

The loop will execute only one iteration, after that the method terminates its work. Various scenarios are probable. For example, return must be inside the unit if, or somewhere before return, a directive continue is missing. It may well be that there is no error here, but then one should make the code more understandable.

Unreachable code

PVS-Studio warning: V3021 CWE-561 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless CustomScriptAssembly.cs 179

public bool IsCompatibleWith(....)
{
....
if (buildingForEditor)
return IsCompatibleWithEditor();

if (buildingForEditor)
buildTarget = BuildTarget.NoTarget; // Editor
....
}

Two identical checks, following one after another. It is clear that in case of buildingForEditor equality to the true value, the second check is meaningless, because the first method terminates its work. If the value buildingForEditor is false, neither then-brunch nor if operator will be executed. There is an erroneous construction that requires correction.

Unconditional condition

PVS-Studio warning: V3022 CWE-570 Expression 'index < 0 && index >= parameters.Length' is always false. AnimatorControllerPlayable.bindings.cs 287

public AnimatorControllerParameter GetParameter(int index)
{
AnimatorControllerParameter[] param = parameters;
if (index < 0 && index >= parameters.Length)
throw new IndexOutOfRangeException(
"Index must be between 0 and " + parameters.Length);
return param[index];
}

The condition of the index check is incorrect - the result will always be false. However, in case of passing the incorrect index to the GetParameter method, the exception IndexOutOfRangeException will still be thrown when attempting to access an array element in the return block. Although, the error message will be slightly different. One has to use || in a condition instead of the operator && so that the code worked the way a developer expected:

public AnimatorControllerParameter GetParameter(int index)
{
AnimatorControllerParameter[] param = parameters;
if (index < 0 || index >= parameters.Length)
throw new IndexOutOfRangeException(
"Index must be between 0 and " + parameters.Length);
return param[index];
}

Perhaps, due to the use of the Copy-Paste method, there is another the same error in the Unity code:

PVS-Studio warning: V3022 CWE-570 Expression 'index < 0 && index >= parameters.Length' is always false. Animator.bindings.cs 711

And another similar error associated with the incorrect condition of the check of the array index:

PVS-Studio warning: V3022 CWE-570 Expression 'handle.valueIndex < 0 && handle.valueIndex >= list.Length' is always false. StyleSheet.cs 81

static T CheckAccess<T>(T[] list, StyleValueType type,
StyleValueHandle handle)
{
T value = default(T);
if (handle.valueType != type)
{
Debug.LogErrorFormat(....  );
}
else if (handle.valueIndex < 0 && handle.valueIndex >= list.Length)
{
Debug.LogError("Accessing invalid property");
}
else
{
value = list[handle.valueIndex];
}
return value;
}

And in this case, a release of the IndexOutOfRangeException exception is possible.As in the previous code fragments, one has to use the operator || instead of && to fix an error.

Simply strange code

Two warnings are issued for the code fragment below.

PVS-Studio warning: V3022 CWE-571 Expression 'bRegisterAllDefinitions || (AudioSettings.GetSpatializerPluginName() == "GVR Audio Spatializer")' is always true. AudioExtensions.cs 463

PVS-Studio warning: V3022 CWE-571 Expression 'bRegisterAllDefinitions || (AudioSettings.GetAmbisonicDecoderPluginName() == "GVR Audio Spatializer")' is always true. AudioExtensions.cs 467

// This is where we register our built-in spatializer extensions.
static private void RegisterBuiltinDefinitions()
{
bool bRegisterAllDefinitions = true;

if (!m_BuiltinDefinitionsRegistered)
{
if (bRegisterAllDefinitions ||
(AudioSettings.GetSpatializerPluginName() ==
"GVR Audio Spatializer"))
{
}

if (bRegisterAllDefinitions ||
(AudioSettings.GetAmbisonicDecoderPluginName() ==
"GVR Audio Spatializer"))
{
}

m_BuiltinDefinitionsRegistered = true;
}
}

It looks like an incomplete method. It is unclear why it has been left as such and why developers haven't commented the useless code blocks. All, that the method does at the moment:

if (!m_BuiltinDefinitionsRegistered)
{
m_BuiltinDefinitionsRegistered = true;
}

Useless method

PVS-Studio warning: V3022 CWE-570 Expression 'PerceptionRemotingPlugin.GetConnectionState() != HolographicStreamerConnectionState.Disconnected' is always false. HolographicEmulationWindow.cs 171

private void Disconnect()
{
if (PerceptionRemotingPlugin.GetConnectionState() !=
HolographicStreamerConnectionState.Disconnected)
PerceptionRemotingPlugin.Disconnect();
}

To clarify the situation, it is necessary to look at the declaration of the methodPerceptionRemotingPlugin.GetConnectionState():

internal static HolographicStreamerConnectionState
GetConnectionState()
{
return HolographicStreamerConnectionState.Disconnected;
}

Thus, calling the Disconnect() method leads to nothing.

One more error relates to the same method PerceptionRemotingPlugin.GetConnectionState():

PVS-Studio warning: V3022 CWE-570 Expression 'PerceptionRemotingPlugin.GetConnectionState() == HolographicStreamerConnectionState.Connected' is always false. HolographicEmulationWindow.cs 177

private bool IsConnectedToRemoteDevice()
{
return PerceptionRemotingPlugin.GetConnectionState() ==
HolographicStreamerConnectionState.Connected;
}

The result of the method is equivalent to the following:

private bool IsConnectedToRemoteDevice()
{
return false;
}

As we can see, among the warnings V3022 many interesting ones were found. Probably, if one spends much time, he can increase the list. But let's move on.

Not on the format

PVS-Studio warning: V3025 CWE-685 Incorrect format. A different number of format items is expected while calling 'Format' function. Arguments not used: index. Physics2D.bindings.cs 2823

public void SetPath(....)
{
if (index < 0)
throw new ArgumentOutOfRangeException(
String.Format("Negative path index is invalid.", index));
....
}

There is no error in code, but as the saying goes, the code "smells". Probably, an earlier message was more informative, like this: "Negative path index {0} is invalid.". Then it was simplified, but developers forgot to remove the parameter index for the method Format. Of course, this is not the same as a forgotten parameter for the indicated output string specifier, i.e. the construction of the type String.Format("Negative path index {0} is invalid."). In such a case, an exception would be thrown. But in our case we also need neatness when refactoring. The code has to be fixed as follows:

public void SetPath(....)
{
if (index < 0)
throw new ArgumentOutOfRangeException(
"Negative path index is invalid.");
....
}

Substring of the substring

PVS-Studio warning: V3053 An excessive expression. Examine the substrings 'UnityEngine.' and 'UnityEngine.SetupCoroutine'. StackTrace.cs 43

static bool IsSystemStacktraceType(object name)
{
string casted = (string)name;
return casted.StartsWith("UnityEditor.") ||
casted.StartsWith("UnityEngine.") ||
casted.StartsWith("System.") ||
casted.StartsWith("UnityScript.Lang.") ||
casted.StartsWith("Boo.Lang.") ||
casted.StartsWith("UnityEngine.SetupCoroutine");
}

Search of the substring "UnityEngine.SetupCoroutine" in the condition is meaningless, because before that the search for "UnityEngine." is performed. Therefore, the last check should be removed or one has to clarify the correctness of substrings.

Another similar error:

PVS-Studio warning: V3053 An excessive expression. Examine the substrings 'Windows.dll' and 'Windows.'. AssemblyHelper.cs 84

static private bool CouldBelongToDotNetOrWindowsRuntime(string
assemblyPath)
{
return assemblyPath.IndexOf("mscorlib.dll") != -1 ||
assemblyPath.IndexOf("System.") != -1 ||
assemblyPath.IndexOf("Windows.dll") != -1 ||  // <=
assemblyPath.IndexOf("Microsoft.") != -1 ||
assemblyPath.IndexOf("Windows.") != -1 ||  // <=
assemblyPath.IndexOf("WinRTLegacy.dll") != -1 ||
assemblyPath.IndexOf("platform.dll") != -1;
}

Size does matter

PVS-Studio warning: V3063 CWE-571 A part of conditional expression is always true if it is evaluated: pageSize <= 1000. UNETInterface.cs 584

public override bool IsValid()
{
....
return base.IsValid()
&& (pageSize >= 1 || pageSize <= 1000)
&& totalFilters <= 10;
}

Condition for a check of a valid page size is erroneous. Instead of the operator ||, one has to use &&. The corrected code:

public override bool IsValid()
{
....
return base.IsValid()
&& (pageSize >= 1 && pageSize <= 1000)
&& totalFilters <= 10;
}

Possible division by zero

PVS-Studio warning: V3064 CWE-369 Potential division by zero. Consider inspecting denominator '(float)(width - 1)'. ClothInspector.cs 249

Texture2D GenerateColorTexture(int width)
{
....
for (int i = 0; i < width; i++)
colors[i] = GetGradientColor(i / (float)(width - 1));
....
}

The problem may occur when passing the value width = 1 into the method. In the method, it is not checked anyway. The method GenerateColorTexture is called in the code just once with the parameter 100:

void OnEnable()
{
if (s_ColorTexture == null)
s_ColorTexture = GenerateColorTexture(100);
....
}

So, there is no error here so far. But, just in case, in the method GenerateColorTexture the possibility of transferring incorrect width value should be provided.

PVS-Studio warning: V3080 CWE-476 Possible null dereference. Consider inspecting 'm_Parent'. EditorWindow.cs 449

public void ShowPopup()
{
if (m_Parent == null)
{
....
....
}
}

Probably, due to a typo, the execution of such code guarantees the use of the null reference m_Parent. The corrected code:

public void ShowPopup()
{
if (m_Parent != null)
{
....
....
}
}

The same error occurs later in the code:

PVS-Studio warning: V3080 CWE-476 Possible null dereference. Consider inspecting 'm_Parent'. EditorWindow.cs 470

internal void ShowWithMode(ShowMode mode)
{
if (m_Parent == null)
{
....
....
}

And here's another interesting bug that can lead to access by a null reference due to incorrect check:

PVS-Studio warning: V3080 CWE-476 Possible null dereference. Consider inspecting 'objects'. TypeSelectionList.cs 48

public TypeSelection(string typeName, Object[] objects)
{
System.Diagnostics.Debug.Assert(objects != null ||
objects.Length >= 1);
....
}

It seems to me that Unity developers quite often make errors related to misuse of operators || and && in conditions. In this case, if objects has a null value, then this will lead to a check of second part of the condition (objects != null || objects.Length >= 1), which will entail the unexpected throw of an exception. The error should be corrected as follows:

public TypeSelection(string typeName, Object[] objects)
{
System.Diagnostics.Debug.Assert(objects != null &&
objects.Length >= 1);
....
}

Early nullifying

PVS-Studio warning: V3080 CWE-476 Possible null dereference. Consider inspecting 'm_RowRects'. TreeViewControlGUI.cs 272

public override void GetFirstAndLastRowVisible(....)
{
....
if (rowCount != m_RowRects.Count)
{
m_RowRects = null;
throw new InvalidOperationException(string.Format("....",
rowCount, m_RowRects.Count));
}
....
}

In this case, the exception throw (access by the null reference m_RowRects) will happen when generating the message string for another exception. Code might be fixed, for example, as follows:

public override void GetFirstAndLastRowVisible(....)
{
....
if (rowCount != m_RowRects.Count)
{
var m_RowRectsCount = m_RowRects.Count;
m_RowRects = null;
throw new InvalidOperationException(string.Format("....",
rowCount, m_RowRectsCount));
}
....
}

One more error when checking

PVS-Studio warning: V3080 CWE-476 Possible null dereference. Consider inspecting 'additionalOptions'. MonoCrossCompile.cs 279

static void CrossCompileAOT(....)
{
....
....
}

Due to the fact that the & operator is used in a condition, the second part of the condition will always be checked, regardless of the result of the check of the first part. In case if the variable additionalOptions has the null value, the exception throw is inevitable. The error has to be corrected, by using the operator && instead of &.

As we can see, among the warnings with the number V3080 there are rather insidious errors.

Late check

PVS-Studio warning: V3095 CWE-476 The 'element' object was used before it was verified against null. Check lines: 101, 107. StyleContext.cs 101

public override void OnBeginElementTest(VisualElement element, ....)
{
if (element.IsDirty(ChangeType.Styles))
{
....
}

if (element != null && element.styleSheets != null)
{
....
}
....
}

The variable element is used without preliminary check for null. While later in the code this check is performed. The code probably needs to be corrected as follows:

public override void OnBeginElementTest(VisualElement element, ....)
{
if (element != null)
{
if (element.IsDirty(ChangeType.Styles))
{
....
}

if (element.styleSheets != null)
{
....
}
}
....
}

In code there are 18 more errors. Let me give you a list of the first 10:

• V3095 CWE-476 The 'property' object was used before it was verified against null. Check lines: 5137, 5154. EditorGUI.cs 5137
• V3095 CWE-476 The 'exposedPropertyTable' object was used before it was verified against null. Check lines: 152, 154. ExposedReferenceDrawer.cs 152
• V3095 CWE-476 The 'rectObjs' object was used before it was verified against null. Check lines: 97, 99. RectSelection.cs 97
• V3095 CWE-476 The 'm_EditorCache' object was used before it was verified against null. Check lines: 134, 140. EditorCache.cs 134
• V3095 CWE-476 The 'setup' object was used before it was verified against null. Check lines: 43, 47. TreeViewExpandAnimator.cs 43
• V3095 CWE-476 The 'response.job' object was used before it was verified against null. Check lines: 88, 99. AssetStoreClient.cs 88
• V3095 CWE-476 The 'compilationTask' object was used before it was verified against null. Check lines: 1010, 1011. EditorCompilation.cs 1010
• V3095 CWE-476 The 'm_GenericPresetLibraryInspector' object was used before it was verified against null. Check lines: 35, 36. CurvePresetLibraryInspector.cs 35
• V3095 CWE-476 The 'Event.current' object was used before it was verified against null. Check lines: 574, 620. AvatarMaskInspector.cs 574
• V3095 CWE-476 The 'm_GenericPresetLibraryInspector' object was used before it was verified against null. Check lines: 31, 32. ColorPresetLibraryInspector.cs 31

Wrong Equals method

PVS-Studio warning: V3115 CWE-684 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. CurveEditorSelection.cs 74

public override bool Equals(object _other)
{
CurveSelection other = (CurveSelection)_other;
return other.curveID == curveID && other.key == key &&
other.type == type;
}

Overload of the Equals method was implemented carelessly. One has to take into account the possibility of obtaining null as a parameter, as this can lead to a throw of an exception, which hasn't been considered in the calling code. In addition, the situation, when _other can't be cast to the type CurveSelection, will lead to a throw of an exception. The code has to be fixed. A good example of the implementation of Object.equals overload is given in the documentation.

In the code, there are other similar errors:

• V3115 CWE-684 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. SpritePackerWindow.cs 40
• V3115 CWE-684 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. PlatformIconField.cs 28
• V3115 CWE-684 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. ShapeEditor.cs 161
• V3115 CWE-684 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. ActiveEditorTrackerBindings.gen.cs 33
• V3115 CWE-684 Passing 'null' to 'Equals' method should not result in 'NullReferenceException'. ProfilerFrameDataView.bindings.cs 60

Once again about the check for null inequality

PVS-Studio warning: V3125 CWE-476 The 'camera' object was used after it was verified against null. Check lines: 184, 180. ARBackgroundRenderer.cs 184

protected void DisableARBackgroundRendering()
{
....
if (camera != null)
camera.clearFlags = m_CameraClearFlags;

// Command buffer
camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque,
m_CommandBuffer);
camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer,
m_CommandBuffer);
}

When the camera variable is used the first time, it is checked for null inequality. But further along the code the developers forget to do it. The correct variant could be like this:

protected void DisableARBackgroundRendering()
{
....
if (camera != null)
{
camera.clearFlags = m_CameraClearFlags;

// Command buffer
camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque,
m_CommandBuffer);
camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer,
m_CommandBuffer);
}
}

Another similar error:

PVS-Studio warning: V3125 CWE-476 The 'item' object was used after it was verified against null. Check lines: 88, 85. TreeViewForAudioMixerGroups.cs 88

protected override Texture GetIconForItem(TreeViewItem item)
{
if (item != null && item.icon != null)
return item.icon;

if (item.id == kNoneItemID) // <=
return k_AudioListenerIcon;

return k_AudioGroupIcon;
}

An error, that in some cases leads to an access by a null link. The execution of the condition in the first block if enables the exit from the method. However, if this does not happen, then there is no guarantee that the reference item is non-zero. Here is the corrected version of the code:

protected override Texture GetIconForItem(TreeViewItem item)
{
if (item != null)
{
if (item.icon != null)
return item.icon;

if (item.id == kNoneItemID)
return k_AudioListenerIcon;
}

return k_AudioGroupIcon;
}

In the code there are 12 similar errors. Let me give you a list of the first 10:

• V3125 CWE-476 The 'element' object was used after it was verified against null. Check lines: 132, 107. StyleContext.cs 132
• V3125 CWE-476 The 'mi.DeclaringType' object was used after it was verified against null. Check lines: 68, 49. AttributeHelper.cs 68
• V3125 CWE-476 The 'label' object was used after it was verified against null. Check lines: 5016, 4999. EditorGUI.cs 5016
• V3125 CWE-476 The 'Event.current' object was used after it was verified against null. Check lines: 277, 268. HostView.cs 277
• V3125 CWE-476 The 'bpst' object was used after it was verified against null. Check lines: 96, 92. BuildPlayerSceneTreeView.cs 96
• V3125 CWE-476 The 'state' object was used after it was verified against null. Check lines: 417, 404. EditorGUIExt.cs 417
• V3125 CWE-476 The 'dock' object was used after it was verified against null. Check lines: 370, 365. WindowLayout.cs 370
• V3125 CWE-476 The 'info' object was used after it was verified against null. Check lines: 234, 226. AssetStoreAssetInspector.cs 234
• V3125 CWE-476 The 'platformProvider' object was used after it was verified against null. Check lines: 262, 222. CodeStrippingUtils.cs 262
• V3125 CWE-476 The 'm_ControlPoints' object was used after it was verified against null. Check lines: 373, 361. EdgeControl.cs 373

The choice turned out to be small

PVS-Studio warning: V3136 CWE-691 Constant expression in switch statement. HolographicEmulationWindow.cs 261

void ConnectionStateGUI()
{
....
HolographicStreamerConnectionState connectionState =
PerceptionRemotingPlugin.GetConnectionState();
switch (connectionState)
{
....
}
....
}

The method PerceptionRemotingPlugin.GetConnectionState() is to blame here. We have already come across it when we were analyzing the warnings V3022:

internal static HolographicStreamerConnectionState
GetConnectionState()
{
return HolographicStreamerConnectionState.Disconnected;
}

The method will return a constant. This code is very strange. It needs to be paid attention.

## Conclusions

I think we can stop at this point, otherwise the article will become boring and overextended. Again, I listed the errors that I just couldn't miss. Sure, the Unity code contains a big number of the erroneous and incorrect constructions, that need to be fixed. The difficulty is that many of the issued warnings are very controversial and only the author of the code is able to make the exact "diagnosis" in each case.

Generally speaking about the Unity project, we can say that it is rich for errors, but taking into account the size of its code base (400 thousand lines), it's not so bad. Nevertheless, I hope that the authors will not neglect the code analysis tools to improve the quality of their product.

Use PVS-Studio and I wish you bugless code!

Report Article

## User Feedback

There are no comments to display.

## Create an account

Register a new account

• 0
• 0
• 1
• 1
• 3

• 13
• 10
• 9
• 17
• 21
• ### Similar Content

• By trapazza
I'm trying to add some details like grass, rocks, trees, etc. to my little procedurally-generated planet. The meshes for the terrain are created from a spherified cube which is split in chunks (chunked LOD).
To do this I've wrote a geometry shader that takes a mesh as input and uses its vertex positions as locations where the patches of grass will be placed (as textured quads).
For an infinite flat world (not spherical) I'd use the terrain mesh as input to the geometry shader, but I've found that this won't work well on a sphere, since the vertex density is not homogeneous across the surface.
So the main question would be: How to create a point cloud for each terrain chunk whose points were equally distributed across the chunk?
Note: I've seen some examples where these points are calculated from intersecting a massive rain of totally random perpendicular rays from above... but I found this solution overkill, to say the least.
Another related question would be: Is there something better/faster than the geometry shader approach, maybe using compute shaders and instancing?
• By FedGuard
Hello all,

I would like to start off with thanking you all for this community. Without fora like these to assist people the already hard journey to making an own game would be exponentially more difficult. Next I would like to apologize for the long post, in advance...
I am contemplating making a game. There, now that's out of the way, maybe some further details might be handy.
I am not some youngster (no offence) with dreams of breaking into the industry, I am 38, have a full-time job, a wife, kid and dog so I think I am not even considered indie? However I recently found myself with additional time on my hands and decided I would try my hand at making a game.Why? Well mostly because I would like to contribute something, also because I think I have a project worth making (and of course some extra income wouldn't hurt either to be honest). The first thing I realized was, I have absolutely no relevant skill or experience. Hmm; ok, never mind, we can overcome that, right?
I have spent a few months "researching",meaning looking at YouTube channels, reading articles and fora. Needless to say, I am more confused now than when I started. I also bought some courses (Blender, Unity, C#) and set out to make my ideas more concrete.
I quickly discovered, I am definitely not an artist... So I decided, though I do plan to continue learning the art side eventually, I would focus on the design and development phase first. The idea being, if it takes me a year or more solely learning stuff and taking courses without actually working on my game, I would become demoralized and the risk of quitting would increase.
So I thought I would:
1: Keep following the courses Unity and C# while starting on the actual game development as the courses and my knowledge progress.
2: Acquire some artwork to help me get a connection with the game and main character, and have something to helm keep me motivated. (I already did some contacting and realized this will not be cheap...). Also try to have the main character model so I can use it to start testing the initial character and game mechanics. For this I have my first concrete question. I already learned that outsourcing this will easily run up in the high hundreds or thousands of dollars... (lowest offer so far being 220 USD) I am therefore playing with the idea of purchasing https://assetstore.unity.com/packages/3d/animations/medieval-animations-mega-pack-12141 with the intention of then have an artist alter and/or add to the animations (it is for a Roman character so some shield animations are not going to work the same way.). This way I could start  with the basic character mechanics. Is this a good idea, waste of money,...? Any suggestions? I then have a related but separate question. Is it a good idea to buy Playmaker (or some other similar software I haven't yet heard of like RPGAIO), and using this for initial build, then changing/adding code as the need arises?
3.Get a playable initial level ready as a rough demo and then starting to look for artist for level design and character/prop creation.
...

I would really appreciate some input from more experienced people, and especially answers to my questions. Of course any advice is extremely welcome.
• By GameTop
Dirt Bike Extreme - another game made with Unity. Took about 2 months to complete.
Take part in extreme motorcycle races across the dangerous and challenging tracks. Dirt Bike Extreme is easy to pick up but hard to master. Race, jump and crash your way and other mad rivals through the amazing tracks as you master the skills and physics of motocross in this high-speed racing adventure. Conquer challenging routes on 23 different runs, discover new bikes and become the best of the best! Over 257K downloads already!
Windows Version:

Mac Version:
https://www.macstop.com/games/dirt-bike-extreme/

• I've been experimenting with my own n-body simulation for some time and I recently discovered how to optimize it for efficient multithreading and vectorization with the Intel compiler. It did exactly the same thing after making it multithreaded and scaled very well on my ancient i7 3820 (4.3GHz). Then I changed the interleaved xy coordinates to separate arrays for x and y to eliminate the strided loads to improve AVX scaling and copy the coordinates to an interleaved array for OpenTK to render as points. Now the physics is all wrong, the points form clumps that interact with each other but they are unusually dense and accelerate faster than they decelerate causing the clumps to randomly fly off into the distance and after several seconds I get a NaN where 2 points somehow occupy exactly the same x and y float coordinates. This is the C++ DLL:
#include "PPC.h" #include <thread> static const float G = 0.0000001F; const int count = 4096; __declspec(align(64)) float pointsx[count]; __declspec(align(64)) float pointsy[count]; void SetData(float* x, float* y){ memcpy(pointsx, x, count * sizeof(float)); memcpy(pointsy, y, count * sizeof(float)); } void Compute(float* points, float* velx, float* vely, long pcount, float aspect, float zoom) { #pragma omp parallel for for (auto i = 0; i < count; ++i) { auto forcex = 0.0F; auto forcey = 0.0F; for (auto j = 0; j < count; ++j) { if(j == i)continue; const auto distx = pointsx[i] - pointsx[j]; const auto disty = pointsy[i] - pointsy[j]; //if(px != px) continue; //most efficient way to avoid a NaN failure const auto force = G / (distx * distx + disty * disty); forcex += distx * force; forcey += disty * force; } pointsx[i] += velx[i] -= forcex; pointsy[i] += vely[i] -= forcey; if (zoom != 1) { points[i * 2] = pointsx[i] * zoom / aspect; points[i * 2 + 1] = pointsy[i] * zoom; } else { points[i * 2] = pointsx[i] / aspect; points[i * 2 + 1] = pointsy[i]; } /*points[i * 2] = pointsx[i]; points[i * 2 + 1] = pointsy[i];*/ } } This is the relevant part of the C# OpenTK GameWindow:
private void PhysicsLoop(){ while(true){ if(stop){ for(var i = 0; i < pcount; ++i) { velx[i] = vely[i] = 0F; } } if(reset){ reset = false; var r = new Random(); for(var i = 0; i < Startcount; ++i){ do{ pointsx[i] = (float)(r.NextDouble()*2.0F - 1.0F); pointsy[i] = (float)(r.NextDouble()*2.0F - 1.0F); } while(pointsx[i]*pointsx[i] + pointsy[i]*pointsy[i] > 1.0F); velx[i] = vely[i] = 0.0F; } NativeMethods.SetData(pointsx, pointsy); pcount = Startcount; buffersize = (IntPtr)(pcount*8); } are.WaitOne(); NativeMethods.Compute(points0, velx, vely, pcount, aspect, zoom); var pointstemp = points0; points0 = points1; points1 = pointstemp; are1.Set(); } } protected override void OnRenderFrame(FrameEventArgs e){ GL.Clear(ClearBufferMask.ColorBufferBit); GL.EnableVertexAttribArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); mre1.Wait(); are1.WaitOne(); GL.BufferData(BufferTarget.ArrayBuffer, buffersize, points1, BufferUsageHint.StaticDraw); are.Set(); GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 0, 0); GL.DrawArrays(PrimitiveType.Points, 0, pcount); GL.DisableVertexAttribArray(0); SwapBuffers(); } These are the array declarations:
private const int Startcount = 4096; private readonly float[] pointsx = new float[Startcount]; private readonly float[] pointsy = new float[Startcount]; private float[] points0 = new float[Startcount*2]; private float[] points1 = new float[Startcount*2]; private readonly float[] velx = new float[Startcount]; private readonly float[] vely = new float[Startcount];
Edit 0: It seems that adding 3 zeros to G increases the accuracy of the simulation but I'm at a loss as to why its different without interleaved coordinates. Edit 1: I somehow achieved an 8.3x performance increase with AVX over scalar with the new code above!

• Continuing to work on “Eldest Souls” (first article here!), I’ve begun familiarising myself with the workflow between Fmod and Unity, and the integration system. I know much of this will be pretty obvious to most, but I thought I’d share my thoughts as a complete beginner learning the ropes of sound designing.
The library of sounds that Fmod provides has been very useful, at least as reference points. I’ve still kept to my ethos of producing the sounds myself as much as possible. Having said that, Fmod gives you 50 free sounds with your download, and I’ve used a wooden crate smash, a drawbridge and electricity sound you can hear in the foley video below.

The thing i found most useful was witnessing changes i made in Fmod being realised instantly in Unity. If a volume needed changing, or the timing of one of my effects was off, i can literally switch to Fmod and then back to Unity and immediately see the result of my alterations. It also seems apparent that using middleware such as this (or i've heard Wwise is also equally intuitive) grants the developer, and myself included, a great deal more flexibility and opportunity to edit sounds without going all the way back to a DAW, and bouncing down again. Needless to say, my workflow is so much faster because of it.
I've also loved the randomised feature of Fmod, whereby any sound can be made to sound slightly different each time it is heard. Taking a footstep recording i made for example, I was able to add further authenticity of uneven footsteps by randomising the pitch and volume of each playback.

I used this technique when creating footsteps for the first major boss in the game called "The Guardian". A big, over-encumbered husk of a monster. I also had fun rummaging through the garage for old tools and metal components for the “Guardian” (the first boss) footsteps. See below!

I also created a sword attack for our player, trying to sound different from the generic “woosh” I see in so many video games. I used a very “sharp” and abrasive sound to differentiate him from any enemies.

On another note, I recently upgraded my microphone to a Rode NTG2 shotgun, which has been phenomenal. I haven’t had to worry about noise interfering with the clarity of my objects, whereas before with the sm58 I had to be clever with my EQ and noise reduction plugins.
Important to note again that this still a “cheap” mic in comparison to most other products on the market, and all in all my entire setup is still very simple and affordable which I’m quite proud of. I’ve seen many musicians spend heaps of money on gear they don’t necessarily need. I much prefer being resourceful with less equipment, than to have more than I can understand or remember how to use.
It’s forced me to understand every aspect and capability of my tools, which I believe is a principal that can be applied to any discipline.

I have more fun little sound effect videos on my Instagram for those interested, where I post regular updates. Thanks for reading! (if you’ve made it this far)

www.sergioronchetti.com
INSTAGRAM
fallenflagstudio.com