Using Raycast and Layermask to teleport player in VR, but the Raycast teleport initiates through objects of a different layer
Hey there,
I've been trying my luck at VR game developing and have a few ideas in mind for which I'm currently devising a phone hardware stresstest to see what phones really are made of and what they can handle.
I own a thirdparty barebones cardboard contraption without the magnet button, so my main (and ONLY) method for user input is a tap on the screen. This can be a limiting factor, since I intend to be able to move around my demo level via teleportation and shoot a prefab cannonball projectile at enemies. With only one input method, I'm in a bit of a pickle here. My plan of action was to have the players touch input be interpreted either as a teleportation command if the player is looking at the floor defined as a teleportation layer for raycasting or as a fire projectile command, if the player is not looking at the floor, or is looking at an object in another layer.
My puny attempt so far works pretty well on the surface (except for Input.touchCount == 1 being executed every frame and things going wonky because of it but I'll try fix that myself) but what I've found is that the raycast will ignore objects like walls or scenery in another layer and teleport you through them, even though GazePoint() should be returning null because the raycast doesn't hit the defined teleportLayer. Yet, if your gaze point in VR space happens to hit the floor behind the object, it will initiate the teleport when it should fire a projectile instead, so every head tilt below flat horizontal will initiate a teleport, even when when standing square infront of another object.
I've tried to implement a fix for this for days so I wouldn't have to bother anyone with what I'm fearing might be a trivial matter of me not understanding the basics of raycasting but I've given up and I'd be very thankful for a nudge in the right direction!
public class TeleportTo : MonoBehaviour
{
private RaycastHit lastRaycastHit;
public LayerMask teleportLayer;
GameObject prefab;
void Start()
{
Cursor.visible = false;
prefab = Resources.Load("cannonball") as GameObject;
}
private GameObject GazePoint()
{
Vector3 origin = transform.position;
Vector3 direction = Camera.main.transform.forward;
float range = 200;
if (Physics.Raycast(origin, direction, out lastRaycastHit, range, teleportLayer.value))
return lastRaycastHit.collider.gameObject;
else
return null;
}
private void TeleportToGaze()
{
transform.position = lastRaycastHit.point + lastRaycastHit.normal * 2;
}
void Update()
{
if (Input.touchCount == 1 && GazePoint () == null)
{ // This is basically fire projectile, so it can be ignored
// GameObject cannonball = Instantiate(prefab) as GameObject;
// cannonball.transform.position = transform.position + Camera.main.transform.forward * 3;
// Rigidbody rb = cannonball.GetComponent<Rigidbody>();
// rb.velocity = Camera.main.transform.forward * 500;
}
if (Input.touchCount == 1 && GazePoint () != null)
{
TeleportToGaze();
}
}
}