[Solved]OnMouseDown() execute only once

I have the following scripts:

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

public class Turret : MonoBehaviour {

    public Transform target;
    private Enemy targetEnemy;

    [Header("General")]
    public float range = 15f;

    [Header("Use Bullets (default)")]
    public float fireRate = 1f;
    private float fireCountdown = 0f;

    [Header("Use Ice")]
    public bool useIce = false;
    public float slowAmount = .5f;
    public float slowRange = 10;

    [Header("Use Fire or Lighting")]
    public bool useFireOrLighting;

    public int damageOverTime = 55;
    public float damageRadius;

    [Header("Unity Setup Fields")]
    public GameObject rangeView;
    public string enemyTag = "Enemy";

    public Transform partToRotate;
    public float turnSpeed = 10f;

    public GameObject bulletPrefab;
    public Transform firePoint;

    public GameObject weaponTrail;

    private Animator anim;

    private GameObject thisTurret;
  
    BuildManager buildManager;

    private void Awake()
    {
        anim = GetComponentInChildren<Animator>();
    }

    // Use this for initialization
    void Start ()
    {
        thisTurret = this.gameObject;

        InvokeRepeating("UpdateTarget", 0f, 0.5f);

        buildManager = BuildManager.instance;
    }

    public Vector3 GetBuildPosition()
    {
        return transform.position;
    }

    private void OnMouseDown()
    {
        Debug.Log("This turret is: " + thisTurret.ToString());
        if (EventSystem.current.IsPointerOverGameObject())
        {
            return;
        }

        if (thisTurret != null)
        {
            buildManager.SelectTurret(thisTurret);
        }
    }

    void UpdateTarget()
    {
        GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        float shortestDistance = Mathf.Infinity;
        GameObject nearestEnemy = null;

        foreach(GameObject enemy in enemies)
        {
            float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
            if(distanceToEnemy <= range)
            {
                targetEnemy = enemy.GetComponent<Enemy>();
            }

            //Default Target
            if (distanceToEnemy < shortestDistance)
            {
                shortestDistance = distanceToEnemy;
                nearestEnemy = enemy;
            }
          
            //Nearest Target
            //if(distanceToEnemy <= range)
            //{
            //    shortestDistance = distanceToEnemy;
            //    nearestEnemy = enemy;
            //}
        }

        if(nearestEnemy != null && shortestDistance <= range)
        {
            target = nearestEnemy.transform;
            //targetEnemy = nearestEnemy.GetComponent<Enemy>();
            anim.SetBool("isAttacking", true);
            weaponTrail.SetActive(true);
        }
        else
        {
            target = null;
        }
    }
  
    // Update is called once per frame
    void Update ()
    {

        if(target == null)
        {
            anim.SetBool("isAttacking", false);
            weaponTrail.SetActive(false);
            return;
        }

        LockOnTarget();

        if(fireCountdown <= 0f)
        {
            Shoot();
            fireCountdown = 1f / fireRate;
        }

        fireCountdown -= Time.deltaTime;
    }

    void LockOnTarget()
    {
        //Target lock on
        Vector3 dir = target.position - transform.position;
        Quaternion lookRotation = Quaternion.LookRotation(dir);
        Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
        partToRotate.rotation = Quaternion.Euler(0f, rotation.y, 0f);
    }

    void Shoot()
    {
        //anim.SetBool("isAttacking", true);
        //weaponTrail.SetActive(true);

        if(useFireOrLighting)
        {
            FireAndLighting();
        }
        else if(useIce)
        {
            IceAttack();
        }
        else
        {
            //Debug.Log("Use bullets!");
            GameObject bulletGO = (GameObject)Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
            Bullet bullet = bulletGO.GetComponent<Bullet>();

            if (bullet != null)
            {
                //Debug.Log("We shoot");
                bullet.Seek(target);
            }
        }
    }

    void FireAndLighting()
    {
        //target.GetComponent<Enemy>().TakeDamage(damageOverTime * Time.deltaTime);

        Collider[] colliders = Physics.OverlapSphere(transform.position, damageRadius);

        foreach (Collider collider in colliders)
        {
            if (collider.tag == "Enemy")
            {
                targetEnemy.TakeDamage(damageOverTime * Time.deltaTime);
            }
        }
    }

