Open PhiSel opened 4 years ago
I can confirm this investigation in terms of destroying Interactable which are still hovered in the moment of the Destroy() call. Tried also several things like disabling the collider and/or XRBaseInteractable before destroying the object with no look.
thx @PhiSel for reporting ;-)
I just exposed the UnregisterInteractable method in the XRInteractionManager.cs script. And then call it from my interactable OnDestroy
How did you go about exposing the internal method without it getting overwritten when closing/reopening the project?
I added the edited files to my version control. Everytime I open the project Unity removes my changes but I just discard the changes in version control.
You can get around the limitation with reflection although personally I think it's better to write a object pooler.
Reflection example (put it on the same object as the XRInteractionManager):
using UnityEngine.XR.Interaction.Toolkit;
using System.Reflection;
public class XRInteractionManagerExposed : MonoBehaviour
{
private static XRInteractionManagerExposed instance = null;
private XRInteractionManager manager = null;
private MethodInfo unregisterInteractable = null;
public static XRInteractionManagerExposed GetInstance()
{
return instance;
}
private void Start()
{
instance = this;
manager = this.GetComponent<XRInteractionManager>();
System.Type t = typeof(XRInteractionManager);
MethodInfo[] methods = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (MethodInfo mi in methods)
{
if (mi.Name == "UnregisterInteractable")
{
unregisterInteractable = mi;
break; //leave the loop
}
}
}
public void UnregisterInteractable(XRBaseInteractable interactable)
{
object[] args = new Object[] { interactable };
unregisterInteractable.Invoke(manager, args);
}
}
Here is something I tried and seems to be working so far:
GetComponent<XRGrabInteractable>().colliders.Clear();
Seems to unregister the collider with the interaction manager before the destruction of the gameobject
Also think XRGrabInteractable can be substituted with what ever XRBaseInteractable script you have, but I'm using grab.
@Peaceteddie I'm upgrading my project to XR 0.10.0 and it works. Cheers!
As @Peaceteddie said, adding gameObject.GetComponent<XRGrabInteractable>().colliders.Clear();
before the deletion of given GameObject works. Have not encountered any errors since.
Try this if you don't want to use Reflection, just create a newer script then replace the old one on Inpsector[Debug Mode], works for XRSocketInteractor too:
public class XRGrabInteractableEs : XRGrabInteractable
{
protected override void OnDestroy()
{
base.OnDestroy();
OnDisable();//Call UnregisterWithInteractionManager
}
...
}
Problem: When destroying an interactable object while the interactor is still inside the object, a MissingReferenceException is thrown:
Reproduction: Attach a XRGrabInteractable component and the following script to a GameObject:
After releasing the grab (selectExit), the object is destroyed but the exception is thrown.
Quickfix: In order to quickly fix this problem, one could change the following in XRBaseInteractable.cs: