1

I'm making a game where camera follows the player (isometric view - kind of) and the player is moving around underground rock cave. Sometimes the camera gets behind an obstacle (or inside a model for example) and to still have the player game object visible, I made this script:

public class ObstructionDetectorBehaviour : MonoBehaviour {
    public Transform TeamTransform;
    public Color TransparentColor;

    public void FixedUpdate() {
        var direction = (Camera.main.transform.position - TeamTransform.position).normalized;
        var hits = Physics.RaycastAll(TeamTransform.position, direction, 100);

        foreach (var hit in hits) {
            if (hit.collider.gameObject.layer != 8) {
                continue;
            }

            var renderer = hit.collider.gameObject.GetComponent<Renderer>();

            renderer.materials[0].shader = Shader.Find("Transparent/Diffuse");
            renderer.materials[0].color = TransparentColor;
        }
    }
}

As you can see it disables the visibility of models between the player and the main camera.

Now, as the player controls where his character is moving by clicking the mouse (scene is divided into tiles), I would also like to be able to know where (on which tile) he clicked, so I did this:

public class PlaneBehaviour : MonoBehaviour, IPointerDownHandler {
    public GameObject ClickSymbol;

    public void Start() {
        var physicsRaycaster = FindObjectOfType<PhysicsRaycaster>();

        if (physicsRaycaster == null) {
            Camera.main.gameObject.AddComponent<PhysicsRaycaster>();
        }
    }

    public void OnPointerDown(PointerEventData eventData) {
        var o = eventData.pointerCurrentRaycast.gameObject;
    }
}

There's a problem however, because the OnPointerDown method is not being invoked all the times it should be. Reason for that is the fact that my underground maze walls have box colliders attached and sometimes the EventSystem component shows me that the mouse is hovering over a rock (the wall) and not a tile - because the rock collider is partially covering the tile.

So what are my options here?

How to make object behind a collider clickable?

Programmer
  • 121,791
  • 22
  • 236
  • 328
Marek M.
  • 3,799
  • 9
  • 43
  • 93
  • *"I know that one would be to put all the walls on Ignore Raycast layer, but that would mean I don't have the means to detect objects between the player and the camera"* I don't get this statement. How does adding Ignore Raycast layer affect detecting objects between the player and the camera? – Programmer Jul 22 '17 at 10:10
  • Ah, sorry - I wrote that because I have all the wall elements on another layer (index 8 in this example) which I'm checking in the `ObstructionDetector` script. Please ignore that sentence. – Marek M. Jul 22 '17 at 10:16
  • Is there a way to tell `PhysicsRaycaster` to do raycasts only to objects placed on specific layer(s)? – Marek M. Jul 22 '17 at 10:19

1 Answers1

2

Sometimes, PhysicsRaycaster or Unity's EventSystem cannot detect clicks due to camera angle. I've ran into this problem but it can be reduced by using the Physics.Raycast class to do this.

If this is just another Object blocking the PhysicsRaycaster, you can use all those Objects you want to detect clicks on a layer called "Tile". You can then use PhysicsRaycaster.eventMask and bit-mask operation to make the PhysicsRaycaster detect clicks on this layer only.

PhysicsRaycaster raycast = Camera.main.GetComponent<PhysicsRaycaster>();
LayerMask layerMask = 1 << LayerMask.NameToLayer("Tile");
raycast.eventMask = layerMask;

The-same solution but with the Physics.Raycast class.

int tileLayerIndex = LayerMask.NameToLayer("Tile");
int layerMask = (1 << tileLayerIndex);

RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

if (Physics.Raycast(ray, out hit, 10, layerMask))
{
    //...
}

You can find more bit-mask operation for ray-casting on layers on my other post.

Basically, you can toggle which Objects to detect raycast on during runt-time with both these solution.

Programmer
  • 121,791
  • 22
  • 236
  • 328