Search Unity

Creating new object at runtime which is distinct from other objects created from the same prefab

Discussion in 'Prefabs' started by jeremy1967, Jun 4, 2019.

  1. jeremy1967

    jeremy1967

    Joined:
    Jun 4, 2019
    Posts:
    6
    Hi. I have searched for this answer, but have so far been unsuccessful in finding a working solution to my problem so my apologies if this has been asked/answered already.

    I have a prefab object with a script attached. At runtime, I call Instantiate() to create a new instance (clone) of the prefab object. This works fine and I can successfully create numerous instances in the game.

    My problem arises from the fact that I am calling 'Input.GetMouseButtonDown()' inside of Update(). My expectation is that I would see this called exactly once in the frame corresponding to a specfic object that was clicked on. Instead, what I see is this getting called for EVERY object that was created from the prefab, not just the one that was clicked.

    I assume this is because the script attached to the prefab is shared among all the clone instance (i.e. they don't each get an independent copy).

    Can someone please explain how I can achieve my desire result of Input.GetMouseButtonDown() only getting called one time for the specific object that was clicked?

    Just to further illustrate, if I have the below code in the script attached to the prefab:

    Code (CSharp):
    1. void Update()
    2. {
    3.     if (Input.GetMouseButtonDown(1))
    4.     {
    5.         Debug.Log("Right button clicked");
    6.     }
    7. }
    and if I have 10 in-game objects, clicking on any one of them will result in the message, "Right button clicked", printed 10 times.

    Thanks for any help.
     
    Last edited: Jun 4, 2019
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    436
  3. TimmyTheTerrible

    TimmyTheTerrible

    Joined:
    Feb 18, 2017
    Posts:
    105
    Usually your components should not handle input at all, but have methods that some other input manager class can call to interact with it.

    As an example, say you have a squad of soldiers your player can control. When a soldier is instantiated it adds itself to a list(a ScriptableObject class with a list property is perfect for this).

    Now your input manager component would store an index into this list as to which soldier the player has selected, and it handles the input detection, and calls the functions on the currently selected soldier.

    The soldier component doesn't handle any of the input, it just has data and methods that can be called.
     
  4. jeremy1967

    jeremy1967

    Joined:
    Jun 4, 2019
    Posts:
    6
    Thanks for the replies! So if I understood everything I read, I came up with the following code and so far it seems to be working:

    Code (CSharp):
    1. private Raycast hitInfo;
    2.  
    3. void Update()
    4. {
    5.     if (Input.GetMouseButtonDown(1))
    6.     {
    7.         if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo))
    8.         {
    9.             if (gameObject == hitInfo.collider.gameObject)
    10.             {
    11.                 DoSomething();
    12.             }
    13.         }
    14.     }
    15. }
    16.  
    With this implementation, I still get the multiple hits on the GetMouseButtonDown() method, but filtering on the gameObject embedded in the Raycast appears to be the key to what I was after. Please let me know if you see any problems with this approach.

    Thanks again!