Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

How to setup an action to detect mouse click (placing object in world)?

Discussion in 'Input System' started by JacketPotatoeFan, Aug 21, 2019.

  1. JacketPotatoeFan

    JacketPotatoeFan

    Joined:
    Nov 23, 2016
    Posts:
    34
    What I want to do is when you press the left mouse button, something happens (place object). I don't want that thing to happen continuously, which is what I am experiencing.

    I have an action setup for the left mouse button. Action type is "Button", interaction is "Press".

    My code that runs:

    Code (CSharp):
    1. public void OnMouseLeft(InputAction.CallbackContext context){
    2.     // Do something when pressed
    3. }
    I press the left mouse button, I want it to do 1 thing (i.e place an object in the world). Am confused on how to check for that. I tried "Tap" but that had the same issue. I looked at the properties of "context" but I am not sure which to use.

    Edit: 0.9.3 is the version I am using
     
  2. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    I assume you are using PlayerInput with Behavior set to "Invoke Unity Events". In that case, you're getting a callback for all three state changes on actions: started, performed, and cancelled. Modifying the callback like so should do the trick.

    Code (CSharp):
    1. public void OnMouseLeft(InputAction.CallbackContext context){
    2.     if (context.performed)
    3.         // Do something when pressed
    4. }
     
  3. JacketPotatoeFan

    JacketPotatoeFan

    Joined:
    Nov 23, 2016
    Posts:
    34
    Thanks for replying.

    I was hoping that I could set a bool in my class as I need to access it outside of my input manager.

    Code (CSharp):
    1. public void OnMouseLeft(InputAction.CallbackContext context){
    2.     if(context.performed){
    3.         this.mouseLeft = true;
    4.     } else {
    5.         this.mouseLeft = false;
    6.     }
    7. }
    This doesn't work, am not sure on how to do this correctly.

    Sorry.
     
  4. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    From the looks of it, I'd say that would be expected to work. What's failing?

    In case all you need to do is query the current state of the action, you can also just poll it.

    Code (CSharp):
    1. // Put *after* PlayerInput so it gets enabled after it.
    2. public class MyBehavior : MonoBehaviour
    3. {
    4.     public PlayerInput input;
    5.     private InputAction mouseLeftAction;
    6.  
    7.     public void OnEnable()
    8.     {
    9.         mouseLeftAction = input.actions["MouseLeft"];
    10.     }
    11.  
    12.     public void Update()
    13.     {
    14.         if (MouseLeftAction.triggered)
    15.             /* ... */;
    16.     }
    17. }
     
    JacketPotatoeFan likes this.
  5. JacketPotatoeFan

    JacketPotatoeFan

    Joined:
    Nov 23, 2016
    Posts:
    34
    It acts as if it's continuously held.

    I guess what I am trying to achieve is exactly the behavior of
    Input.GetMouseButtonDown
    .

    Following your sample code does work, so thanks for that.
     
  6. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    @Rene-Damm Wait, wait, I have a question for this.

    What do you mean by: // Put *after* PlayerInput so it gets enabled after it.
    Do you mean to add this MyBehaviour-Component in the ComponentHierarchy of a GameObject AFTER the PlayerInput-Component? This implies that OnEnable gets called deterministic/hierarchical, that true or did I misunderstand that?
     
  7. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Goes to show how much stuff I have forgotten. So, after taking a closer look... scratch all that. My memory told me that we Awake() by serialization order (and queue, which however doesn't matter for MBs) but OnEnable() by component order. Which, if I had read this post by the grand master before, I would have known is bogus.

    So yeah, guess it's down to script execution order to sort this one out :(

    The fact it even matters is unfortunate and probably something that PlayerInput should handle internally. Thing is that PlayerInput may duplicate its actions in OnEnable(). If you look them up before, you may reference the wrong action. Let me have a look and see how to handle that better in PlayerInput itself.
     
    BTStone likes this.
  8. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Alrighty then, I almost thought: holy S***, did you folks change something so fundamental and didn't tell anyone? :D
     
  9. adamoverstreet20

    adamoverstreet20

    Joined:
    Jan 4, 2021
    Posts:
    4
    Gota question for you if you wouldn't mind taking a look at my script
    I got these buttons i want to use the buttons to select a index of the character list

    question is how would i update ....

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

    public partial class CharacterSeletion : MonoBehaviour
    {
    private GameObject[] characterList;
    private int index;

    private void Start()
    {
    index = PlayerPrefs.GetInt("CharacterSelected");

    characterList = new GameObject[transform.childCount];

    for (int i = 0; i < transform.childCount; i++)
    characterList = transform.GetChild(i).gameObject;
    foreach (GameObject go in characterList)
    go.SetActive(false);

    if (characterList[index])
    characterList[index].SetActive(true);

    }
    public void ToggleLeft()

    {

    characterList[index].SetActive(false);

    index--;
    if (index < 0)
    index = characterList.Length - 1;

    characterList[index].SetActive(true);
    }

    public void ToggleRight()
    {

    {

    characterList[index].SetActive(false);

    index++;
    if (index == characterList.Length)
    index = 0;

    characterList[index].SetActive(true);
    }
    }
    public void SinglePlayerButton()
    {
    PlayerPrefs.SetInt("CharacterSelected", index);
    SceneManager.LoadScene("Game");

    }
    public void MultiplePlayerButton()
    {
    PlayerPrefs.SetInt("CharacterSelected", index);
    SceneManager.LoadScene("MultiplePlayer");

    }
    public void ToAnimalSelectionButton()
    {
    PlayerPrefs.SetInt("CharacterSelected", index);
    SceneManager.LoadScene("AnimalSelection");

    }
    public void ToMainMenuButton()
    {
    PlayerPrefs.SetInt("CharacterSelected", index);
    SceneManager.LoadScene("MainMenu");

    }
    }

    To make it where instead of arrows being used its the buttons grabbing the indexes?

    I figured that code for my animal selection now I wanna upgrade it some can you explain what part I have to change for it or do I need to rewrite it all? I just want the buttons to make one of the CharacterSelected object index to appear, so that'll be targeted and making it appear right? Still learning some here