• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By ethancodes
      I'm having a weird issue with detecting a collision. I've tried everything I could find online but nothing seems to work. I have a brick object. It has a 2D Collider attached and I have also attached a 2D Rigidbody on it. I also have an EndScreen 2D Collider. The EndScreen 2D collider is tagged with "EndScreen". I am trying to detect when a brick collides with the end screen collider and simply print "game over" in the console. 
      This is my current code for this part of the program, it is attached to the bricks:
      void OnCollisionEnter (Collision2D collision) { if (collision.gameObject.tag == "EndScreen") { Debug.Log("Game over"); } } Several things have happened depending on the set up. If I have the rigidbody 2D set as static, my ball object can still collide with the bricks, but I get no Log message. If I set it to Kinematic or Dynamic, I get absolutely no interaction between the ball and the bricks, and nothing when the bricks pass through the collider. I have tried to set the collider to a trigger and use OnTriggerEnter2D, no change. I have tried to put the rigidbody on the EndScreen object and tried to set it's body type to all 3 settings, no change. The only thing I can think of that I have not done is put the script on the EndScreen object and switch the tag to the bricks. The reason I have not done this is because I will have several types of bricks, some of which will have different tags. 
       
      Please tell me somebody can see what I'm doing wrong here, because I'm losing my mind over something I feel should be ridiculously simple. Thanks.
    • By ethancodes
      I'm working on an endless wave-based arkanoid/space invaders style hybrid. Bricks spawn above the screen and move down line by line. You must destroy all bricks before they hit the bottom of the screen. There will be multiple types of bricks and random power-up spawns. Currently I am just using a simple Log function that takes in the current wave as a parameter. This works to increase the number of bricks spawned each wave, but I want to find a way to make this much more complicated. Here is a list of everything that should be effected by the increase in difficulty:
      1. Number of bricks
      2. Types of bricks (1 hit bricks, 2 hit bricks, 3 hit bricks, etc.) 
      3. Speed that the bricks move down the screen
      4. How often power-ups spawn
      The biggest problem here is that I can't just increase all of these with each new wave. If I did that, it would quickly become far to difficult. What I would like is an algorithm that gives some amount of variance in the increase between all 4 of these. Say one wave we put 60% of the increase to number of bricks, 20% increase to power-up spawns, 10% to types of bricks and 10% to speed of bricks. But on the next wave those percentages are all moved around and we now have say 105% to work with so the overall difficulty has increased as well. The different types of bricks need to also change to the point where if someone has made it to a certain wave, such as wave 50 for example, there are no longer any 1 hit bricks. We now would have just 2-4 hit bricks, and if they are crazy good and make it all the way to round 100, Now it's just 3-5 hit bricks, etc. 
      If anybody has any good ideas or suggestions on this, I'd appreciate anything you've got! Thanks!
    • By PVS-studio team
      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(....) { .... discardedModifications.Concat(discardedRotationModifications); return discardedModifications.ToArray(); } 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(....) { .... return discardedModifications.Concat(discardedRotationModifications) .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.
      Paradoxical check
      PVS-Studio warning: V3080 CWE-476 Possible null dereference. Consider inspecting 'm_Parent'. EditorWindow.cs 449
      public void ShowPopup() { if (m_Parent == null) { .... Rect r = m_Parent.borderSize.Add(....); .... } } 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) { .... Rect r = m_Parent.borderSize.Add(....); .... } } 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) { .... Rect r = m_Parent.borderSize.Add(....); .... } 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(....) { .... if (additionalOptions != null & additionalOptions.Trim().Length > 0) arguments += additionalOptions.Trim() + ","; .... } 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!
       
    • By ethancodes
      I feel like I should know this, but I tried looking it up to make sure I wasn't confusing myself, and couldn't seem to find a clear answer that made sense to me. When assigning something like this:
      GridSquare randomPosition; randomPosition = gridPositions[Random.Range(0,gridPositions.GetLength(0)),Random.Range(0,gridPositions.GetLength(1))]; Am I putting a copy of the GridSquare in gridPositions into the GridSquare randomPosition, or is randomPosition referencing the GridSquare at this location? If it's a copy, is there a way to reference it, like a pointer in c++, because that's what I want to do.
    • By NaterTots
      I'm looking for people to collaborate with on a (small scoped) project of our choosing.  I'm ideally looking for something that we can publish to an app store in under 6 months and then reassess the situation before deciding on next steps.  I'm not terribly concerned about genre/art/2Dvs3D/platform/etc, I think it's more important to gather a group of like-minded individuals and then make those choices once we understand the skillset of the people involved.  I want to treat this as a learning experience, a way to add another game to our CVs, and potentially as a way to meet people who can continue to collaborate in the future.
      Full Disclosure
      I've tried this in the past (using the similar Reddit forum) and gotten burned every time.  Because of that, I want to make sure that I'm only collaborating with people who will be directly contributing to the product - art/sound/animation/development/etc.  I'm not looking to work with people whose responsibilities are limited to entrepenuer/"idea man"/project management.
      About Me
      By day, I'm a Principal Software Architect at an enterprise software firm.  I've been working in Software Development for around 15 years, mainly focusing on the Microsoft stack - C++, C#, .NET, WPF, databases and most recently with modern architecture (containers, Docker, REST APIs, RabbitMQ, etc etc).  I have many years of Product Ownership, Project Management, and leading a dev team from an idea to a released product, so I can very comfortably "rein in" the scope of work, ensure we're driving towards an MVP, and make sure we're all on the same page about decisions we're making. 
      By night, I'm a hobby Game Developer.  I've been playing with game dev for years (like basically every person who gets into Software Dev) from DirectX 9 through XNA, GameMaker Studio, and the last 5 or so years have been in Unity3D.  Feel free to browse my Github (https://github.com/natertots).  I've "published" a couple very, very basic games by myself.  Here's one: https://play.google.com/store/apps/details?id=com.NaterTots.Sloth .  Don't get your hopes up.
      Being an architect by profession, I sometimes focus on spending too much time architecting the "perfect" solution to a problem.  Case in point - I've spent the last couple weeks making a Data I/O layer to more easily create data objects that get serialized/deserialized generically from any of a number of locations (locally, web, save location).  I have a strong programming background and feel comfortable implementing most any aspect of a game.
      About You
      A passionate contributor: art/sound/animation/development/etc.  Experience level doesn't matter.  I don't think we should try to enforce hours/time contribution, just as long as we're not stalling and continually making progress, even if it slows at times.
      Someone who's in it to learn and get better.  We're not going to make the next PUBG or WoW.  I don't even want to have the expectation that the focus of this project is to make money.
      A good communicator.  I've had the best experience working with a combination of Slack and Trello.  I'm in the EST time zone and will spend most of my working time around 8pm-midnight, so being available at some point during those times to chat would be a big plus.  
      Willing to work in Unity 3D and (if a dev) program in C#.  Sorry this is a narrow scope, but since I've focused so much effort on ramping up on this platform and language, I would rather not shift away from it.  Note: I'm just looking for people "willing", not necessarily experienced.
       
      I look forward to working with you,
      Nate
  • Advertisement
  • Advertisement

C# assigning a property from an object in a list to a variable

Recommended Posts

1 hour ago, Scouting Ninja said:

You have to use Add and Remove to keep it dynamic.

 

Aaaahhhh...soooo using the Clear method like this: 

gridOptions.Clear();

is not going to shrink the list, just make that element null? I hadn't realized that. That still doesn't explain why it has 4 element even before it is ever populated, but I bet when I go back through the code I'll find something that it's picking up to determine the length of the List and I didn't even realize it. I'll check it tonight when I get home. Thanks to everybody for all the help on this. I really appreciate it!

Share this post


Link to post
Share on other sites
Advertisement

So I'm still having issues. I keep randomly getting this out of range exception:

ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[GridSquare].get_Item (Int32 index) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:633)
BoardManager.CheckBorders (Int32 currentPosition) (at Assets/Scripts/BoardManager.cs:117)
BoardManager.RandomPosition () (at Assets/Scripts/BoardManager.cs:85)
BoardManager.LayoutObjectAtRandom (UnityEngine.GameObject brick, Int32 brickCount) (at Assets/Scripts/BoardManager.cs:152)
BoardManager.SetupScene (Int32 level) (at Assets/Scripts/BoardManager.cs:169)
GameManager.InitGame () (at Assets/Scripts/GameManager.cs:27)
GameManager.Awake () (at Assets/Scripts/GameManager.cs:22)
UnityEngine.Object:Instantiate(GameObject)
LevelManager:Awake() (at Assets/Scripts/LevelManager.cs:23)

 

