Disable/Enable VR from code using SteamVR 2.0.1 - c#

As the title says, I'm trying to enable/disable VR between different applications, and I need to do it as many times as I want.
I'm using Unity 2017.4 and SteamVR 2.0.1. I'm trying to do it with two different scenes of the same project (testing one in the editor, and launching the other as .exe).
This solution is not working, since apparently Actions and Poses are not handled correctly when VR is stopped with XRSettings.enabled = false.
Did anyone experienced the same behaviour?
I tried to find a workaround:
1) Disabling/enabling also Player and Hands
...
// ** ENABLE VR **
if (enable)
{
print("Enabling VR ...");
XRSettings.LoadDeviceByName("OpenVR");
yield return null;
print("Loaded device: " + XRSettings.loadedDeviceName);
XRSettings.enabled = enable;
EnablePlayerAndHands(true);
}
// ** DISABLE VR **
else
{
print("Disabling VR ...");
EnablePlayerAndHands(false);
XRSettings.LoadDeviceByName("");
yield return null;
print("Loaded device: " + XRSettings.loadedDeviceName);
XRSettings.enabled = false;
}
...
2) Added these lines in the SteamVR.cs file:
private void Dispose(bool disposing)
{
...
// added code
SteamVR_Input.initialized = false;
SteamVR_Behaviour.instance = null;
}
(In order to make it work, I had to add a public setter for the SteamVR_Behaviour.instance property).
3) In SteamVR_Behaviour, I added a check inside Update(), LateUpdate() and FixedUpdate():
if (_instance != null) ... // do update
These modifications won't fix the problems actually, because I still have some exceptions when I enable back VR, for example:
GetPoseActionData error (/actions/default/in/SkeletonLeftHand): InvalidHandle handle: 1152990670760182193
UnityEngine.Debug:LogError(Object)
Valve.VR.SteamVR_Action_Pose:UpdateValue(SteamVR_Input_Sources, Boolean) (at Assets/SteamVR/Input/SteamVR_Action_Pose.cs:96)
Valve.VR.SteamVR_Action_Skeleton:UpdateValue(SteamVR_Input_Sources, Boolean) (at Assets/SteamVR/Input/SteamVR_Action_Skeleton.cs:75)
Valve.VR.SteamVR_Input:UpdateSkeletonActions(SteamVR_Input_Sources, Boolean) (at Assets/SteamVR/Input/SteamVR_Input.cs:487)
Valve.VR.SteamVR_Input:UpdateSkeletonActions(Boolean) (at Assets/SteamVR/Input/SteamVR_Input.cs:462)
Valve.VR.SteamVR_Input:LateUpdate() (at Assets/SteamVR/Input/SteamVR_Input.cs:352)
Valve.VR.SteamVR_Behaviour:LateUpdate() (at Assets/SteamVR/Scripts/SteamVR_Behaviour.cs:224)
...but they are raised just a few times and then they stop. It could be due to some bad timing. Btw, I put an Interactable gameobject inside the empty scene just to test if I could still interact with it after disabling/enabling, and it seems that I can.
Still, I would expect some easier and cleaner method to achieve my goal. Am I missing something obvious or is it a bug from SteamVR newest version?
Thanks in advance for any help.

Please see this link for reference
https://docs.unity3d.com/ScriptReference/XR.XRSettings-enabled.html
Stopping a VR session is not supported in GearVR, not sure about SteamVR

Related

Oculus Go's controller not detected by OVRInput.IsControllerConnected()