    void IceAttack()
    {
        //Debug.Log("It use Ice!");

        Collider[] colliders = Physics.OverlapSphere(transform.position, slowRange);
      
        foreach (Collider collider in colliders)
        {
            if (collider.tag == "Enemy")
            {
                targetEnemy.Slow(slowAmount);
                GameObject bulletGO = (GameObject)Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
                Bullet bullet = bulletGO.GetComponent<Bullet>();

                if (bullet != null)
                {
                    //Debug.Log("We shoot");
                    bullet.Seek(target);
                }
            }
        }
    }


    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, range);
    }
}

and

using UnityEngine;

public class BuildManager : MonoBehaviour {

    public static BuildManager instance;

    private void Awake()
    {
        //if (instance != null)
        //{
        //    Debug.Log("More than one BuildManager in scene!");
        //    return;
        //}
        //instance = this;

        //Check if instance already exists
        if (instance == null)
            instance = this;
        else if (instance != this)
            Destroy(gameObject);

        DontDestroyOnLoad(gameObject); //Keep this object when loading a new scene
    }

    [Header("Nodes")]
    public GameObject nodes;

    [Header("Build Effect")]
    public GameObject buildEffect;

    private TurretBlueprint turretToBuild;
    private BoxCollider bC;
    private GameObject currentTurretRange;
    private GameObject selectedTurret;
    private GameObject oldSelectedTurret;
  
    public TurretUI turretUI;

    [HideInInspector]
    public Transform currentTurret;

    public bool CanBuild { get { return turretToBuild != null; } }

    private void Update()
    {
        if (currentTurret != null)
        {
            Vector3 m = Input.mousePosition;
            m = new Vector3(m.x, m.y, transform.position.y);
            Vector3 p = Camera.main.ScreenToWorldPoint(m);
            currentTurret.position = new Vector3(p.x, p.y, p.z);
        }

        if (Input.GetMouseButtonDown(0) && currentTurret != null)
        {
            Destroy(currentTurret.gameObject);
        }
    }

    public void SelectTurret(GameObject turret)
    {
        if(selectedTurret == turret)
        {
            Debug.Log("Selected turret is: " + selectedTurret.ToString());
            DeselectTurret(selectedTurret);
            return;
        }

        selectedTurret = turret;
        Debug.Log("Selected turret here is: " + selectedTurret.ToString());
        Debug.Log("Pasted turret here is: " + turret.ToString());
        if (oldSelectedTurret == null)
        {
            oldSelectedTurret = selectedTurret;
        }

        //Debug.Log("Selected turret is: " + selectedTurret.ToString());

        if (oldSelectedTurret != selectedTurret)
        {
            turretUI.Hide(oldSelectedTurret);

            //Debug.Log("Old in if Selected turret is: " + oldSelectedTurret.ToString());

            oldSelectedTurret = selectedTurret;
        }
        //Debug.Log("Current Selected turret is: " + selectedTurret.ToString());

        turretToBuild = null;

        turretUI.SetTarget(selectedTurret);
    }

    public void DeselectTurret(GameObject turret)
    {
        if(turret != null)
        {
            Debug.Log("Turret to deselect is: " + turret.ToString());
            turretUI.Hide(turret);
            selectedTurret = null;
        }
        else
        {
            Debug.Log("Turret to deselect is null!");
        }
    }

    public void SelectTurretToBuild(TurretBlueprint turret, GameObject range)
    {
        turretToBuild = turret;
        //selectedTurret = null;
        currentTurretRange = range;
        nodes.SetActive(true);
        currentTurret = ((GameObject)Instantiate(turretToBuild.prefab)).transform;
        ChangeRangeMat changeRangeMat = (ChangeRangeMat)FindObjectOfType(typeof(ChangeRangeMat));
        changeRangeMat.RangeMatRed();
        currentTurretRange.SetActive(true);
        currentTurret.GetComponent<Turret>().range = 0f;
        DeselectTurret(null);
    }

    public void BuildTurretOn(Node node)
    {
        //Build a turret
        if(PlayerStats.Money < turretToBuild.cost)
        {
            Debug.Log("Not enough money to build that!");
            return;
        }

        if (currentTurret != null && CanBuild)
        {
            PlayerStats.Money -= turretToBuild.cost;

            GameObject turret = (GameObject)Instantiate(turretToBuild.prefab, node.GetBuildPosition(), Quaternion.identity);
            node.turret = turret;

            GameObject effect = (GameObject)Instantiate(buildEffect, node.GetBuildPosition(), Quaternion.identity);
            Destroy(effect, 5f);

            Destroy(currentTurret.gameObject);
            node.turret.transform.GetChild(0).gameObject.SetActive(false);
            node.turret.transform.GetChild(1).gameObject.SetActive(false);
            bC = node.turret.AddComponent<BoxCollider>();
            bC.size = new Vector3(2, 34, 2);

            BoughtTurret();

            //Debug.Log("Turret build! Money left: " + PlayerStats.Money);
        }
    }

    public void BoughtTurret()
    {
        turretToBuild = null;
        currentTurret = null;
        nodes.SetActive(false);
        //currentTurretRange.SetActive(false);
        currentTurretRange = null;
    }
}

As the title say the OnMouseDown() executes only once then stop working and is not the console collapse

Try making the function public.

That should make no difference. Methods in MonoBehaviour like OnMouseDown are retrieved using reflection and the access modifier is pretty much ignored. I’d recommend protected, so you are able to override the method in subclasses, but that doesn’t help here.

The most common source for the only working once issues, is that the first time the method is called, it deactivates the GameObject and therefore, the method is no longer called. I don’t think that’s the case here, but it’s worth a check.

What does the Console say? Would be nice to see how far things actually get.

I suspect that’s the expected behaviour. It is called when the mouse is pressed down on the object but not every subsequent frame. If you look at the API documentation for MouseOver it states how it is called every frame whereas MouseDown does not state that so I think the results you’re getting is as expected.

Therefore, it’s up to you to track when the button is released or leaves the object.

1 Like

This turret is: NeolithicKnifeTurret(Clone) (UnityEngine.GameObject)
UnityEngine.Debug:Log(Object)
Turret:OnMouseDown() (at Assets/Scripts/Turret.cs:69)
UnityEngine.SendMouseEvents:smile:oSendMouseEvents(Int32)

Selected turret here is: NeolithicKnifeTurret(Clone) (UnityEngine.GameObject)
UnityEngine.Debug:Log(Object)
BuildManager:SelectTurret(GameObject) (at Assets/Scripts/BuildManager.cs:69)
Turret:OnMouseDown() (at Assets/Scripts/Turret.cs:77)
UnityEngine.SendMouseEvents:smile:oSendMouseEvents(Int32)

Pasted turret here is: NeolithicKnifeTurret(Clone) (UnityEngine.GameObject)
UnityEngine.Debug:Log(Object)
BuildManager:SelectTurret(GameObject) (at Assets/Scripts/BuildManager.cs:70)
Turret:OnMouseDown() (at Assets/Scripts/Turret.cs:77)
UnityEngine.SendMouseEvents:smile:oSendMouseEvents(Int32)

and then it say nothing

On second click it should say: Debug.Log("Selected turret is: " + selectedTurret.ToString());

]QUOTE]I suspect that’s the expected behaviour. It is called when the mouse is pressed down on the object but not every subsequent frame. If you look at the API documentation for MouseOver it states how it is called every frame whereas MouseDown does not state that so I think the results you’re getting is as expected.

Therefore, it’s up to you to track when the button is released or leaves the object.[/QUOTE]

I have tried to do OnMouseExit it dose’t change a thing.

Are you sure, EventSystem.current.IsPointerOverGameObject() is false and thisTurret isn’t null?

yes it work once and I tried by commenting both if statements

Bump. Anyone have any idea ?

It seems I was changing Layers but not all the children layers