Strange behavior with Raycast and Oculus Rift

I’ve been experiencing this strange “bug” it seems with my raycast in Unity using my Oculus Rift. So I’ve scripted a raycast, and used a Debug.DrawRay so I could visualize the ray and trouble shoot etc. I noticed that it would work for a while, and the ray would cast directly out the front of the camera shooting in a forward direction, but after a while ( perhaps, if I leave unity running for an hour or so, working on things on and off) the raycast would suddenly act almost as if it was no longer attached to the camera, but instead to the player controller rigid body. The ray would cast straight out from the rigid body, and I could look around with the oculus rift, and the ray wouldn’t follow the camera. Then, if I detach my script from the camera, then re-attach it, suddenly things are back to normal. This continues to happen, and seems to only happen after being in unity for a while. I made a video and posted it on youtube so you could see. This was after leaving unity running overnight. I came back in to find that the raycast had detached itself, so I fired up the recorder and showed how it was broken, then it gets fixed after removing and re-adding the component. Any ideas what I’ve done wrong or what I might do to fix it?

Thank you!!!

Hi this is super strange behaviour! Thanks for the detailed video. I’m going to attempt to reproduce this issue tonight.

-Will
Unity QA

1 Like

Thank you! And I’m glad that maybe there’s a chance I didn’t just do something stupid! :slight_smile:

did you have any luck re-creating this? I’ve now experienced this on a second computer. I brought my project home to work on, and it’s doing the same thing here on my home computer. Would there be anything I could give you to help you figure out what’s going on? It’s frustrating to have to re-add the script to get the raycast working correctly again since I have to map all the public gameobjects each time I do that.

I don’t see how physx is even slightly related to VR. They’re totally different things. Can you share your raycast script?

this seems to be related to the raycast emitting from the MainCamera which is being controlled by the oculus rift. That’s how this is VR related.

Here’s the piece of the script that is giving me trouble:

