Search Unity

Selecting Tiles With Raycast (Unity 2D)

Discussion in 'Scripting' started by ThisIsNotATest, Nov 18, 2017.

  1. ThisIsNotATest

    ThisIsNotATest

    Joined:
    Nov 18, 2017
    Posts:
    6
    So I am making a game in 2D that will involve clicking on tiles with a recast. Unfortunately, overtime I try to use it the raycast fires but returns a miss. Does anybody have any idea what the problem is?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class SelectionManager : MonoBehaviour {
    5.     public static SelectionManager me;
    6.  
    7.     [SerializeField]
    8.     GameObject currentlySelected;
    9.  
    10.     [SerializeField]
    11.     TileMasterClass[] objectsWithSuperClass;
    12.  
    13.     void Awake () {
    14.         findAllSuperClassExamples();
    15.     }
    16.  
    17.     void Start () {
    18.  
    19.     }
    20.  
    21.     void Update () {
    22.         checkForLeftMouseClick ();
    23.     }
    24.     public void setSelected(GameObject toSet)
    25.     {
    26.         currentlySelected = toSet;
    27.         currentlySelected.GetComponent<TileMasterClass> ().OnSelect ();
    28.     }
    29.     public GameObject getSelected()
    30.     {
    31.         return currentlySelected;
    32.     }
    33.  
    34.     void clearSelected()
    35.     {
    36.         currentlySelected = null;
    37.     }
    38.  
    39.     void checkForLeftMouseClick()
    40.     {
    41.         if (Input.GetKeyDown (KeyCode.Mouse0)) {
    42.             Debug.Log ("Clicking, looking for raycast hits");
    43.             selectionRaycast ();
    44.         }
    45.     }
    46.  
    47.     void selectionRaycast()
    48.     {
    49.         Vector2 mousePos = new Vector2 (Camera.main.ScreenToWorldPoint (Input.mousePosition).x, Camera.main.ScreenToWorldPoint (Input.mousePosition).y);
    50.  
    51.         RaycastHit2D raycast = Physics2D.Raycast (mousePos, Vector2.up, 10000000f);
    52.         try{
    53.  
    54.             GameObject hitObject = raycast.collider.gameObject;
    55.             Debug.Log(hitObject.name);
    56.             setSelected(hitObject);
    57.             Debug.Log ("Hit...Something");
    58.  
    59.         }
    60.         catch{
    61.             Debug.Log ("No Valid Objects Selected");
    62.         }
    63.     }
    64.             void findAllSuperClassExamples()
    65.     {
    66.         objectsWithSuperClass = FindObjectsOfType<TileMasterClass> ();
    67.  
    68.     }
    69.  
    70. }
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Here's a quick link (which I'm pretty sure answers your question): https://sushanta1991.blogspot.ca/2015/01/raycast-in-unity2d-using-mouse-position.html

    That said, though, there is another option: Using the IPointerClickHandler interface, which is what I would suggest :)
    If you're not familiar with it (never used it on the UI, for example), add a Physics2d raycaster to your camera, and implement the IPointerClickHandler on your class/script. Add "using UnityEngine.EventSystems;" at the top of the script, too. Let the IDE help you add the method, and then fill in your code.
     
  3. ThisIsNotATest

    ThisIsNotATest

    Joined:
    Nov 18, 2017
    Posts:
    6
    Hmm. The raycast code in the link seems to be having the same problem as my original code (it fires but never hits).
    Can you explain how the IPointerClickHandler interface works?

    Thanks for replying.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Did you try the points I made in my my post about how to get it setup/working? :)
     
  5. ThisIsNotATest

    ThisIsNotATest

    Joined:
    Nov 18, 2017
    Posts:
    6
    I did what I thought you were telling me to do, but I probably put it in wrong.
    Here is the new code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.EventSystems;
    5. public class SelectionManager : MonoBehaviour, IPointerClickhandler {
    6.     public static SelectionManager me;
    7.     public Camera cam;
    8.     [SerializeField]
    9.     GameObject currentlySelected;
    10.  
    11.     [SerializeField]
    12.     TileMasterClass[] objectsWithSuperClass;
    13.  
    14.     void Awake () {
    15.         findAllSuperClassExamples();
    16.     }
    17.  
    18.     void Start () {
    19.  
    20.     }
    21.  
    22.     void Update () {
    23.         checkForLeftMouseClick ();
    24.     }
    25.     public void setSelected(GameObject toSet)
    26.     {
    27.         currentlySelected = toSet;
    28.         currentlySelected.GetComponent<TileMasterClass> ().OnSelect ();
    29.     }
    30.     public GameObject getSelected()
    31.     {
    32.         return currentlySelected;
    33.     }
    34.  
    35.     void clearSelected()
    36.     {
    37.         currentlySelected = null;
    38.     }
    39.  
    40.     void checkForLeftMouseClick()
    41.     {
    42.         if (Input.GetKeyDown (KeyCode.Mouse0)) {
    43.             Debug.Log ("Clicking, looking for raycast hits");
    44.             selectionRaycast ();
    45.         }
    46.     }
    47.  
    48.     void selectionRaycast()
    49.     {
    50.         Vector3 mousePos = Input.mousePosition;
    51.         mousePos.z = 10;
    52.  
    53.         Vector3 screenPos = cam.ScreenToWorldPoint(mousePos);
    54.  
    55.         RaycastHit2D hit = Physics2D.Raycast(screenPos,Vector2.zero);
    56.  
    57.         if (hit) {
    58.             Debug.Log ("Raycast Hit");
    59.             print (hit.collider.name);
    60.         }
    61.         else {
    62.             Debug.Log ("Raycast Missed");
    63.         }
    64.  
    65.     }
    66.        
    67.             void findAllSuperClassExamples()
    68.     {
    69.         objectsWithSuperClass = FindObjectsOfType<TileMasterClass> ();
    70.  
    71.     }
    72.  
    73. }
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay, you didn't implement the interface. I'm surprised you didn't get a warning/error about that?
    If you mouse-over the IPointerClickHandler at the top of the class in your IDE, there should be an "implement interface' popup or something like that :)
    So, let the IDE fill it in, and you can remove the mouse check in update.
    Just move your logic to the interface's method. Let me know if it works for you :)
     
  7. ThisIsNotATest

    ThisIsNotATest

    Joined:
    Nov 18, 2017
    Posts:
    6
    Hmm. When I mouse over the IPointerClickHandler it says: error CS0103: the names IPointerClickHandler does not exist in the current context.
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    hm, odd. Did you paste from your project to here when you posted your code? You missed the capital 'H' in handler?
     
  9. ThisIsNotATest

    ThisIsNotATest

    Joined:
    Nov 18, 2017
    Posts:
    6
    I fixed the H in handler, but mousing over it isn't giving me any sort of clickable popup. There is also a new error message that says, `SelectionManager' does not implement interface member `UnityEngine.EventSystems.IPointerClickHandler.OnPointerClick(UnityEngine.EventSystems.PointerEventData)'
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Right, that message means you have typed the name properly for the interface, at least.
    There is a popup of some sort. I somewhat forget what it's like in Mono, but in visual studio it literally pops up and offers to implement it for you (pretty sure it's similar in Mono).

    Anyways, you can also just type the darn thing manually. I believe the syntax is:
    Code (csharp):
    1.  
    2. public void OnPointerClick(PointerEventData data) {
    3.    print("Yay, click !");
    4.   }
    5.  
    Something like that.
     
  11. ThisIsNotATest

    ThisIsNotATest

    Joined:
    Nov 18, 2017
    Posts:
    6
    I was also trying to simplify the code to see if that fixed anything, and got it down to this
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SelectionManager : MonoBehaviour {
    6.  
    7.     public static SelectionManager me;
    8.  
    9.     [SerializeField]
    10.     GameObject currentlySelected;
    11.  
    12.     [SerializeField]
    13.     TileMasterClass[] objectsWithSuperClass;
    14.  
    15.     void Awake () {
    16.         findAllSuperClassExamples();
    17.     }
    18.  
    19.     void Start () {
    20.  
    21.     }
    22.  
    23.     void Update () {
    24.         checkForLeftMouseClick ();
    25.     }
    26.     public void setSelected(GameObject toSet)
    27.     {
    28.         currentlySelected = toSet;
    29.         currentlySelected.GetComponent<TileMasterClass> ().OnSelect ();
    30.     }
    31.     public GameObject getSelected()
    32.     {
    33.         return currentlySelected;
    34.     }
    35.  
    36.     void clearSelected()
    37.     {
    38.         currentlySelected = null;
    39.         Debug.Log ("Cleared Currently Selected");
    40.  
    41.     }
    42.  
    43.     void checkForLeftMouseClick()
    44.     {
    45.         if (Input.GetKeyDown (KeyCode.Mouse0)) {
    46.             Debug.Log ("Clicking, looking for raycast hits");
    47.             selectionRaycast ();
    48.         }
    49.     }
    50.  
    51.     void selectionRaycast()
    52.     {
    53.         Vector2 mousePos = new Vector2(Camera.main.ScreenToWorldPoint (Input.mousePosition).x,Camera.main.ScreenToWorldPoint (Input.mousePosition).y);
    54.  
    55.         RaycastHit2D raycast = Physics2D.Raycast (mousePos, Vector2.zero, 0f);
    56.  
    57.         try {
    58.             GameObject hitObject = raycast.collider.gameObject;
    59.             Debug.Log (hitObject.name);
    60.             setSelected(hitObject);
    61.         }
    62.         catch {
    63.             Debug.Log ("Raycast Missed");
    64.         }
    65.  
    66.     }
    67.  
    68.     void findAllSuperClassExamples()
    69.     {
    70.         objectsWithSuperClass = FindObjectsOfType<TileMasterClass> ();
    71.  
    72.     }
    73.  
    74. }
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Did you try what I posted, as well or no?