Unity trying to load wrong namespace when building for WSA - unity3d

I have two DLLs with their PDB files loaded into my Unity project. One targets the editor in the "Select platforms for plugin" inspector and is in the folder Assets/Plugins. The other targets WSAPlayer, has UWP selected for the SDK and DotNet for the scripting backend. It is in the folder Assets/Plugins/WSA.
When I attempt to build for Windows Store (SDK: Universal 10, Target device: PC, UWP Build Type: XAML, UWP SDK: Latest installed, and Build and run on: Local Machine) I get the following errors:
Assets\CubeScript.cs(16,48): error CS0246: The type or namespace name 'Win32HidDevice' could not be found (are you missing a using directive or an assembly reference?)
Error building Player because scripts had compiler errors
I would not expect UWP to be able to load Win32HidDevice, nor does my UWP DLL use it, so it must be coming from the other DLL. The app works fine debugging in the editor, and if I also check "Standalone" on the first DLL then I can build and run a standalone app.
What settings do I need to get Unity to ignore the Win32 DLL and use the UWP one when building for WSA?
I do not think it is the script itself, but for completeness here it is:
using UnityEngine;
using Zanzibar;
public class OrbScript : MonoBehaviour
{
public Mat mat;
void Start ()
{
MatManager.Instance.MatConnected += MatConnected;
MatManager.Instance.MatDisconnected += MatDisconnected;
MatManager.Instance.Initialize(Communication.AllSupported);
}
private void MatConnected(Mat mat)
{
Debug.LogFormat("Mat {0}", mat.UniqueName);
this.mat = mat;
}
private void MatDisconnected(Mat mat)
{
this.mat = null;
}
void Update ()
{
if (mat == null)
{
GetComponent<Renderer>().material.color = Color.black;
}
else if (mat.TaggedObjects.Count > 0)
{
GetComponent<Renderer>().material.color = Color.green;
}
else if (mat.Touches.Count > 0)
{
GetComponent<Renderer>().material.color = Color.magenta;
}
else
{
GetComponent<Renderer>().material.color = Color.white;
}
}
}

#Tautvydas-Zilys spotted my problem over on the Unity forums here. I'd been looking in the wrong script, doh! CubeScript.cs contained this line:
var currentMat = orb.mat.Device as Win32HidDevice;
which I needed to replace with these lines:
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
var currentMat = orb.mat.Device as Win32HidDevice;
#elif UNITY_WSA_10_0
var currentMat = orb.mat.Device as UwpDevice;
#endif

Related

Is there a way to automatically disable normal maps for mobile builds in Unity?

I'm trying to build a Unity game for mobile, and I want to know if there is a way to remove normal maps from all materials (Standard shader, built in pipeline) when building for mobile platforms without removing them from other platforms. Using Unity 2021 LTS. I already looked through the Project Settings, and it doesn't seem like there is an easy way to do this.
I ended up finding a solution to my own problem, so I'll post it here just in case anyone else needs it.
Create a file called NormalMapPreprocess.cs with this code, and put it in the Assets/Editor folder, and it will remove the normal maps at build time.
using System.Collections.Generic;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;
#if UNITY_ANDROID
public class NormalMapPreprocess : IPreprocessShaders
{
ShaderKeyword m_KeywordNormal;
public NormalMapPreprocess()
{
m_KeywordNormal = new ShaderKeyword("_NORMALMAP");
}
public int callbackOrder { get { return 0; } }
public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data)
{
for (int i = data.Count - 1; i >= 0; --i)
{
if (data[i].shaderKeywordSet.IsEnabled(m_KeywordNormal))
{
data.RemoveAt(i);
}
}
}
}
#else
public class NormalMapPreprocess {}
#endif
Not sure if this is the best solution, but at least it works.

LocatableCamera (PhotoCapture) on the Hololens 2

I have 2 issues when using PhotoCapture on the Hololens 2, which are probably connected. They did not occur on the Hololens 1.
The only obtainable resolution is 3904x2196
Getting the CameraToWorldMatrix always fails
As can be seen in the docs, this resolution has no framerate associated with it.
My presumption is that the CameraToWorldMatrix is only obtainable for camera profiles with a lower resolution.
How can i change the resolution and get the matrix within Unity?
Minimal Reproducible Example
I am using Unity 2019.2.19f1 and Visual Studio 2019 Community (16.4.5)
Create a new Unity Project following the steps here, except using IL2CPP as the scripting backend instead of .NET
In Player Settings: Capabilities enable InternetClient, InternetClientServer, PrivateNetworkClientServer, Webcam, Microphone and SpatialPerception, in Player Settings: Supported Device Families select Holographic
Create a new empty gameobject and add the following script:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Windows.WebCam;
public class PhotoCaptureController : MonoBehaviour
{
PhotoCapture photoCaptureObject = null;
bool isRunning = false;
void Start()
{
StartCoroutine(StartCameraCapture());
}
private IEnumerator StartCameraCapture()
{
if (!Application.HasUserAuthorization(UserAuthorization.WebCam))
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
}
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
Debug.Log("Creating PhotoCapture");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
else
{
Debug.Log("Webcam Permission not granted");
}
}
private void Update()
{
if (isRunning)
{
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
}
void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
photoCaptureObject = captureObject;
IEnumerable<Resolution> availableResolutions = PhotoCapture.SupportedResolutions;
foreach (var res in availableResolutions)
{
Debug.Log("PhotoCapture Resolution: " + res.width + "x" + res.height);
}
Resolution cameraResolution = availableResolutions.OrderByDescending((res) => res.width * res.height).First();
CameraParameters c = new CameraParameters();
c.hologramOpacity = 0.0f;
c.cameraResolutionWidth = cameraResolution.width;
c.cameraResolutionHeight = cameraResolution.height;
c.pixelFormat = CapturePixelFormat.BGRA32;
captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
}
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
isRunning = true;
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
}
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame frame)
{
if (result.success)
{
if (frame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix))
{
Debug.Log("Successfully obtained CameraToWorldMatrix: " + cameraToWorldMatrix.ToString());
}
else
{
Debug.Log("Failed to obtain CameraToWorldMatrix");
}
}
frame.Dispose();
}
}
Change Build Settings:
Build, open VS solution, set build target to ARM64, Debug and deploy to Device
This CameraCapture plugin may work for you. It's a native plugin for Unity. The readme.txt contains information on building it. Basically, you need to build the native plugin variants before trying to open up the Unity sample. If you haven’t built C++/WinRT components, you may need to go through the setup steps here. The SpatialCameraTracker.cs file shows how to receive the camera matrices.
There is minimal support on this but all the code is in the repo

How to use JNI in Unity

I have a JAR library that i need to use in a Unity project but i have never used JAR before,
i couldn't get JNI to work correctly
here is a simple code which outputs 0 but probably should return the correct hashcode of the java string??
public class test : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
AndroidJNIHelper.debug = true;
using (AndroidJavaObject jc = new
AndroidJavaObject("java.lang.String","test"))
{
int a = jc.CallStatic<int>("hashCode");
Debug.Log(a);
}
}
}
Problem was that i was using the editor after moving to android it worked perfectly .

Game Freezes While Switching Between VR and Normal (standalone) Mode [duplicate]

How can I set the display to stereoscopic programmatically in Unity for an app deployed to an Android device?
I want a UI menu where the user can toggle between "VR mode" and normal mode. I do not want VR mode by default as it should be an option at run-time. I know there is a setting for "Virtual Reality Supported" in the build settings, but again, I do not want this enabled by default.
Include using UnityEngine.XR; at the top.
Call XRSettings.LoadDeviceByName("") with empty string followed by XRSettings.enabled = false; to disable VR in the start function to disable VR.
When you want to enable it later on, call XRSettings.LoadDeviceByName("daydream") with the VR name followed by XRSettings.enabled = true;.
You should wait for a frame between each function call. That requires this to be done a corutine function.
Also, On some VR devices, you must go to Edit->Project Settings->Player and make sure that Virtual Reality Supported check-box is checked(true) before this will work. Then you can disable it in the Start function and enable it whenever you want.
EDIT:
This is known to work on some VR devices and not all VR devices. Although, it should work on Daydream VR. Complete code sample:
IEnumerator LoadDevice(string newDevice, bool enable)
{
XRSettings.LoadDeviceByName(newDevice);
yield return null;
XRSettings.enabled = enable;
}
void EnableVR()
{
StartCoroutine(LoadDevice("daydream", true));
}
void DisableVR()
{
StartCoroutine(LoadDevice("", false));
}
Call EnableVR() to enable vr and DisableVR() to disable it. If you are using anything other than daydream, pass the name of that VR device to the LoadDevice function in the EnableVR() function.
For newer builds of Unity (e.g. 2019.4.0f1) you can use the XR Plugin Management package.
To enable call:
XRGeneralSettings.Instance.Manager.InitializeLoader();
To disable call:
XRGeneralSettings.Instance.Manager.DeinitializeLoader();
I'm using Unity 2021 but this probably works in earlier versions, I'm also using XR Plug-in Management.
Start:
XRGeneralSettings.Instance.Manager.StartSubsystems();
Stop:
XRGeneralSettings.Instance.Manager.StopSubsystems();
Full documentation at:
https://docs.unity3d.com/Packages/com.unity.xr.management#4.0/manual/EndUser.html
2020.3.14f1
Doesn't work for me, I get this error when running my Android app.
Call to DeinitializeLoader without an initialized manager.Please make
sure wait for initialization to complete before calling this API.
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
static void TryToDeinitializeOculusLoader()
{
XRGeneralSettings.Instance.Manager.DeinitializeLoader();
}
More context.
I try to unload the Oculus loader, before he manages to load the plugin.
I have an Android app, and the Oculus loader calls Application.Quit because the device is not an Oculus headset.
Waiting for XRGeneralSettings.Instance.Manager.isInitializationComplete takes too long.
Tried all RuntimeInitializeLoadType annotations.
OculusLoader.cs
#elif (UNITY_ANDROID && !UNITY_EDITOR)
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
static void RuntimeLoadOVRPlugin()
{
var supported = IsDeviceSupported();
if (supported == DeviceSupportedResult.ExitApplication)
{
Debug.LogError("\n\nExiting application:\n\nThis .apk was built with the Oculus XR Plugin loader enabled, but is attempting to run on a non-Oculus device.\nTo build for general Android devices, please disable the Oculus XR Plugin before building the Android player.\n\n\n");
Application.Quit();
}
if (supported != DeviceSupportedResult.Supported)
return;
try
{
if (!NativeMethods.LoadOVRPlugin(""))
Debug.LogError("Failed to load libOVRPlugin.so");
}
catch
{
// handle Android standalone build with Oculus XR Plugin installed but disabled in loader list.
}
}
#endif
SOLUTION
Made my build class extend IPreprocessBuildWithReport
public void OnPreprocessBuild(BuildReport report)
{
DisableXRLoaders(report);
}
///https://docs.unity3d.com/Packages/com.unity.xr.management#3.2/manual/EndUser.html
/// Do this as a setup step before you start a build, because the first thing that XR Plug-in Manager does at build time
/// is to serialize the loader list to the build target.
void DisableXRLoaders(BuildReport report)
{
XRGeneralSettingsPerBuildTarget buildTargetSettings;
EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out buildTargetSettings);
if (buildTargetSettings == null)
{
return;
}
XRGeneralSettings settings = buildTargetSettings.SettingsForBuildTarget(report.summary.platformGroup);
if (settings == null)
{
return;
}
XRManagerSettings loaderManager = settings.AssignedSettings;
if (loaderManager == null)
{
return;
}
var loaders = loaderManager.activeLoaders;
// If there are no loaders present in the current manager instance, then the settings will not be included in the current build.
if (loaders.Count == 0)
{
return;
}
var loadersForRemoval = new List<XRLoader>();
loadersForRemoval.AddRange(loaders);
foreach (var loader in loadersForRemoval)
{
loaderManager.TryRemoveLoader(loader);
}
}
public void Awake() {
StartCoroutine(SwitchToVR(()=>{
Debug.Log("Switched to VR Mode");
}));
//For disable VR Mode
XRSettings.enabled = false;
}
IEnumerator SwitchToVR(Action callback) {
// Device names are lowercase, as returned by `XRSettings.supportedDevices`.
// Google original, makes you specify
// string desiredDevice = "daydream"; // Or "cardboard".
// XRSettings.LoadDeviceByName(desiredDevice);
// this is slightly better;
string[] Devices = new string[] { "daydream", "cardboard" };
XRSettings.LoadDeviceByName(Devices);
// Must wait one frame after calling `XRSettings.LoadDeviceByName()`.
yield return null;
// Now it's ok to enable VR mode.
XRSettings.enabled = true;
callback.Invoke();
}

Switch VR mode while moving to next scene in Daydream [duplicate]