void Update () {
Vector3 forward = WalkingCamera.transform.forward;
Debug.DrawRay(WalkingCamera.transform.position, forward, Color.red);

Here’s the entire script:

using UnityEngine;
using System.Collections;

public class PlayerReach : MonoBehaviour {
AudioSource audio;
private bool AudioPlaying = false;
private float AudioPosition = 0.0f;
//public GameObject Radio_old;
public Material RadioBody;
public bool IsSitting = false;
private GameObject Player;
private GameObject Fireplace;
//public Camera SeatCamera;
public Camera WalkingCamera;
//public GameObject Spectre;
public GameObject DeadMarley;
public GameObject DeadMarleyLight;
private GameObject DeadMarley_go;
private GameObject DeadMarleyLight_go;
public Light RoomLight;
public Light MoonLight;
private float RoomLightMaxIntensity = .25f;
private float RoomLightMinIntensity = 0.0f;
private float MoonLightMaxIntensity = 0.25f;
private float MoonLightMinIntensity = 0.1f;
public GameObject FireLightObject;
public GameObject Fire;
public GameObject Sparks;
private bool SpectreExists = false;
public Material RadioBodyHighlight;
float RoomLightCurrentIntensity;
float MoonLightCurrentIntensity;
float FireEmitterSize;
bool SparksActive = true;
public RaycastHit hitInfo;
Animator SpectreAnimator;
private bool DeadMarleyExists = false;
public GameObject Stage;
public GameObject AChristmasCarolTitle;
public GameObject AChristmasCarolTitle2;
public GameObject AChristmasCarolTitle3;
public GameObject AChristmasCarolTitle4;

private void BringLightsDown()
{
if (SparksActive == true)
{
Sparks.SetActive(false);
SparksActive = false;
}

if (RoomLightCurrentIntensity > RoomLightMinIntensity)
{
RoomLight.GetComponent().intensity = RoomLightCurrentIntensity - .001f;

}

if (MoonLightCurrentIntensity > MoonLightMinIntensity)
{
MoonLight.GetComponent().intensity = MoonLightCurrentIntensity - .001f;

}
if (FireLightObject.GetComponent().IntensityMultiplier > .4f)
{
FireLightObject.GetComponent().IntensityMultiplier = FireLightObject.GetComponent().IntensityMultiplier - .01f;
if (FireEmitterSize > .06f)
{
Fire.GetComponent().startSize = Fire.GetComponent().startSize - .007f;
}

}
}

private void BringLightsUp()
{
if (SparksActive == false)
{
Sparks.SetActive(true);
SparksActive = true;
}

if (RoomLightCurrentIntensity < RoomLightMaxIntensity)
{
RoomLight.GetComponent().intensity = RoomLightCurrentIntensity + .001f;

}

if (MoonLightCurrentIntensity < MoonLightMaxIntensity)
{
MoonLight.GetComponent().intensity = MoonLightCurrentIntensity + .001f;

}
if (FireLightObject.GetComponent().IntensityMultiplier < 2.0f)
{
FireLightObject.GetComponent().IntensityMultiplier = FireLightObject.GetComponent().IntensityMultiplier + .01f;
if (FireEmitterSize < .74f)
{
Fire.GetComponent().startSize = Fire.GetComponent().startSize + .007f;
}

}
}

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
Vector3 forward = WalkingCamera.transform.forward;
Debug.DrawRay(WalkingCamera.transform.position, forward, Color.red);

RaycastHit hitInfo;
Ray MyRay = new Ray(transform.position, forward);

if(Physics.Raycast(transform.position, forward, out hitInfo, 2.0f))
{
//print("You can touch the " + hitInfo.collider.gameObject.name);

/*if (hitInfo.collider.gameObject.name == “Radio_old”)
{

Renderer rend = Radio_old.GetComponent();
rend.material.shader = Shader.Find(“RadioBody”);
rend.material.SetColor(“Color”, Color.yellow);

}
else
{
Renderer rend = Radio_old.GetComponent();
rend.material.shader = Shader.Find(“RadioBody”);
rend.material.SetColor(“Color”, Color.white);

}*/
if (hitInfo.collider.gameObject.name == “Radio_old”)
{
if (AudioPlaying == false)
{
GameObject.Find(“RadioText”).GetComponent().text = “Click to Play”;
}
else
{
GameObject.Find(“RadioText”).GetComponent().text = “Click to Pause”;
}
} else
{
GameObject.Find(“RadioText”).GetComponent().text = “”;
}

if (Input.GetMouseButtonDown(0))
{

if (hitInfo.collider.gameObject.name == “Radio_old”)
{
if (AudioPlaying == true)
{
audio = hitInfo.collider.gameObject.GetComponent();
audio.Pause();
AudioPosition = audio.time;
AudioPlaying = false;
//Debug.Log(audio.time);
}
else
{
audio = hitInfo.collider.gameObject.GetComponent();
audio.Play();

AudioPlaying = true;
//Debug.Log(“AudioPlaying =” + AudioPlaying);

}
}
}
}

//DreamSequence
if (AudioPlaying == true)
{
RoomLightCurrentIntensity = RoomLight.GetComponent().intensity;
MoonLightCurrentIntensity = MoonLight.GetComponent().intensity;
FireEmitterSize = Fire.GetComponent().startSize;

AudioPosition = audio.time;
//Debug.Log(RoomLightCurrentIntensity);

if (audio.time > 67 & audio.time < 78)
{
BringLightsDown();
}

if (audio.time > 120 & audio.time < 130)
{
BringLightsUp();
}

//ENTER Title!
if (audio.time > 34 && audio.time < 38)
//31
{

if (GameObject.Find(“A Christmas Carol Title(Clone)”) == null)
{
GameObject AChristmasCaorlTitle = Instantiate(AChristmasCarolTitle, new Vector3(0.0F, 0.0f, 0.0f), Quaternion.Euler(0f, 180f, 0f)) as GameObject;

}
}

//ENTER Title!
if (audio.time > 43 && audio.time < 48)
//31
{

if (GameObject.Find(“A Christmas Carol Title2(Clone)”) == null)
{
GameObject AChristmasCaorlTitle2 = Instantiate(AChristmasCarolTitle2, new Vector3(0.0f, 0.0f, 0.0f), Quaternion.Euler(0f, 180f, 0f)) as GameObject;

}
}

//ENTER Title!
if (audio.time > 52 && audio.time < 58)
//31
{

if (GameObject.Find(“A Christmas Carol Title3(Clone)”) == null)
{
GameObject AChristmasCaorlTitle3 = Instantiate(AChristmasCarolTitle3, new Vector3(0.0f, 0.0f, 0.0f), Quaternion.Euler(0f, 180f, 0f)) as GameObject;

}
}

//ENTER Title!
if (audio.time > 61 && audio.time < 68)
//31
{

if (GameObject.Find(“A Christmas Carol Title4(Clone)”) == null)
{
GameObject AChristmasCaorlTitle4 = Instantiate(AChristmasCarolTitle4, new Vector3(0.0f, 0.0f, 0.0f), Quaternion.Euler(0f, 180f, 0f)) as GameObject;

}
}

//ENTER Dead Marley!
if (DeadMarleyExists == false)
{
if (audio.time > 72 && audio.time < 84)
//74
{
DeadMarleyExists = true;
GameObject DeadMarley_go = Instantiate(DeadMarley, new Vector3(123.3f, -.14f, 271.0f), Quaternion.Euler(0f,0f,0f)) as GameObject;
GameObject DeadMarleyLight_go = Instantiate(DeadMarleyLight, new Vector3(121.914f, 3.816f, 269.461f), Quaternion.Euler(45.803f, 88.078f, -8.315f)) as GameObject;
DeadMarley_go.transform.parent = GameObject.Find(“Stage”).transform;
DeadMarleyLight_go.transform.parent = GameObject.Find(“Stage”).transform;
DeadMarley_go = GameObject.Find(“coffin_prefab(Clone)”);
DeadMarleyLight_go = GameObject.Find(“DeadmarleyLight(Clone)”);
DeadMarley_go.GetComponent().SetTrigger(“Coffin_Open”);

}
}
else
{
if (audio.time > 122)
//122
{

GameObject.Find(“coffin_prefab(Clone)”).GetComponent().SetTrigger(“Coffin_Sink”);
if (audio.time > 129)
{
Destroy(GameObject.Find(“Marley_Dead(Clone)”));
Destroy(GameObject.Find(“DeadmarleyLight(Clone)”));
DeadMarleyExists = false;
}

}
}
//ENTER THE SPECTRE!
/*if (SpectreExists == false)
{
if (audio.time > 78)
{
GameObject Spectre_go = Instantiate(Spectre, new Vector3(123.83f, 1.27f, 266.13f), Quaternion.identity) as GameObject;
Spectre_go.transform.parent = GameObject.Find(“Stage”).transform;
SpectreExists = true;
}
}

else

{

Vector3 SeatCamForward = SeatCamera.transform.forward;
//Debug.DrawRay(SeatCamera.transform.position, SeatCamForward, Color.green);
if (Physics.Raycast(transform.position, forward, out hitInfo, 10.0f))
{
if (hitInfo.collider.gameObject.name == “HouseWindows”)
{
if (audio.time > 10)
{
SpectreAnimator = GameObject.Find(“spectre_prefab(Clone)”).GetComponent();
int SpectreMoveHash = GameObject.Find(“spectre_prefab(Clone)”).GetComponent().SpectreMoveHash;
SpectreAnimator.SetTrigger(“WindowLook”);
}
}
} else if (Physics.Raycast(SeatCamera.transform.position, SeatCamForward, out hitInfo, 10.0f))
if (hitInfo.collider.gameObject.name == “HouseWindows”)
{
if (audio.time > 10)
{
SpectreAnimator = GameObject.Find(“spectre_prefab(Clone)”).GetComponent();
int SpectreMoveHash = GameObject.Find(“spectre_prefab(Clone)”).GetComponent().SpectreMoveHash;
SpectreAnimator.SetTrigger(“WindowLook”);
}
}

}*/

}

//Set Stage Visibility
if (IsSitting == false)
{
Renderer[ ] renderers = Stage.GetComponentsInChildren();

foreach (Renderer r in renderers)
{
r.enabled = false;
}

Light[ ] lights = Stage.GetComponentsInChildren();
foreach (Light l in lights)
{
l.enabled = false;
}

} else
{
Renderer[ ] renderers = Stage.GetComponentsInChildren();

foreach (Renderer r in renderers)
{
r.enabled = true;
}
Light[ ] lights = Stage.GetComponentsInChildren();
foreach (Light l in lights)
{
l.enabled = true;
}

}

// sit Down
if (Input.GetMouseButtonDown(0))
{
Player = GameObject.Find(“Player”);
Fireplace = GameObject.Find(“fireplace”);

if (IsSitting == false)
{

if (Physics.Raycast(transform.position, forward, out hitInfo, 2.0f))
{
if (hitInfo.collider.gameObject.name == “SofaChair”)
{
IsSitting = true;
//Debug.Log(“You’ve Pressed ‘e’”);
Player.gameObject.GetComponent().isKinematic = true;
//GetComponent().enabled = false;
Player.gameObject.transform.position = new Vector3(123.21f, 1.638f, 270.57f);
Player.transform.LookAt(Vector3.zero);

//WalkingCamera.enabled = false;
//SeatCamera.enabled = true;

}
}
}
else
{

IsSitting = false;
Player.gameObject.GetComponent().isKinematic = false;
//GetComponent().enabled = false;
Player.gameObject.transform.position = new Vector3(123.95f, 2.06f, 270.17f);
//WalkingCamera.enabled = true;
//SeatCamera.enabled = false;
}
}

}
}

all I can figure is that sometimes the ray gets drawn from the camera knowing that it is an oculus controlled camera, and then it works. Then sometimes the ray gets drawn from the camera somehow thinking it’s a normal, non VR controlled camera. Because the ray moves and pivots with the mouse, not with the rotation of the oculus rift. This is driving me nuts. There truly is no rhyme or reason. It’ll be working just fine, then one time I’ll hit the “play” button to preview the game and suddenly it’s not casting from the oculus rift anymore, but is moved by the mouse.

I did notice this morning that the ray in fact does originate from the transform of the main camera. I can see on the very first frame, the main camera is about .8 units above the transform of the “player” rigid body that the camera is attached to. But instantly the camera updates to the position it’s getting from the rift, so typically it drops down a few units and as the camera is being controlled by the rift. When the raycast is working, it drops down right along with the camera and is always updating it’s rotation and direction along with the camera. When the raycast is NOT working, it stays up there at the original .8 units above the “Player” transform, doesn’t follow along with the MainCamera, and instead I can move it around and change the angle of the raycast with mouse input.

I would really love some help figuring this out. Everytime the raycast decides to quit working on me, I have to detach my script from the MainCamera and re-attach it. Which makes me have to re-link all of the public GameObjects, and it’s becoming troublesome.

another note, when the raycast is broken, if I do a project build at that time, the build is also broken. So it builds into the game the broken raycast. If I build when the raycast is working properly, all is well.

Thanks for any help with this!

alright, I believe I’ve found what’s causing the problem, still don’t know how to “fix” it as it is, but at least I know where the problem is coming from. So, I’ve imported the default “RigidBodyFPSController” from the standard assets as my character and main camera. This comes with a default “RigidbodyFirstPersonController.cs” script attached to the parent RigidBody. There is something inside that script that seems to be causing an issue with my created script that I’ve attached to the MainCamera that is a child of the RigidBody. If I disable the “RigidbodyFirstPersonController” script, my raycast from my script works every time. I believe the only thing I’m using from the “RigidbodyFirstPersonController” script is the ability to move my character around, so perhaps the solution to this problem is for me to write my own movement script and just abandon the script that came as part of the standard asset prefab.

Unless someone here can easily identify why the script that comes with the RigidBodyFPSController standard asset would interfere with my own raycast script on the camera.

Thanks

Hi jtrim1,

Thanks for the report and follow-up, I briefly had a chance to play around with this issue last week and could not get it to reproduce. However, it seems like you have found the root cause of the problem in the FPS Rigidbody controller. Ideally, the standard assets should work with most if not all of Unity’s modules be it VR or mobile or whatever, so I will investigate this issue to see if it’s a problem in the VR module. My first instinct is that it’s not but I can’t be sure.

In the meantime, a custom FPS controller might be a good solution. Also, I’m pretty sure Oculus has a decent VRFPSController as a part of their Utils. (Or at least they used to) That could be a good lead as well.

Anyway, let us know how it goes.

Thanks,
Will
Unity QA