[Solved] RayCast doesn't hit Object

Hey everyone,

I’m currently having a little problem with my project and RayCasts in particular. In general, I use the RayCast to select a variety of things, which can be summarised as HexTiles and InteractableObjects. The HexTiles make up my map and the InteractableObjects are all the things which then can be placed on the map. When either one of those objects is hit, it’s highlighted by changing its color to visualize to the user, what he currrently has selected. HexTiles will be colored red, InteractableObjects white.
Now, for most of the things, it all works perfectly fine. HexTiles are always hit and they always change their color. But out of all my InteractableObjects I’ve got so far, there are two, that won’t work. When I click one of those, instead of hitting and highlighting the InteractableObject, it hits and highlights the HexTile behind it. Here are some examples:

  1. a normal gras map, without any selections

  2. a gras map with a HexTile selected

  3. a gras map with a pine tree (InteractableObject) selected

  4. a sand map with a HexTile selected

  5. a sand map after trying to select the palm tree (InteractableObject)

As you see, it won’t select/highlight the palm tree even though I use the same code and stuff as I do to select the pine tree, which obviously works.
The code is pretty straight-forward and shouldn’t provide any problems:

 public class MouseManager : MonoBehaviour {

    CameraManager cameraMan;
    GameManager gameMan;

    // Use this for initialization
    void Start () {
        cameraMan = this.gameObject.GetComponent<CameraManager> ();
        gameMan = this.gameObject.GetComponent<GameManager> ();
    }

    // Update is called once per frame
    void Update () {

       [...]

        // MOUSE POINTER HOVER

        // Returns the type of GameObject we are mousing over
        Ray ray = Camera.main.ScreenPointToRay( Input.mousePosition );
        RaycastHit hitInfo;

        if( Physics.Raycast(ray, out hitInfo) ) {
            GameObject hitObject = hitInfo.collider.transform.parent.gameObject;

            // What kind of object are we over?
            if(hitObject.GetComponent<Hex>() != null) {
                // We are over a hex
                MouseOver_Hex(hitObject);
            } else if (hitObject.GetComponent<InteractableObject>() != null) {
                // We are over an InteractableObject
                MouseOver_Interactable (hitObject);
            }
        }
    }

// What happens when we click on a tile?
    private void MouseOver_Hex(GameObject hitObject) {
        // LEFT-CLICK
        // to deselect InteractableObjects and toggle tile-highlighting
        if(Input.GetMouseButtonDown(0)) {
            if (gameMan.HideCreationMenu ()) {
                return;
            }

            // If we have an InteractableObject selected, we simply deselect it
            if ( MapData.IsInteractableObjectSelected() ) {
                MapData.DeselectInteractableObject ();
                return;
            }

            // If we don't have anything selected, we toggle highlighting of the tile
            hitObject.GetComponent<Hex>().ToggleHighlighting();
        }

        // RIGHT-CLICK
        // for InteractableObject interaction
        else if(Input.GetMouseButtonDown(1)) {
            // Only do something, when the tile is not already occupied
            if (hitObject.GetComponent<Hex> ().occupied) {
                return;
            }

            // If we don't have anything selected, we open the menu to create an InteractableObject
            if (!MapData.IsInteractableObjectSelected()) {
                MapData.SetInteractionSpot (hitObject);
                gameMan.ShowCreationMenu ();

            // Otherwise we check what it is, that we have selected
            } else {
                GameObject selObj = MapData.GetSelectedInteractableObject ();
        
                // If it's a unit, we move it
                if (selObj.GetComponent<Unit> () != null) {
                    MapData.SetInteractionSpot (hitObject);
                    Unit selectedUnit = selObj.GetComponent<Unit> ();
                    selectedUnit.currentTile.GetComponent<Hex> ().occupied = false;
                    selectedUnit.currentTile = hitObject;
                    selectedUnit.destination = hitObject.transform.position + hitObject.GetComponent<Hex>().GetHeightOffset();
                    hitObject.GetComponent<Hex> ().occupied = true;
            
                // Anything else (loot, obstacle, ...) is simply deselected
                } else {
                    MapData.DeselectInteractableObject ();
                }
            }
        }
    }

    // What happens when we click on an InteractableObject?
    private void MouseOver_Interactable(GameObject hitObject){
        // LEFT-CLICK
        // to select and deselect the InteractableObject
        if(Input.GetMouseButtonDown(0)) {
            if (gameMan.HideCreationMenu ()) {
                return;
            }

            // If the clicked InteractableObject is the one we already selected, only deselect it
            bool sameInteractableObject = hitObject.GetComponent<InteractableObject> ().IsSelected ();
            MapData.DeselectInteractableObject ();

            if (sameInteractableObject) {
                return;
            }

            // Otherwise, after deselecting the former selected InteractableObject, we select the new one
            MapData.SelectInteractableObject (hitObject);
        }

        // RIGHT-CLICK
        // to change color
        else if(Input.GetMouseButtonDown(1)){
            // If a selected InteractableObject is right-clicked, it is deselected
            if (hitObject.GetComponent<InteractableObject> ().IsSelected ()) {
                MapData.DeselectInteractableObject ();
            }
            // If an unselected InteractableObject is right-clicked, its color is changed
            else {
                hitObject.GetComponent<InteractableObject> ().SwitchColor ();
            }
        }
    }
public static class MapData {

    private static GameObject selectedInteractableObject;
    private static GameObject creationSpot;

    [...]

    // Selects an InteractableObject and highlights it
    public static void SelectInteractableObject(GameObject gameObj){
        gameObj.GetComponent<InteractableObject> ().Select ();
        selectedInteractableObject = gameObj;
    }

    // Deselects the currently selected InteractableObject and changes its color back to standard
    public static void DeselectInteractableObject(){
        if (selectedInteractableObject != null) {
            selectedInteractableObject.GetComponent<InteractableObject> ().Deselect ();
            selectedInteractableObject = null;
        }
    }

    // Returns true, if an InteractableObject is currently selected. False otherwise
    public static bool IsInteractableObjectSelected(){
        return selectedInteractableObject != null;
    }

    // Returns the currently selected InteractableObject
    public static GameObject GetSelectedInteractableObject(){
        return selectedInteractableObject;
    }

    // Sets the location where to create an InteractableObject
    public static void SetInteractionSpot(GameObject newSpot){
        creationSpot = newSpot;
    }

    // Returns the location where to create an InteractableObject via a GameObject element
    public static GameObject GetInteractionSpot(){
        return creationSpot;
    }

}
public class Hex : MonoBehaviour {
    public bool occupied = false;

    Material standardMaterial;
    bool highlighted = false;

    [...]

    // Highlights and un-highlights the tile
    public void ToggleHighlighting(){
        MeshRenderer mr = this.GetComponentInChildren<MeshRenderer>();

        // If the hex tile is already highlighted, we change it back to normal
        if (highlighted) {
            mr.material = standardMaterial;
            highlighted = false;

        // Otherwise we highlight it
        } else {
            mr.material.color = MyColor.hexHighlightColor;
            highlighted = true;
        }
    }
}

All the InteractableObjects implement this code, with their own twist obviously

public abstract class InteractableObject : MonoBehaviour {

    public GameObject currentTile;
    public Color standardColor;

    protected bool selected = false;

    public abstract void SwitchColor ();

    public void SetColor(Color c){
        this.GetComponentInChildren<MeshRenderer> ().material.color = c;
    }

    public void ResetColor(){
        this.GetComponentInChildren<MeshRenderer> ().material.color = standardColor;
    }

    public void Select(){
        selected = true;
        SetColor (MyColor.interactableHighlightColor);
    }

    public void Deselect(){
        selected = false;
        SetColor (standardColor);
    }

    public bool IsSelected(){
        return selected;
    }

    public void Destroy(){
        Destroy (this.gameObject);
    }
}

So, I hope I provided enough code and examples. Does anybode know why the palm tree won’t be hit by the RayCast? Thank you in advance!

Can you select the palm tree by selecting the top of it instead of the trunk?

It could be that the ray is off by a little bit. Use Debug.DrawLine/DrawRay to draw the entire ray from ray.origin to hitInfo.point, and compare that with your tree collider to see if it’s actually hitting the tree’s geometry. A screenshot showing both the line and the tree’s collider would also be helpful

No, I couldn’t select the top of the palm tree either, but by now I was able to solve this by myself.
It seems, that after importing the different tree models, I immediatly ticked the checkbox “Generate Colliders” for the all the other trees in my project except for the two that didn’t work (the palm tree and a dead tree) - I must have missed those. Then I created all the different tree-Prefabs. The ones, where I had checked the checkbox, got a Mesh Collider. The other two did not get one, when creating the prefab, and still didn’t get it automatically after checking the “Generate Colliders” checkboxes afterwards, even after refreshing the prefabs and stuff. By now, I manually added the Mesh Colliders to the broken Prefabs, which solved the problem.

TL; DR I’m an idiot.

Jus did some stuff in the wrong order and it kept me busy for 3 days now… and after posting the problem online, I find the solution within a couple of hours. -_-

Well, thank you anyway for your reply and have a nice day!

P.S: Is there a way to mark this thread as solved?

I believe you can edit your first post to change the title of the thread.