How can I set the display to stereoscopic programmatically in Unity for an app deployed to an Android device?
I want a UI menu where the user can toggle between "VR mode" and normal mode. I do not want VR mode by default as it should be an option at run-time. I know there is a setting for "Virtual Reality Supported" in the build settings, but again, I do not want this enabled by default.
Include using UnityEngine.XR; at the top.
Call XRSettings.LoadDeviceByName("") with empty string followed by XRSettings.enabled = false; to disable VR in the start function to disable VR.
When you want to enable it later on, call XRSettings.LoadDeviceByName("daydream") with the VR name followed by XRSettings.enabled = true;.
You should wait for a frame between each function call. That requires this to be done a corutine function.
Also, On some VR devices, you must go to Edit->Project Settings->Player and make sure that Virtual Reality Supported check-box is checked(true) before this will work. Then you can disable it in the Start function and enable it whenever you want.
EDIT:
This is known to work on some VR devices and not all VR devices. Although, it should work on Daydream VR. Complete code sample:
IEnumerator LoadDevice(string newDevice, bool enable)
{
XRSettings.LoadDeviceByName(newDevice);
yield return null;
XRSettings.enabled = enable;
}
void EnableVR()
{
StartCoroutine(LoadDevice("daydream", true));
}
void DisableVR()
{
StartCoroutine(LoadDevice("", false));
}
Call EnableVR() to enable vr and DisableVR() to disable it. If you are using anything other than daydream, pass the name of that VR device to the LoadDevice function in the EnableVR() function.
For newer builds of Unity (e.g. 2019.4.0f1) you can use the XR Plugin Management package.
To enable call:
XRGeneralSettings.Instance.Manager.InitializeLoader();
To disable call:
XRGeneralSettings.Instance.Manager.DeinitializeLoader();
I'm using Unity 2021 but this probably works in earlier versions, I'm also using XR Plug-in Management.
Start:
XRGeneralSettings.Instance.Manager.StartSubsystems();
Stop:
XRGeneralSettings.Instance.Manager.StopSubsystems();
Full documentation at:
https://docs.unity3d.com/Packages/com.unity.xr.management#4.0/manual/EndUser.html
2020.3.14f1
Doesn't work for me, I get this error when running my Android app.
Call to DeinitializeLoader without an initialized manager.Please make
sure wait for initialization to complete before calling this API.
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
static void TryToDeinitializeOculusLoader()
{
XRGeneralSettings.Instance.Manager.DeinitializeLoader();
}
More context.
I try to unload the Oculus loader, before he manages to load the plugin.
I have an Android app, and the Oculus loader calls Application.Quit because the device is not an Oculus headset.
Waiting for XRGeneralSettings.Instance.Manager.isInitializationComplete takes too long.
Tried all RuntimeInitializeLoadType annotations.
OculusLoader.cs
#elif (UNITY_ANDROID && !UNITY_EDITOR)
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
static void RuntimeLoadOVRPlugin()
{
var supported = IsDeviceSupported();
if (supported == DeviceSupportedResult.ExitApplication)
{
Debug.LogError("\n\nExiting application:\n\nThis .apk was built with the Oculus XR Plugin loader enabled, but is attempting to run on a non-Oculus device.\nTo build for general Android devices, please disable the Oculus XR Plugin before building the Android player.\n\n\n");
Application.Quit();
}
if (supported != DeviceSupportedResult.Supported)
return;
try
{
if (!NativeMethods.LoadOVRPlugin(""))
Debug.LogError("Failed to load libOVRPlugin.so");
}
catch
{
// handle Android standalone build with Oculus XR Plugin installed but disabled in loader list.
}
}
#endif
SOLUTION
Made my build class extend IPreprocessBuildWithReport
public void OnPreprocessBuild(BuildReport report)
{
DisableXRLoaders(report);
}
///https://docs.unity3d.com/Packages/com.unity.xr.management#3.2/manual/EndUser.html
/// Do this as a setup step before you start a build, because the first thing that XR Plug-in Manager does at build time
/// is to serialize the loader list to the build target.
void DisableXRLoaders(BuildReport report)
{
XRGeneralSettingsPerBuildTarget buildTargetSettings;
EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out buildTargetSettings);
if (buildTargetSettings == null)
{
return;
}
XRGeneralSettings settings = buildTargetSettings.SettingsForBuildTarget(report.summary.platformGroup);
if (settings == null)
{
return;
}
XRManagerSettings loaderManager = settings.AssignedSettings;
if (loaderManager == null)
{
return;
}
var loaders = loaderManager.activeLoaders;
// If there are no loaders present in the current manager instance, then the settings will not be included in the current build.
if (loaders.Count == 0)
{
return;
}
var loadersForRemoval = new List<XRLoader>();
loadersForRemoval.AddRange(loaders);
foreach (var loader in loadersForRemoval)
{
loaderManager.TryRemoveLoader(loader);
}
}
public void Awake() {
StartCoroutine(SwitchToVR(()=>{
Debug.Log("Switched to VR Mode");
}));
//For disable VR Mode
XRSettings.enabled = false;
}
IEnumerator SwitchToVR(Action callback) {
// Device names are lowercase, as returned by `XRSettings.supportedDevices`.
// Google original, makes you specify
// string desiredDevice = "daydream"; // Or "cardboard".
// XRSettings.LoadDeviceByName(desiredDevice);
// this is slightly better;
string[] Devices = new string[] { "daydream", "cardboard" };
XRSettings.LoadDeviceByName(Devices);
// Must wait one frame after calling `XRSettings.LoadDeviceByName()`.
yield return null;
// Now it's ok to enable VR mode.
XRSettings.enabled = true;
callback.Invoke();
}