M
M
Mimocodil2022-04-18 21:25:58
Unity
Mimocodil, 2022-04-18 21:25:58

How to click on buttons in 3D?

There are 4 buttons in the field of view of the fixed camera. Buttons are ordinary cubes with colliders. The mouse is not fixed and is used to control the game. When you click on each of the buttons, a different event should occur.

625dabe6842cb221996534.png

At the moment the code is like this (below). It works only if the camera is rotated, and the mouse is in the center, and there is a beam "shot" current in front of the camera. How to remake it so that it works with a fixed camera and a moving mouse?

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

public class ButtonClick : MonoBehaviour {

  [SerializeField] private Transform aimPoint;
  [SerializeField] private float range;

  [SerializeField] private string leftRedTag;
  [SerializeField] private string leftWhiteTag;
  [SerializeField] private string rightRedTag;
  [SerializeField] private string rightWhiteTag;

  private void Update() {
    if (Input.GetMouseButtonDown(0)) {
      RaycastHit hit;
      if (Physics.Raycast(aimPoint.position, aimPoint.forward, out hit, range))
        OnButtonClick(hit.transform.gameObject.tag);
    }
  }

  private void OnButtonClick(string tag) {
    if (tag == leftRedTag) {
      // код левой красной кнопки
    } else if (tag == leftWhiteTag) {
      // код левой белой кнопки
    } else if (tag == rightRedTag) {
      // код правой красной кнопки
    } else if (tag == rightWhiteTag) {
      // код правой белой кнопки
    }
  }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
K
K0TlK, 2022-04-19
@Ezekiel4

You raycast somewhere forward from some transform, and you need to raycast towards the cursor. Camera.ScreenPointToRay returns a ray that goes from the camera to a location on the screen. Example:

var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity))
{
    Debug.DrawRay(hit.point, hit.normal * 10, Color.red, 10f);
}

And don't use tags like that. When you have not 4 buttons, but 40, will you have 40 conditions in the OnButtonClick method? And if you wrote a tag with an error, then you will look for where the errors come from? Select these buttons separately, get the required component when raycasting, and call the OnButtonClick method already on a separate component.
public interface IButton
{
    public void OnClick();
}

public class YellowButton : IButton
{
    public void OnClick()
    {
        Debug.Log("Yellow");
    }
}

public class Example : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity))
            {
                if(hit.transform.TryGetComponent(out IButton button))
                {
                    button.OnClick();
                }
            }
        }

    }
}

Also, each component can have an OnMouseDown method that is called when the player clicks on it. You can create a button component and when you click on it, an event will be called, to which you can subscribe the necessary methods.
public class Button : MonoBehaviour
{
    public event Action ButtonPressed;

    private void OnMouseDown()
    {
        ButtonPressed?.Invoke();
    }

}

public class ButtonHandler : MonoBehaviour
{
    [SerializeField] private Button _button;

    private void OnEnable()
    {
        _button.ButtonPressed += DoStuff;
    }

    private void OnDisable()
    {
        _button.ButtonPressed -= DoStuff;
    }

    private void DoStuff()
    {

    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question