I have a Unity game that runs on both Android Cardboard and Oculus Go. I'm trying to determine whether the Go's controller is connected.
I imported the Oculus integration package from the Unity asset store (though I'm not sure it's actually required... I've gotten the impression that Oculus support has been built into Unity since at least 2018.3, if not 2018.2 or earlier). I also deleted Cardboard and added Oculus as Virtual Reality SDKs in Player settings.
The following code executes in the Start() method that initializes most of my game:
void Start() {
// ...
if (OVRInput.IsControllerConnected(OVRInput.Controller.RTrackedRemote)) {
// do something visible
}
// ...
}
The problem is, OVRInput.IsControllerConnected(...) always returns false, and the code inside the block never executes.
Other things I've tried:
Moved the call to OVRInput.IsControllerConnected() from Start() to Update(), just in case it's an initialization-time issue. No success. Same result.
Instead of using OVRInput.Controller.RTrackedRemote as the argument, I tried the other objects... LTrackedRemote, Active, All, Gamepad, LTouch, RTouch, Remote, Touch, Touchpad, and None. All of them except '.None' returned false. '.None' returned true.
I set a breakpoint on the line calling OVRInput.IsControllerConnected() (after moving it to Update()), then called OVRInput.GetConnectedControllers() in VS2017's immediate window... it returned "None". Ditto for OVRInput.GetActiveController().
The game itself began as Android Cardboard. So far, the only major changes I've made to it are:
Importing the Oculus support library from Unity's Asset store.
In Player -> XR Settings, I deleted "Cardboard" and added "Oculus" as a VR SDK
In Build Settings, I changed the build method from 'Gradle' to 'Internal' (Gradle builds failed... I've seen posts from summer 2018 saying it's a Unity bug, but I'm not sure whether that's still current info... regardless, changing from Gradle to Internal made THAT error go away).
Most notably, I have NOT added any Oculus-specific prefabs, or changed/removed any of the GoogleVR-specific prefabs.
I know you tried moving IsControllerConnected to Update but did you try GetConnectedControllers in Update after a second? That's what did the trick for me. So in Update():
// initialize hand once after one second of start
if(!handInitialised){
initialWait += Time.deltaTime;
if(initialWait > 1f){
OVRInput.Controller c = OVRInput.GetConnectedControllers();
if(c == OVRInput.Controller.LTrackedRemote || c == OVRInput.Controller.LTouch){
//
}
//
handInitialised = true;
}
}

Unity:Time.timescale =0 not working

I am trying to display player tutorial when the user 1st starts the game using playerpref and want the game to be paused, the problem i am facing is that Time.timescale=0 is not pausing the game when placed inside start (tutorialCanvas gets displayed), but works when is called by a button(Pause button).
Following is the code I use
void Start()
{
if (PlayerPrefs.HasKey ("test4") ==false ) {
tutorialCanvas.SetActive (true);
Time.timeScale = 0;
}
}
Time.timeScale = 0 is really messed up for me so what i could recommend you is that if you just want to pause something like pausing a movement of a character then you can try it like this :
GameObject PlayerScript;
if(Input.GetKey(KeyCode.P)){
//lets disable the playermovement script only not the whole object
PlayerScript = GetComponent<PlayerMovement>().enabled = false;
}
I've been stucked there also so i made an alternative way. And you can also visit this one. If you want a free of that asset you can get it here
I had this issue recently, although it was only doing it on a build, and not in the editor. Changing timeScale to something like 0.0001f would fix it, but that wasn't a great solution. Creating an input settings asset (under Camera -> Player Input -> Open Input Settings) seemed to have fixed it for the builds.

Unity Start nog called on real build

I've made a dice app as a project to learn to work with unity (it was so good in my eyes that I put it on the google play store) but when I downloaded it from there, the Start function of at least 2 scripts isn't called and I have no idea whether the other Start functions are being called.
Here you can see 2 of the Start functions that aren't called
void Start()
{
light = light.GetComponent<Light>();
GetComponent<Button>().onClick.AddListener(TaskOnClick);
rawImage = GetComponent<RawImage>();
isLockMode = false;
rawImage.texture = getIconLock(isLockMode);
}
void Start()
{
Screen.fullScreen = false;
Dice.AddDie();
Input.gyro.enabled = true;
GlobalConfig.onShowShadowsChanged += onShadowsEnabledChange;
}
They work when I use Unity Remote on my smartphone and they also work when I just use unity without the remote...
the first script is attached to a UI element and the second script is attached to an empty GameObject called 'App'
It's also even more weird because they used to work but then I switched pc's (but used the same code).
I think something is wrong with the building itself
Found out the problem, the build was generating two files, an .apk and an other .odb or somethingl ike that (might be another extension). I had to untick 'split application binary' in the player settings

Unable to Dismiss the PreviewViewController when Using iOS ReplayKit with Unity 5.3.4 via Custom Plugin

I am attempting to use ReplayKit's native screen recording functionality along with my Unity app so that I can enjoy the benefits of native screen recording and sharing UI.
I have created a Unity plugin which calls my native code written in Objective-C(++) and everything seems to work fine up until it comes to dismissing the RPPreviewViewController.
So my record button in the Unity UI triggers the ReplayKit startRecordingWithMicrophoneEnabled:handler function and the stop button correctly calls the stopRecording function which returns the RPPreviewViewController instance to my handler.
In the RPPreviewViewController, the "Save" button correctly saves to the camera roll and the share button works as expected. But Tapping "Cancel" (or "Done" depending on the context) does nothing.
Here is the code in my stopRecordingWithHandler: function which deals with the RPPreviewViewController:
- (void) stopRecording {
[[RPScreenRecorder sharedRecorder] stopRecordingWithHandler:^(RPPreviewViewController *previewController,NSError *error){
if (previewController != nil) {
previewController.previewControllerDelegate = self;
[previewController willMoveToParentViewController:rootView];
[rootView addChildViewController:previewController];
previewController.view.frame = CGRectMake(0.0, 0.0, rootView.view.bounds.size.width, rootView.view.bounds.size.height);
[rootView.view addSubview:previewController.view];
self.presentedController = previewController;
} else {
NSString *msg = [NSString stringWithFormat:#"The screen recorder is unavailable:\n%#", [error localizedDescription]];
[self displayMessageDialog:msg];
}
}];
}
// Implementation of PreviewControllerDelegate protocol
- (void)previewControllerDidFinish:(RPPreviewViewController *)previewController {
[previewController willMoveToParentViewController:nil];
[previewController.view removeFromSuperview];
[previewController removeFromParentViewController];
self.presentedController = nil;
}
As you can see, I have implemented the protocol for RPPreviewViewControllerDelegate and attempt to dismiss the view on its is closed event but the delegate function is never being called.
I can't figure out what is wrong, is it something I've coded wrong or is there an intricacy when using with Unity?
I'm stuck so any pointers would be much appreciated!
UPDATE:
rootView is used in the above code so here is how I retrieved that reference in the the init function:
static UIViewController *rootView;
- (ReplayKitController*) init {
self = [super init];
if(self && rootView == nil) {
rootView = [[UIApplication sharedApplication] windows][0].rootViewController;
}
return self;
}
I finally sorted it after trying a few things but I believe the problem was how I was setting the previewControllerDelegate with
previewController.previewControllerDelegate = self;
And have since changed it to use
[previewController setPreviewControllerDelegate:self];
Which seems to work!
Thanks to all who checked out my question and I hope this helps someone out there!

Trouble stopping particle emission in unity

I am trying to only allow the particle system to emit particles when something is visible. The particle system knows when to start if a Boolean named avail is true. The code I thought would work for this is the following:
if (avail)
{
GetComponent<MeshRenderer>().enabled = true;
GetComponent<ParticleSystem>().enableEmission = true;
print("Mesh enabled");
}
However, this failed. I also tried:
if (avail)
{
GetComponent<MeshRenderer>().enabled = true;
GetComponent<ParticleSystem>().emission.enabled = true;
print("Mesh enabled");
}
However, this too failed. On every site I have searched in, these two "solutions" came up but they don't work for me. the first example said "this method of doing this is obsolete" and the second example says I can't set "emission.enabled" to a variable because it is a getter not a setter. Any help with figuring this out is extremely appreciated.
I don't have unity opened right now, but I think that
GetComponent<ParticleSystem>().Stop();
is what you need. You can restart the system using
GetComponent<ParticleSystem>().Play();
Also, if you do this often, you should consider keeping your particle system in a class variable.

Categories

Resources