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:
-
a normal gras map, without any selections
-
a gras map with a HexTile selected
-
a gras map with a pine tree (InteractableObject) selected
-
a sand map with a HexTile selected
-
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!