I'm not sure what exactly is causing this. Here is all of the code in this class with the exception of what I use to initialize the bricks simply because I know that needs some cleaning up and reworking, but I haven't done it yet.. I have gone through and added better comments so hopefully what I'm doing makes more sense. I'm still very confused as to why my gridOptions list is giving itself 4 elements before it even checks to see if it wants to put something there. 

 


		private int columns = 20;                //Number of columns in our game board.
		private int rows = 30;  				//Number of rows in our game board.
		private int currentPositionId;			//holds the Id of the current position
		private int index = 0;					//index of gridPositions as we loop through, used to set Id to each GridSquare

		public int brickCount;               //Number of bricks to spawn.


		//Define brick types to assign sprites to in editor
		public GameObject oneHitBrick;                                
		public GameObject twoHitBrick;                                  
		public GameObject threeHitBrick;                                 
		public GameObject explodingBarrel;  //temporarily represented by the unbreakable brick
		                         
		private Transform boardHolder;     //A variable to store a reference to the transform of our Board object.
		private int randomIndex;			//select index to place next brick
		private Vector3 randomPosition;		//Position at the randomIndex
		private List <GridSquare> gridPositions = new List <GridSquare> ();   //list of positions on game board
		private List<GridSquare> gridOptions = new List<GridSquare>(); //list of options to place next brick


		//Clears our list gridPositions and prepares it to generate a new board.
		void InitialiseList ()
		{
			//Clear our list gridPositions.
			gridPositions.Clear ();

			//Loop through x axis (columns).
			for(int x = 1; x < columns-1; x++)
			{
				//Within each column, loop through y axis (rows).
				//start at 18 to spawn our bricks offscreen
				for(int y = 18; y < rows-1; y++)
				{
					bool occupied = false;
					//At each index add a new Vector3 to our list with the x and y coordinates of that position.
					//index is the Id of GridSquare to allow for matching with gridOptions list later
					gridPositions.Add (new GridSquare(new Vector3(x,y,0), occupied, index));

					index++;
				}
			}
		}
	
		//RandomPosition returns a random position from our gridPositions or gridOptions list.
		Vector3 RandomPosition ()
		{
			if (gridPositions.All(c => c.IsOccupied == false)) //check if all gridPositions are unoccupied
			{
				//set randomIndex value to a random number between 0 and the count of items in our List gridPositions.
			    randomIndex = Random.Range (1, gridPositions.Count);

				//set randomPosition to the element at randomIndex in gridPOsitions list
				randomPosition = gridPositions [randomIndex].GridPosition;

				//ensures the GridSquare will not be re-used 
				gridPositions[randomIndex].IsOccupied = true;

				//sets the currentPositionId to the current GridSquare based on Id
				currentPositionId = gridPositions[randomIndex].Id;

				//Return the randomly selected Vector3 position.
				return randomPosition;
			} 
				//call CheckBorders to populate list gridOptions
				CheckBorders(currentPositionId);

				//set randomIndex value to a random number between 0 and the count of items in our List gridOptions.
				randomIndex = Random.Range (0, gridOptions.Count);

				//set randomPosition value to the entry at randomIndex from our List gridOptions.
				randomPosition = gridOptions [randomIndex].GridPosition;

				//make sure the chosen GridSquare can't be re-used
				gridOptions[randomIndex].IsOccupied = true;

				//set currentPositionid to the current GridSquare by Id.
				currentPositionId = gridOptions[randomIndex].Id;

				//Return the randomly selected Vector3 position.
				return randomPosition;	
			

		}
		//check borders is used to check above, below, left, and right of the current GridSquare to see if those options are available for next brick, and then each
		//available option is added to list gridOptions
		void CheckBorders (int currentPosition)
		{
			int count = 0; //used to track gridOptions element

			gridOptions.Clear (); //empty gridOptions list

			if (gridPositions [currentPosition].GridPosition.x != 1) { //check to make sure we are not on column 1, if not, check 1 column to 																			//the left. If available, set to gridOptions list
				if (gridPositions [currentPosition - 11].IsOccupied == false) {
					gridOptions.Add (gridPositions [currentPosition - 11]);     //As soon as this line executes, my gridOptions lists shows this
				}															//this being populated, and then 3 null elements following it.
            }																//the nulls get populated accordingly as long as they are viable 																				//positions

			if (gridPositions [currentPosition].GridPosition.x != 20) { //check to make sure we are not on column 20, if not, check 1 column to the right. If available, set to gridOptions list
				if (gridPositions [currentPosition + 11].IsOccupied == false) {
					gridOptions.Add (gridPositions [currentPosition + 11]);
				}
			}

			if (gridPositions [currentPosition].GridPosition.y != 18) { //check to make sure we are not on row 18, if not, check 1 row under. If available, set to gridOptions list
				if (gridPositions [currentPosition - 1].IsOccupied == false) {
					gridOptions.Add (gridPositions [currentPosition - 1]);
				}
			}

			if (gridPositions [currentPosition].GridPosition.y != 30) { //check to make sure we are not on row 30, if not, check 1 row up. If available, set to gridOptions list
				if (gridPositions [currentPosition + 1].IsOccupied == false) {
					gridOptions.Add (gridPositions [currentPosition + 1]);
				}
			}

			//After checking all 4 locations, remove any null elements.
			foreach (GridSquare square in gridOptions) { 
				if (gridOptions [count] == null) {
					gridOptions.Remove (square);
				}
					count++;		
			}
		}

 

