0

Problem: Whenver I start my level and draw a line, first time I draw I get the error mentioned below. When I draw again the script works fine without giving any error. Kindly if someone can look into this and help out it'll be great! I've been stuck on this problem for a few days no... This one when my mouse is pressed:

 ArgumentOutOfRangeException: Index was out of range. Must be
 non-negative and less than the size of the collection. Parameter name:
 index System.ThrowHelper.ThrowArgumentOutOfRangeException
 (System.ExceptionArgument argument, System.ExceptionResource resource)
 (at <695d1cc93cca45069c528c15c9fdd749>:0)
 System.ThrowHelper.ThrowArgumentOutOfRangeException () (at
 <695d1cc93cca45069c528c15c9fdd749>:0)
  System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at
  <695d1cc93cca45069c528c15c9fdd749>:0) DrawingManager.DrawVisibleLine
   () (at Assets/2DPhysicsDraw/Scripts/DrawingManager.cs:401)
   DrawingManager.Update () (at
   Assets/2DPhysicsDraw/Scripts/DrawingManager.cs:219)

This one when my I release the mouse,

   NullReferenceException: Object reference not set to an instance of an
   object DrawingManager.Update () (at
   Assets/2DPhysicsDraw/Scripts/DrawingManager.cs:274)

Awake Method:

   private void Awake()
    {
    startMoving = false;
    drawCount = 0;
    if (_instance != null && _instance != this)
    {
        //Destroy(this.gameObject);
    }
    else
    {
        _instance = this;
    }
    }

Start Method:

 void Start()
{
    DestroyLastPath();
    startMoving = false;
    canDraw = true;
  // Physics2D.IgnoreLayerCollision( 8, 3 ,true);
    Physics2D.IgnoreLayerCollision(LayerMask.NameToLayer("OnDraw"),
    LayerMask.NameToLayer("OnDraw"));
    mousePointer = GameObject.Find("MousePointer");
    cloneNumber = 0;
    //colorStart = Color.black;
   // colorEnd = Color.black;
  //  widthStart = 0.2f;
   // widthEnd = 0.2f;
    verticesDistance = 0.1f;
  //  lifeTime = 2f;
    colliderType = ColliderTypeChoices.Polygon_Collider;
  //  isPermanent = true;
  //  fixedPosition = false;
    showMassCenter = false;
    massCenterPrecision = 100;
    dynamicMass = true;
    massScale = 1f;
    gravityScale = 1f;
 //   overlapHandling = overlapHandlingChoices.Follow_The_Edge;
    freezeWhileDrawing = true;

    tagsCantdraw = tagCantDraw.Split(',');
    //tagCantDraw
    
    
    pathLineRenderer = path.GetComponent<LineRenderer>();
    //pathRigidbody = path.GetComponent<Rigidbody2D>();
    pathLineRenderer.useWorldSpace = false;

    // Setting up material of the line, it can be modified or placed as public so it can be changed in inspector
    // *Obs: changing the material will be facilitated in the next release of the asset
  //  pathLineRenderer.material = new Material(Shader.Find("Particles/Alpha Blended Premultiply"));

    pathLineRenderer.SetColors(colorStart, colorEnd);
    pathLineRenderer.SetWidth(widthStart, widthEnd);
    posCount = 0;
}

