Making LockOn System But having InvalidOperationException, ObjectDisposedException Error,, Please Help me :(



So I’m making LockOn to Enemy like eldenring,
I’m using
[SerializeField] List targetEnemy = new List();
to store while using new InputSystem. (rightClick)

the problem is IT’S WORKING But not always

when i click the rightmousebtn too quick
InvalidOperationException, ObjectDisposedException Error Occurs like last picture

Or when i got out of my lockOnRadius too fast the Error Occurs
but when i go back in and click the right mouse btn 3times over it works, but i want to handle with no bugs,

I spend my whole day trying out what was the problem and trying to catch the exception,
but i didn’t make it, :frowning:
please help me with my code,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
using Unity.VisualScripting;

public class LockOn : MonoBehaviour
{
    [SerializeField] float lockOnRadius = 12;
    [SerializeField] LayerMask targetLayer;
    [SerializeField] float minViewAngle = 0f;
    [SerializeField] float maxViewAngle = 360f;

    [SerializeField] List<EnemyAttributesManager> targetEnemy = new List<EnemyAttributesManager>();
    [SerializeField] Transform lockOnImage;

    [SerializeField] CinemachineFreeLook playerCam; 
    [SerializeField] CinemachineFreeLook enemyCam; 

    EnemyAttributesManager currentTarget;
    Vector3 currentTargetPosition;

    public bool isFindTarget = false;
    private Transform cameraTransform;
    // Start is called before the first frame update
    void Awake()
    {
        cameraTransform = Camera.main.transform;
    }

    private void Start()
    {
        lockOnImage.gameObject.SetActive(false);
        enemyCam.Priority = 0;
    }

    private void Update()
    {       
        if (isFindTarget && isTargetRange())
        {
            if (currentTarget != null && targetEnemy.Count > 0)
            {
                LookAtTarget();
            }
            else
            {
                ResetTarget();
            }
        }else if (!isTargetRange())
        {
            ResetTarget();
        }
    }

    private void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(transform.position, lockOnRadius);
    }

    public void FindLockOnTarget()
    {
        Collider[] findTarget = Physics.OverlapSphere(transform.position, lockOnRadius, targetLayer);

        for (int i = 0; i < findTarget.Length; i++)
        {
            EnemyAttributesManager target = findTarget[i].GetComponent<EnemyAttributesManager>();

            if (target != null)
            {
                Vector3 targetDir = target.transform.position - transform.position;

                float viewAngle = Vector3.Angle(targetDir, cameraTransform.forward);

                if (viewAngle > minViewAngle && viewAngle < maxViewAngle)
                {
                    RaycastHit hit;
                    
                    if(Physics.Linecast(transform.position,
                        target.transform.position,out hit, targetLayer))
                    {
                        targetEnemy.Add(target);
                    }
                }
                else
                {
                    ResetTarget();
                }
            }
        }        

        if (targetEnemy.Count > 0 && isTargetRange())
        {
            LockOnTarget();
        }
        else
        {
            ResetTarget();
        }
        
    }

    private void LockOnTarget()
    {
        if(targetEnemy == null || targetEnemy.Count == 0)
        {
            ResetTarget();
            return;
        }

        float shortDistance = Mathf.Infinity;


        for (int i = 0; i < targetEnemy.Count; i++)
        {
            float distanceFromTarget = Vector3.Distance(transform.position, targetEnemy[i].transform.position);

            if(distanceFromTarget < shortDistance)
            {
                shortDistance = distanceFromTarget;
                currentTarget = targetEnemy[i];
            }
        }


        if(currentTarget != null)
        {
            enemyCam.Priority = 11;
            enemyCam.m_LookAt = targetEnemy[0].transform;
            FindTarget();
        }
    }

    private void LookAtTarget()
    {
        if(currentTarget == null)
        {            
            ResetTarget();
            return;
        }

        if (!isTargetRange())
        {
            isFindTarget = false;
            ResetTarget();
            return;
        }

        currentTargetPosition = currentTarget.transform.position;

        lockOnImage.position = Camera.main.WorldToScreenPoint(currentTargetPosition + new Vector3(0, 1f, 0)); ;

        Vector3 dir = (currentTargetPosition - transform.position).normalized;
        dir.y = transform.position.y;

        transform.forward = Vector3.Lerp(transform.forward, dir, Time.deltaTime * 20f);
    }

    private void FindTarget()
    {
        isFindTarget = true;

        lockOnImage.gameObject.SetActive(true);
    }

    private bool isTargetRange()
    {
        float distance = (transform.position - currentTargetPosition).magnitude;

        if(distance > lockOnRadius)
        {
            ResetTarget();
            return false;
        }
        else
        {
            return true;
        }
    }

    public void ResetTarget()
    {
        targetEnemy.Clear();
        isFindTarget = false;
        currentTarget = null;
        lockOnImage.gameObject.SetActive(false);
        enemyCam.Priority = 0;
    }
}

and this is what i use in new input system in my characterController

    public void LockOn(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            _lockOn = !_lockOn;

            if (_lockOn)
            {
                lockOn.ResetTarget();
                lockOn.FindLockOnTarget();
            }
            else
            {
                lockOn.ResetTarget();
            }
        }
    }

This is going to fail:

when your targetEnemy list is empty, as it is in your second screenshot.

Check the .Length property before using the 0th entry.

Here’s more reading:

Here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

http://plbm.com/?p=236

Steps to success:

  • find which collection it is and what line of code accesses it <— (critical first step!)
  • find out why it has fewer items than you expect
  • fix whatever logic is making the indexing value exceed the collection size

Remember also:

  • a collection with ZERO elements cannot be indexed at all: it is empty
  • you might have more than one instance of this script in your scene/prefab
  • the collection may be used in more than one location in the code
  • indices start at ZERO (0) and go to the count / length minus 1.

This means with three (3) elements in your collection, they are numbered 0, 1, and 2 only.

1 Like