I'm really hoping someone can explain what I'm doing wrong here. I'm open to any suggestions as to what I can do to get this working or what's causing the out of range exception. Or why the gridOptions.Remove is not working, etc. Thanks.

Share this post


Link to post
Share on other sites
Posted (edited)

The error says you are trying to find a index that is out of the grid. The point you are trying to find isn't in the list. This should happen when your point is near the border if the grids.

IndexError.jpg.8364d781a909fe1dd2824e77448965b1.jpg

21 hours ago, ethancodes said:

I'm still very confused as to why my gridOptions list is giving itself 4 elements before it even checks to see if it wants to put something there. 

Looks like the CheckBoarders code will add null objects when it fails. Can't really tell without testing it.

 

After seeing your code I understand why you are having so much problems. It would be easier to use a multidimensional system, instead of a one dimension list.

Think of a vector2, it has a X and a Y axis. Keeping track of each dimension is easy and finding any point is done by checking each axis on its own. So no need for so many IF statements to find the borders. I will make a example to show how it works.

 

Edited by Scouting Ninja

Share this post


Link to post
Share on other sites

I had considered using a multidimensional array, but I had some doubts whether it would work how I need it to. I'm reworking all of this code now to see if I can get a multidimensional array to work for me, but if you want to write some stuff out to help me better understand that would be a huge help. I'm definitely getting pretty confused here. 