FixedUpdate Method:

 void FixedUpdate()
{
    mousePointer.GetComponent<TargetJoint2D>().target = 
 (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
}

public void StartVehicle()
{
    StartCar.SetActive(true);
}

Update Method:

   void Update()
    {
     canDraw = true;
        
    // hit detection by mouse position for the on drawing collision handling
    if (overlapHandling == overlapHandlingChoices.Cut_After_Collision)
        hit = Physics2D.Raycast(mousePointer.transform.position, Vector2.zero, 
     Mathf.Infinity, layerMask);

    // mouseRay detects if the mouse is over some object
    mouseRay = 
      Physics2D.Raycast((Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition),
      Vector2.zero, Mathf.Infinity, layerMask);
    
    if (Input.GetMouseButtonDown(0))
    {
      //  PathMaterial.color = Pathcolor[GameManager.EnvirenmentNo - 1];
        FreezeMoving.freeze = true;

        // disables the drawing when click on objects with the tag "Wall"
        foreach (string tag in tagsCantdraw)
        {
            if (mouseRay.collider != null && mouseRay.collider.tag == tag) 
                canDraw = false;
        }
        if (GraphicRaycasterRaycasterExample.Instance.candraw == false)
        {
            canDraw = false;
        }

        if (canDraw == true)
        {
            mousePointer.transform.position = 
        Camera.main.ScreenToWorldPoint(Input.mousePosition);
            if (overlapHandling == overlapHandlingChoices.Follow_The_Edge)
                Physics2D.IgnoreLayerCollision( 9, 8 ,true);
                mousePointer.GetComponent<CircleCollider2D>().isTrigger = false;

            mousePointer.transform.localScale = new Vector3(widthEnd, widthEnd, widthEnd);
            canDraw = true;
            StarPrefab();
            centerOfMassCount = 0;
            centerOfMass = Vector2.zero;
        }
    }

    if (Input.GetMouseButton(0))
    {
        if (canDraw == true)
        {
            Particle.SetActive(true);
            // if collides, sets collision handing flag
            if (hit.collider != null)
            {
                mouseHit = true;
               
            }

            canDraw = true;
            DrawVisibleLine();
            
           
           
        }
    }
    if (Input.GetMouseButtonUp(0))
    {
        FreezeMoving.freeze = false;
        Particle.SetActive(false);
        if (canDraw == true)
        {
            mousePointer.GetComponent<CircleCollider2D>().isTrigger = true;
            mouseHit = false;


            if (colliderType == ColliderTypeChoices.Edge_Collider)
            {
                newVerticies.Add(mousePointer.transform.position - 
         clone.transform.position);
                Debug.Log("currently in if");
            }
            else
            {
                Debug.Log("Currently in esleeee");
                newVerticies2.Clear();
                newVerticies.Add(mousePointer.transform.position);
                for (int i = 0; i < newVerticies.Count - 1; i++)
                {
                    if (i < newVerticies.Count - 2)
                    {
                        // calculates the angle of each edge in the line
                        colliderAngle = Mathf.Atan2(newVerticies[i].y - newVerticies[i + 
          1].y,
         newVerticies[i].x - newVerticies[i + 1].x);
                        colliderAngle = colliderAngle + (Mathf.Deg2Rad * 90f);
                    }
                    else
                    {
                        // Since we have two points to have an edge and the last point is 
            not in this for, the angle calculation is
           not 
                        // done for the last edge and the same angel from befor is preserved
                    }
                    float cos = Mathf.Cos(colliderAngle);   // calc cos
                    float sin = Mathf.Sin(colliderAngle);   // calc sin

                    // Get the width of the line for each point of it
                    float tempWidth = Mathf.Lerp(widthStart, widthEnd, (float)i / 
           (newVerticies.Count - 2));

                    // To make the Polygon Collider 2D go around the line, it means each 
          side of the line,
                    // adds one point to the beginning and one to the end of the List
                    newVerticies2.Add(new Vector2(
                                    (newVerticies[i].x) + ((tempWidth / 2) * cos),
                                    (newVerticies[i].y) + ((tempWidth / 2) * sin)));
                    newVerticies2.Insert(0, new Vector2(
                                    (newVerticies[i].x) - ((tempWidth / 2) * cos),
                                    (newVerticies[i].y) - ((tempWidth / 2) * sin)));

                }
                pathPolygonCollider.points = newVerticies2.ToArray();
                pathPolygonCollider.sharedMaterial = material;
            }
            CalculatesPrevCenterOfMassAndMass(newVerticies.Count - 1);
            clone.layer = LayerMask.NameToLayer("Drawing");
            pathLineRenderer.SetVertexCount(newVerticies.Count - 1);
            for (int i = 0; i < newVerticies.Count - 1; i++)
            {

                pathLineRenderer.SetPosition(i, newVerticies[i]);

            }

            if (dynamicMass == true)
                pathRigidbody.mass *= massScale;
            else pathRigidbody.mass = massScale;
            centerOfMass /= centerOfMassCount;
            if (newVerticies.Count > 2 && (widthStart != 0 || widthEnd != 0))
                pathRigidbody.centerOfMass = centerOfMass;

            // Check if you want to show the center of mass during the gameplay and 
           instantiate the prefab in the proper position
            // *Obs: the MassCenter prefab can be personalized with an image or anything you 
            want to show the center of mass
            if (showMassCenter)
            {
                massCenterClone = (GameObject)Instantiate(massCenter, 
            this.transform.position,
             Quaternion.identity);
                massCenterClone.transform.parent = pathRigidbody.transform;
                massCenterClone.transform.position = centerOfMass;
            }

            pathRigidbody.bodyType = RigidbodyType2D.Dynamic;
            posCount = 0;
             
            // Check if the drawn line is too small or if it doesn't have visual volume and 
            destroy the prefab if it true
            /*if (newVerticies.Count <= 2 || (widthStart == 0 && widthEnd == 0))
            {
                cloneNumber--;
                Destroy(clone);
            }*/
        }
        canDraw = true;
        drawCount++;
        Debug.Log(drawCount);
        FreezeMoving.freeze = false;
        // if set to freeze the drawn objects while drawing a new one and is not set to be 
         fixed position, 
        // it adds the script FreezeMoving to the new drawings so it freezes when 
           FreezeMoving.freeze variable is true
        if (fixedPosition == false && clone)
        {
            clone.gameObject.AddComponent<FreezeMoving>();
        }
        else
        {
            if (pathRigidbody != null)
            {
                pathRigidbody.bodyType = RigidbodyType2D.Static;
            }
        }
        Invoke(nameof(StartVehicle),1.5f);
        
    }

}

DestroyLastPathMethod:

  public void DestroyLastPath()
{
    if (paths.Count > 0)
    {
        Destroy(paths[paths.Count - 1]);
        paths.RemoveAt(paths.Count - 1);
    }
   
   
}

StarPrefab Method:

 /// <summary>
/// Instantiate prefab and initialize necessary variables for the drawing construction
/// </summary>

void StarPrefab()
{
    canDraw = true;
    clone = (GameObject)Instantiate(path, mousePointer.transform.position, 
      Quaternion.identity); // instantiate
       prefab
    clone.name = "Drawing" + cloneNumber;
    paths.Add(clone);
        // Rename instantiated object so it can be easyli tracked
    cloneNumber++;                                          // Add 1 in the variable for 
        renaming the drawings
    pathLineRenderer = clone.GetComponent<LineRenderer>();
    pathRigidbody = clone.GetComponent<Rigidbody2D>();
    pathRigidbody.bodyType = RigidbodyType2D.Kinematic;                       // Set 
        rigidbody kinematic so it wont move during the drawing process
    pathRigidbody.gravityScale = gravityScale;              // Adjust gravity for the 
          drawing
    clone.transform.position = Vector3.zero; // Camera.main.transform.position - new
         Vector3(0,0,Camera.main.transform.position.z);
    clone.transform.rotation = Quaternion.identity;
    pathRigidbody.centerOfMass = Vector2.zero;              // Initialize center of mass 
       before calculating the real position
    pathLineRenderer.SetColors(colorStart, colorEnd);       // Set colors
    pathLineRenderer.SetWidth(widthStart, widthEnd);        // width
    newVerticies.Clear();                                   // Clear Lists before adding new 
       points for the new drawing
    newVerticies_.Clear();
    newVerticies2.Clear();                                  // This is the List used to 
          create the Polygon Collider 2D
    pathLineRenderer.SetVertexCount(1);                     // Add one position spot so it 
       can add the first point of the Drawing
    pathLineRenderer.SetPosition(0, mousePointer.transform.position - new
      Vector3(0,0,Camera.main.transform.position.z)); // Add first point in
         the Line Renderer

    newVerticies.Add(mousePointer.transform.position - clone.transform.position); // Add 
            first point to the array used to
        create the Colliders
    newVerticies_.Add(mousePointer.transform.position - clone.transform.position);

    // Check if the chosen collider is Edge or Polygon and destroy the one is not going to 
           be used
    if (colliderType == ColliderTypeChoices.Edge_Collider)
    {
        Destroy(clone.GetComponent<PolygonCollider2D>());
        pathEdgeCollider = clone.GetComponent<EdgeCollider2D>();
    }
    else
    {
        Destroy(clone.GetComponent<EdgeCollider2D>());
        pathPolygonCollider = clone.GetComponent<PolygonCollider2D>();
        pathPolygonCollider.points = newVerticies2.ToArray(); // Bugfix: when creating a new 
           drawing, collider was created in the
        center of the scene and hit some objects
         }
         }

Drawline Method:

   /// <summary>
/// Draw the line using mouse position and adding the points to the Line Renderer
/// </summary>

void DrawVisibleLine()
{
    canDraw = true;
    Debug.Log("drawinggggggggggggggg");
    // Check if the minimun distance (verticesDistance) from the previous vertice is reached 
        and add the next point
    if (Vector2.Distance(mousePointer.transform.position, newVerticies_[posCount]) >= 
           verticesDistance || 
        Vector2.Distance(mousePointer.transform.position, newVerticies_[posCount]) <= 
             verticesDistance
        )
    {
      
        
        posCount++;
        pathLineRenderer.SetVertexCount(posCount + 1);
        pathLineRenderer.SetPosition(posCount, mousePointer.transform.position - new 
             Vector3(0, 0,
           Camera.main.transform.position.z));
        Particle.transform.position = mousePointer.transform.position - new Vector3(0, 0,
         Camera.main.transform.position.z);
        newVerticies_.Add(mousePointer.transform.position - clone.transform.position);
        if (mouseHit == false)
        {
            newVerticies.Add(mousePointer.transform.position - clone.transform.position);

            // Check the chosen collider
            if (colliderType == ColliderTypeChoices.Edge_Collider)
            {
                //for (int i = 0; i < newVerticies.Count - 1; i++)
                //{
                //    // Get the width of the line for each point of it
                //    float tempWidth = Mathf.Lerp(widthStart, widthEnd, (float)i / 
             (newVerticies.Count - 2));
                //    
                //}
                if (newVerticies.Count > 2)
                    pathEdgeCollider.points = newVerticies.ToArray();
                pathEdgeCollider.sharedMaterial = material;
            }
            else
            {
                newVerticies2.Clear();
                newVerticies.Add(mousePointer.transform.position - 
              clone.transform.position);
                for (int i = 0; i < newVerticies.Count - 1; i++)
                {

                    // calculates the angle of each edge in the line
                    colliderAngle = Mathf.Atan2(newVerticies[i].y - newVerticies[i + 1].y, 
                newVerticies[i].x - newVerticies[i + 1].x);
                    colliderAngle = colliderAngle + (Mathf.Deg2Rad * 90f);


                    float cos = Mathf.Cos(colliderAngle);   // calc cos
                    float sin = Mathf.Sin(colliderAngle);   // calc sin

                    // Get the width of the line for each point of it
                    float tempWidth = Mathf.Lerp(widthStart, widthEnd, (float)i / 
                (newVerticies.Count - 2));

                    // To make the Polygon Collider 2D go around the line, it means each 
                  side of the line,
                    // adds one point to the beginning and one to the end of the List
                    newVerticies2.Add(new Vector2(
                                    (newVerticies[i].x) + ((tempWidth / 2) * cos),
                                    (newVerticies[i].y) + ((tempWidth / 2) * sin)));
                    newVerticies2.Insert(0, new Vector2(
                                    (newVerticies[i].x) - ((tempWidth / 2) * cos),
                                    (newVerticies[i].y) - ((tempWidth / 2) * sin)));
                    
                }
                newVerticies.RemoveAt(newVerticies.Count - 1);
                pathPolygonCollider.points = newVerticies2.ToArray();
                pathPolygonCollider.sharedMaterial = material;
            }
        }
    }
    
}

