Home > Mobile >  Can't check list in script in Unity3D
Can't check list in script in Unity3D

Time:11-02

Me need check list to lengt, but why it don't work.

I want deteche object, i want make destroy block as minecraft

How i make it:

i set list of objects

if collider touch X object and left button click - destroy target from list in first position, but if X object is X object - don't destroy object in the list

But i get error: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index - if collider touch obejcts: WorldMap, Water, Berries

i can't tell about this in details. Best review my code:


using System.Collections.Generic;
using System.Collections;
using UnityEngine;

public class GetTarget : MonoBehaviour
{
    [Header("Координаты блока")] // block positions
    public int positionX;
    public int positionY;
    public int positionZ;

    [Header("Получение цели")] // set list for block to destroy
    public static List<GameObject> target = new List<GameObject>();

    private void OnTriggerStay(Collider collider)
    {
        target.Insert(0, collider.gameObject);

        if(target[0].name == "WorldMap") // can't destroy world map
        {
            if(target.Count != 0)
            {
                Debug.Log("Вы не можете получить "   target[0]); // you can't get (test message)
                target.Remove(collider.gameObject);  
            }
        }
        if(target[0].name == "Water") // you can't destroy water in structure
        {
            if(target.Count != 0)
            {
                Debug.Log("Вы не можете получить "   target[0]); // you can't get (test message)
                target.Remove(collider.gameObject);  
            }
        }
        if(target[0].name == "Berries") // you can't destroy berries
        {
            if(target.Count != 0)
            {
                Debug.Log("Вы не можете получить "   target[0]); // you can't get (test message)
                target.Remove(collider.gameObject);  
            }
        }
    }

    private void Update() // i get position for collider
    {
        Vector3 positions = transform.position;

        positionX = (int)Mathf.Round(gameObject.transform.position.x);
        positionY = (int)Mathf.Round(gameObject.transform.position.y);
        positionZ = (int)Mathf.Round(gameObject.transform.position.z);

// set position for collider - positions = transfrom.position

        positions.x = positionX;
        positions.y = positionY;
        positions.z = positionZ;
    }
}


CodePudding user response:

While I can't be certain without line numbers it looks like your error is happening as you remove the target but the top level ifs don't check if the target count is greater then zero.

Your code right now is this

if(target[0].name == "WorldMap") // can't destroy world map

you should change all those ifs to follow this logic

if(target.Count() > 0 && target[0].name == "WorldMap") // can't destroy world map

that should solve the index out of range exception.

CodePudding user response:

To answer your initial question, the reason you're getting the out of bounds is because in some scenarios, you're removing the last item in the list, but you then still try and check the target arrays [0] index. You're removing elements with target.Remove(collider.gameObject) which then leaves all following target[0] checks being out of range.

A quick cleanup of the code might look something like this:

public class GetTarget : MonoBehaviour
{
    // These can be assigned as a Vector3Int.
    [Header("Координаты блока")] // block positions
    //public int positionX;
    //public int positionY;
    //public int positionZ;
    public Vector3Int position;


    [Header("Получение цели")] // set list for block to destroy
    public static List<GameObject> target = new ();

    // You probably only want to check for this when the collider first makes contact.
    private void OnTriggerEnter ( Collider collider )
    {
        /*
            Shouldn't you be checking an object's tag, not the object name?
            e.g.
            if ( collider.CompareTag( "WorldMap" ) ) { ... }
        */
        if ( collider.gameObject.name == "WorldMap" ||
            collider.gameObject.name == "Water" ||
            collider.gameObject.name == "Berries" )
        {
            Debug.Log ( $"Вы не можете получить {collider.gameObject.name}" ); // you can't get (test message)
            return;
        }

        // I don't know why you need to insert at index 0, so I won't change it.
        target.Insert ( 0, collider.gameObject );
    }

    private void Update ( ) // i get position for collider
    {
        var pos = transform.position;
        position = new Vector3Int ( 
            ( int ) Mathf.Round ( pos.x ), 
            ( int ) Mathf.Round ( pos.y ), 
            ( int ) Mathf.Round ( pos.z ) ) ;

        // I THINK you wanted to then assign the rounded position to the transform position:
        transform.position = position;
    }
}
  • Related