Share this post


Link to post
Share on other sites
8 hours ago, ethancodes said:

but if you want to write some stuff out to help me better understand that would be a huge help.

I had more time than expected, as I am fixing and formating my PC, and ended up creating the complete grid:

SN2DGrid.zip

Import into your Unity, a empty new project, as a custom pack and run the test scene. It will look invisible but once you start it will look like this:

GridExampleLook.thumb.jpg.befd90ef627e10b08f3bc8d0600e69e5.jpg

This is a 20 By 20 (400 cells) grid, it will start with a 9 By 9 grid (81) grid and you can adjust it. You can also adjust how many rocks there is.

Note: I use Unity GameObject and a Mono script for this, instead of my own class, because I wanted a easy way to find what block I click on. If you use your own class you will need to ray trace or use another way to find a exact point.

Features:

Randomly finds a point at start, never selecting a point with a rock on it. Color coded. Left_Click selects the point where your mouse is. Right_Click selects a new random point. Can select points near the edge. I made a lot of comments explaining things.

Tell me if it doesn't work or if there is a problem, or if you want a step by step explanation of how something works.

Share this post


Link to post
Share on other sites

I didn't have much time to look into this tonight, but I did glance through the scene and code real quick. It's not exactly what I need, but I think it'll definitely be a huge help. I'll be back on this tomorrow evening so hopefully I'll be able to figure it all out then.

