PTCInc / vuforia-engine

Bug and feedback issue tracker for the Vuforia Engine SDK
https://developer.vuforia.com
19 stars 0 forks source link

[Unity-UWP] INVALID_TARGET_NAME after initializing #95

Closed Rombond closed 7 months ago

Rombond commented 7 months ago

Summarize the bug: Can't initialize after a deinit with an image target on an uwp app from Unity.

Observed problem To change webcam I have to Deinit() and Initialize():

public void cameraChange()
{
    if (!VuforiaApplication.Instance.IsInitialized) return;
    VuforiaApplication.Instance.Deinit();
    VuforiaConfiguration.Instance.WebCam.DeviceNameSetInEditor = camList.options[camList.value].text;
    VuforiaApplication.Instance.Initialize();
}

After the Initialize i have an "INVALID_TARGET_NAME" error and the choosen webcam stay in the previous states. It does it only on the exported version, if i'm in play mode no error.

Expected result Webcam changes and no error in logs

Reproducible steps Steps to reproduce the behavior:

  1. Open the image target example
  2. Make a script with this:
    private void Update()
    {
    if (Input.GetKeyDown(KeyCode.U))
    {
        if (!VuforiaApplication.Instance.IsInitialized) return;
        VuforiaApplication.Instance.Deinit();
        VuforiaApplication.Instance.Initialize();
    }
    }
  3. Export to UWP and install
  4. Run and press 'U'

Affected Vuforia Engine version: I tried 10.19.3 and 10.21.3

Affected platform:

Device or platform logs

Exception in callback: Failed to create ImageTargetObserver: INVALID_TARGET_NAME
> UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object)
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:LogFormat(LogType, String, Object[])
UnityEngine.Debug:LogErrorFormat(String, Object[]).
Vuforia.Internal.Utility.UnityLogger:LogError(String, Object[])
Vuforia.Internal.Utility.Log:Error(String, Object[])
Vuforia.Utility.ExtensionMethods.DelegateHelper:InvokeDelegate(Delegate, Object[])
Vuforia.Utility.ExtensionMethods.DelegateHelper:InvokeWithExceptionHandling(Action)
Vuforia.Internal.Core.Engine:OnStart()
Unity.VisualScripting.InstanceInvokerBase`1:CompileExpression(MethodCalExpression, ParameterExpression[])
Vuforia.Internal.Core.Engine:Start(Action)
Vuforia.Internal.Core.Engine:Start()
Vuforia.VuforiaBehaviour:VuforiaInitialized(VuforiaInitError)
System.Reflection.RuntimeMethodInfo:InternalInvoke(Object, Object[], Exception&)
System.Reflection.RuntimeMethodInfo:Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)
System.Reflection.MethodBase:Invoke(Object, Object[])
System.Delegate:DynamicInvoke(Object[])
Vuforia.Utility.ExtensionMethods.DelegateHelper:InvokeDelegate(Delegate, Object[])
Vuforia.Utility.ExtensionMethods.DelegateHelper:InvokeWithExceptionHandling(Action`1, T)
Vuforia.Internal.Core.Engine:InitOnCameraReady()
System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences()
Vuforia.Internal.ExternalCamera.NullExternalCamera:Init(Func`1)
Vuforia.Internal.Core.Engine:<Init>b__158_0()
Unity.VisualScripting.InstanceInvokerBase`1:CompileExpression(MethodCalExpression, ParameterExpression[])
Vuforia.Internal.Core.EnginePermissions:OnPermissionRequestFinished(Boolean)
System.Collections.Generic.EqualityComparer`1:get_Default()
Vuforia.Internal.Permissions.EmptyPermissionRequester:Request(IEnumerable`1)
Vuforia.Internal.Core.EnginePermissions:RequestPermissions()
Vuforia.Internal.Core.EnginePermissions:Request(Action)
Vuforia.Internal.Core.Engine.Init(String)
Vuforia.VuforiaApplication:InitEngine()
Vuforia.VuforiaApplication:Initialize()
VuforiaController:cameraChange()

Workaround I disable any other webcams than the one that I want to use.

ptc-pscheper commented 7 months ago

Hi there, the VuforiaConfiguration.Instance.WebCam.DeviceNameSetInEditor method is only expected to work in the editor and should not be used during runtime. I assume this causes the additional errors you experience and therefor close this ticket. Also note that targeting Windows PCs might cause additional issues and degraded performance as they are not specifically recommended in our recommended devices list.

Rombond commented 7 months ago

Like i said in the "Reproducible steps" even without VuforiaConfiguration.Instance.WebCam.DeviceNameSetInEditor the VuforiaApplication.Instance.Initialize() doesn't works as exepected.

How can i switch webcams during runtimes or before loading the scene if i have multiples plugged in USB-C into my Surface Pro 8 ?

ptc-epassaro commented 7 months ago

Hi @Rombond, some additional information about the Exception: the errors you're seeing are due to calling VuforiaApplication.Instance.Deinit() and VuforiaApplication.Instance.Initialize() in the same frame.

Vuforia destroys all the ObserverBehaviours when VuforiaApplication.Instance.Deinit() is called, but Unity by design doesn't actually destroy objects immediately. When VuforiaApplication.Instance.Initialize() is called in your code, Unity hasn't completely destroyed everything, so you get those exceptions.

To make sure that Vuforia is correctly deinitialized, you should wait one frame before using VuforiaApplication.Instance.Initialize():

private void Update()
{
    if (Input.GetKeyDown(KeyCode.U))
    {
        if (!VuforiaApplication.Instance.IsInitialized) return;

        StartCoroutine(ReinitVuforia());
    }
}

IEnumerator ReinitVuforia()
{
    VuforiaApplication.Instance.Deinit();
    yield return null;
    VuforiaApplication.Instance.Initialize();
}

Again, on Deinit Vuforia destroys all the ObserverBehaviours in the scene, so all the Observerbehaviours in your scene will not be recreated when Vuforia re-initializes and they will not detect or track. Our suggestion in this cases is to reload your scene completely after calling Deinit.

Regarding switching cameras at runtime, that is something that Vuforia does not support out-of-the-box. The only way to do this is to create a custom Driver for your camera. You can find some additional resources at these urls:

Note that, when using a custom Driver, you will have to use a different overload of the VuforiaApplication.Instance.Initialize() method: VuforiaApplication.Instance.Initialize(string, IntPtr)