1

I am raycasting to detect collision with objects that are on the controllable layer. For some reason objects that are not on the controllable layer are also getting hit. Here is the code where I call the raycast.

if (Input.touches.Length > 0)
    {
        RaycastHit hit;
        if (Physics.Raycast(firstPersonCamera.ScreenPointToRay(Input.GetTouch(0).position), out hit, controllableLayer))
        {
            Debug.Log("Object hit");
            Debug.Log(hit.transform.gameObject.name);

            Touch touch = Input.GetTouch(0);

            GameObject objectHit = hit.transform.gameObject;

            if (dragging)
            {
                Vector3 cursorScreenPoint = new Vector3(touch.position.x, touch.position.y, screenPoint.z);
                Vector3 cursorPosition = firstPersonCamera.ScreenToWorldPoint(cursorScreenPoint) + offset;
                objectHit.transform.position = cursorPosition;
            }
            // Handle finger movements based on touch phase.
            switch (touch.phase)
            {
                // Record initial touch position.
                case TouchPhase.Began:
                    screenPoint = firstPersonCamera.WorldToScreenPoint(objectHit.transform.position);
                    offset = objectHit.transform.position - firstPersonCamera.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, screenPoint.z));
                    dragging = true;
                    break;

                // Determine direction by comparing the current touch position with the initial one.
                case TouchPhase.Moved:
                    break;

                // Report that a direction has been chosen when the finger is lifted.
                case TouchPhase.Ended:
                    dragging = false;
                    break;
            }
        }
        else
        {
            Debug.Log("Nothing hit");
        }
    }

Also here is where I declare the layermask

void Awake()
{
    firstPersonCamera = GameObject.Find("First Person Camera").GetComponent<Camera>();
    controllableLayer = LayerMask.NameToLayer("Controllable");
    Debug.Log(LayerMask.LayerToName(controllableLayer));
}
Enryu
  • 1,406
  • 1
  • 14
  • 26

1 Answers1

4

Because Layers use bit shifting, you have to do as follow when raycasting :

int layerMask = 1 << controllableLayer;
Physics.Raycast(firstPersonCamera.ScreenPointToRay(Input.GetTouch(0).position), out hit, layerMask)

Otherwise, declare controllableLayer as an integer and do as follow :

int controllableLayer ;

void Awake()
{
    controllableLayer = 1 << LayerMask.NameToLayer("Controllable");
}

void Update()
{
    // ...
    if( Physics.Raycast(firstPersonCamera.ScreenPointToRay(Input.GetTouch(0).position), out hit, controllableLayer) )
    {
        // ...
    }
}

Check these links :

  1. https://answers.unity.com/questions/472886/use-layer-name-for-layermask-instead-of-layer-numb.html
  2. https://gamedev.stackexchange.com/questions/132132/why-do-unity-layer-masks-need-to-use-bit-shifting
Hellium
  • 7,206
  • 2
  • 19
  • 49
  • So I still need to have this in awake also? controllableLayer = LayerMask.NameToLayer("Controllable"); – Enryu Nov 16 '17 at 16:21
  • Yes, or you could declare `controllableLayer` as an `int` and assign its value as follow in `Awake` : `controllableLayer = 1 << LayerMask.NameToLayer("Controllable");` Then, when calling `Raycast`, keep what you had : `Physics.Raycast(firstPersonCamera.ScreenPointToRay(Input.GetTouch(0).position), out hit, controllableLayer)` (Check my updated answer) – Hellium Nov 16 '17 at 16:23
  • Apparently I was actually doing 2 things wrong. I was not doing the bitshift like you said, but I was also using the incorrect constructor. The constructor I was using was treating the layermask as the max distance argument. I fixed it now, thanks for your help. – Enryu Nov 16 '17 at 16:37