Share this post


Link to post
Share on other sites
9 hours ago, ethancodes said:

It's not exactly what I need

Was expecting this because all we did was re-created what was already there. A vector2 and vector3 is a grid and if we want to see if there is an object at a point we can do a ray trace or check the Unity object list to see what points at this grid is occupied.

In other words this system just adds a engine on top of the engine.

Share this post


Link to post
Share on other sites

Hi, ethancodes! Any luck figuring out your ArgumentOutOfRangeException? If not, I think I see what's going on.

Inside of InitializeList, when you're creating your GridSquares the maximum X value is 18 and the maximum Y value is 28.

So, your grid looks something like this.

Grid.PNG.8bec27208537f864793bcf524f46648b.PNG

In orange across the top are the "y" coordinates and across the side are the "x" coordinates. Inside each box is the index into "gridPositions", or your Id.

Inside of "CheckBoarders", you're doing the following check to ensure you're not on the final row:

if (gridPositions [currentPosition].GridPosition.x != 20)

However, since the maximum value for "x" is 18, this condition always evaluates to true. Even when you're on the last row! So, if we were to pick an Id from the last row in the grid, lets say 187, and step through that code then your check would evaluate to true. 

if (gridPositions [currentPosition/*187*/].GridPosition.x /*x == 18*/ != 20)
{
    if (gridPositions [currentPosition + 11 /*187 + 11 = 198. This is outside the bounds of gridPositions, and is throwing the exception*/].IsOccupied == false)
}

As for why gridOptions is initializing to four elements, I don't see anything that would be causing that. What are you doing to see those nulls?

I'm going to speculate here, and if I'm wrong I apologize. I *suspect* that what you're doing is looking at "gridOptions" through the debugger. Either through a watch, or the Locals window, or perhaps just hovering over "gridOptions" with your mouse. Then, you're drilling down until you see the private "_items" field and drilling down into that. If so, here is what is going on...

List<T> stores the items you add to it internally via a fixed sized array. When you add an item to an empty List<T>, it resizes the internal array to have a length of four. This is why you're seeing four items, three of which are nulls, in _items after the first item gets added (if that is indeed what you're seeing).

If you're curious why it doesn't just resize the internal array to fit exactly the number of items you're adding it's because that resize is an expensive operation. Essentially, it has to allocate a new array then copy the old array into the new one. This isn't something you want to happen every single time you add an item to the list. Incidentally, every time List<T> gets an item that exceeds its capacity, the size of the internal array doubles. If you were to add five GridSquares to "gridOptions" and look at "_items" you would see eight items. Add 9 GridSquares to "gridOptions" and look at "_items" and you would see 16 items.

This might also explain why your "Remove" isn't working... you don't actually have any nulls in "gridOptions".

Share this post


Link to post
Share on other sites

@Joshua Robinson this explains a lot actually. Now I am faced with the decision of changing my code back to using the List like I was here, or just getting it to work with the multidimensional array as I have it now. I'm pretty close with the multidimensional array, but I'm once again getting an out of range exception. Only this time, it's not even spawning bricks. The exception seems to be happening when setting up the grid. Suggestions on which to use? I personally liked using the list a lot better only because it was much easier to read for me. But if there will be a large difference in performance with using a multidimensional array, then I'll keep that. Keeping in mind that the new model also uses a List. So basically, two lists, or one multidimensional array and one list are the two options.

 

Share this post


Link to post
Share on other sites
12 hours ago, ethancodes said:

I personally liked using the list a lot better only because it was much easier to read for me.

Just pointing out that you can use multidimensional lists. Remember that a list is an array, it just has extra code attached to make it dynamic but the way this works is that the array is copied and so it does have impact on performance.

I am curious, are you trying to make marching cubes? If you explained what you want it would be easier to help you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement