Home > Net >  How to change the position of GameObjects with Unity Input.GetMouseButtonDown method?
How to change the position of GameObjects with Unity Input.GetMouseButtonDown method?

Time:09-16

I already know how to click on 3D Objects in the scene by using the Input.GetMouseButtonDown. I'm trying to change the 3D Object position by clicking on the object. I added a Box Collider in the object and I'm calling the following method.

void Update() {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                foreach (GameObject child in floorTiles) {
                    BoxCollider box = child.GetComponentInChildren<BoxCollider>();
                    
                    if (hit.transform.name.Equals(box.name))
                    {
                        
                        handleOnMouseDown(hit.collider);
                    }
                }
            }
        }
    }

floorTiles is an array of GameObjects.

If I hit one of these objects the below function is called:

void handleOnMouseDown(Collider box) {
        GameObject parent = box.transform.parent.gameObject;
        Vector3 position = parent.transform.position;
        
        positionX.GetComponent<TextMeshProUGUI>().text = position.x.ToString();
        
        posXButtonPlus.GetComponent<Button>().onClick.AddListener(() => handleOnChangePosition("posx", parent));
    }

This works, however, when I click many objects, all the last objects clicked also keep changing their positions. How can I change one position per time?

CodePudding user response:

Each click on an object, adds listener to your button, but you don't ever remove listeners. You end up with multiple listeners, that's why more objects are moved than intended.

You could remove listener after each button click, but that seems like a total overkill.

Instead of adding multiple listeners, consider adding just one which will remember the last clicked object, and clicking your button will move only that object.

Also, if you want to move objects just by clicking on them, not on button click, you can simplify all these, and move the object directly in handleOnMouseDown.

Remove listeners variant:

void handleOnMouseDown(Collider box)
{
    posXButtonPlus.GetComponent<Button>().onClick.AddListener(() => handleOnChangePosition("posx", box.gameObject));
}

void handleOnChangePosition(string pos, GameObject go)
{
    // I don't have code for moving, but I imagine looks something like this. right * 0.5f can be anything, did it just for tests.
    go.transform.position  = Vector3.right * 0.5f;

    posXButtonPlus.GetComponent<Button>().onClick.RemoveAllListeners();
}

Last clicked variant:

GameObject lastClicked;

void Awake()
{
    posXButtonPlus.GetComponent<Button>().onClick.AddListener(() => handleOnChangePosition());
}
void handleOnMouseDown(Collider box)
{
    lastClicked = box.gameObject;
    
}

void handleOnChangePosition()
{
    lastClicked.transform.position  = Vector3.right * 0.5f;
}

Without buttons and other stuff:

void handleOnMouseDown(Collider box)
{
    box.transform.position  = Vector3.right * 0.5f;
}
  • Related