Thanks in Advance!

  • I don't know your line numbers ... double click on the errors in Unity or click the blue links they will directly bring you to the according code line ... I would start checking if `posCount` is valid in `newVerticies_[posCount]` – derHugo Mar 02 '22 at 08:29
  • And for the NullRef your Update method you post is way to complex and we don't know what line `274` is ... but look into your code at line `274` what could possibly be `null` .. then find out why this is the case ;) – derHugo Mar 02 '22 at 08:32
  • Hi @derHugo sir, this is the line 274, pathPolygonCollider.points = newVerticies2.ToArray(); – Burhan Ahmad Mar 02 '22 at 08:40
  • I tried debugging as well but cant seem to find the issue as it works just fine after i get this error once. – Burhan Ahmad Mar 02 '22 at 08:41
  • well then either `pathPolygonCollider` or `newVerticies2` is `null` in that moment .. now find out why this is the case. Where are they assigned? Is i sure that this line is never being executed before these are assigned correctly? It is quite hard to tell as your code snippet is really cluttered .. it is neither a Minimal example nor the entire code .. but something in between which isn't really helpful :) – derHugo Mar 02 '22 at 08:43
  • These are the lines 219 and 401 respectively, 219: DrawVisibleLine(); , 4101: if (Vector2.Distance(mousePointer.transform.position, newVerticies_[posCount]) >= verticesDistance || Vector2.Distance(mousePointer.transform.position, newVerticies_[posCount]) <= verticesDistance ) – Burhan Ahmad Mar 02 '22 at 08:43
  • I'm sorry should i post the function in which this is happening instead? – Burhan Ahmad Mar 02 '22 at 08:45
  • You should post a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) of your code ... however, in your case this might be quite difficult to achieve since you seem to not even know what is possibly related to the error and what not. All we can ell you from here is that either `pathPolygonCollider` or `newVerticies2` is `null` in that moment and that `posCount` is either `< 0` or `>= newVerticies_.Count` ... the **why** you will have to figure out yourself I guess or somehow provide the complete code ^^ – derHugo Mar 02 '22 at 08:47
  • I'll try to see if pathpolygonCollider/ newvertices2 is null, if I find something then I'll let you know sir @derHugo – Burhan Ahmad Mar 02 '22 at 08:54
  • @derHugo So when I click the first time the vertices are not added in either newverticies_ or newverticies2 and I want my mousehit/ when I click on screen to add vertices to these two lists. I can share code with you if you say so :( – Burhan Ahmad Mar 02 '22 at 11:31
  • @derHugo actually, when I go to my level from the main menu like when i turn on the game and start a level this works fine. The line is drawn on first touch. But when I restart or go to the next level (I have used the restart logic on next level) it doesnt work first time and gives these two errors: Error 1: ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (on lines 415 and 220) and the second error, Error2: NullReferenceException: (on line 277) – Burhan Ahmad Mar 02 '22 at 11:33

0 Answers0