If you're using anything beyond [1.0.0-pre.3] - 2021-03-18, XR Toolkit will now automatically show Serialized Fields. So, no need for the custom Inspector!
Exactly what I needed. Please keep this way of explaining what you do. I usually have a hard time to follow your professionalism and high-math but this time I really had no problems and I learned something instead of doing copy-paste with your videos.
Big fan of you keeping it simple on the scope of the video, but then in the video getting pretty in depth. I.e. talking about overriding functions and calling the base function and why that's necessary, and then covering the editor GUI. For me, at least, those little pieces of nuance are extremely valuable; arguably more so than just for creating a tag check for XRSocketInteractor, but just learning Unity in practical ways. For someone who is a pro at Unity/C# perhaps they may feel it's a waste of time for you explaining those things, but they can fast forward through that to see the final code, whereas if you didn't cover that stuff to appeal to that audience then the more noob audience would be missing out, so I think it's a win-win when you do that. Or, a win-draw if that makes sense
Thanks, Shawn! Yeah, that was more/less my thinking. Which is why it's pretty lucky that it made it into a vid. I would've just put the project on Patreon and called it a day. I'm hoping there are more use-cases like this so I make a video like this once a month. I do enjoy having a video that isn't just a massive project.
Awesome! I Would love some more XR inreraction toolkit tutorials on overriding functions. It's the one thing that's like higher mathematics for me. Great explenations.
This was fantastic. Got it to work right away. What if I wanted to only allow the socket to accept items that are held by the player's xrcontroller? For example, I have set the socket to follow just ahead and below the camera as a sort of pouch, however it hoovers up any grabbable that comes into proximity. Would I set each item's tag to "socketable" on select and then remove the tag when select ends?
You'd want to add some functionality within the "CanSelect" function. Something like, "return interactable.isSelected", however, I'm not super sure how well this will work. But, it will get you started on prevent the Socket from just picking up any Interactable by accident.
I am trying to outline the object that is about to be grabbed. I am adding an outline to OnHoverEntered, the problem I'm running into is if multiple objects are in the collider, it will outline all of them. How do I know which object is the one that is going to be grabbed and isolate the hover outline to just that object? Thanks Andrew.
You may need to use a Highlight Nearest functionality. There's a measurer within the Interactor to find the nearest Interactable. I'd start with the logic of, whenever there is a Hover Enter/Exit, find the nearest Interactable and add the outline.
@@VRwithAndrew I did it!! Thank you for the guidance, a problem I ran into was that often OnHoverEnter / Exit, it was still registered as closest to the first object, but it wouldn't check again until there was an exit or enter, so if I wanted to grab after that check, I would often grab an object that wasn't highlighted while the first object was still highlighted. (Probably worth noting these objects are literally touching each other as its a color palette) So I had to put the functions to run in Update to keep it accurate and responsive. If you have any ideas to make it so the function only runs once or more optimized, let me know. Maybe I'll make this feature my first tutorial video, as it seems like a pretty common need in VR/AR development, but for some reason isn't a default feature in OpenXR. using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using System.Linq; public class DirectInteractorWithClosestObjects : XRDirectInteractor { [SerializeField] Dictionary distances = new Dictionary(); [SerializeField] List interactables = new List(); [SerializeField] IXRInteractable closestInteractable; Outline outline; protected override void Awake() { base.Awake(); Dictionary distances = new Dictionary(); List interactables = new List(); } public void OutlineClosestInteractable() { if (outline != null) { outline.OutlineWidth = 0f; } GetValidTargets(interactables); if (interactables.Count > 0) { foreach (IXRInteractable interactable in interactables) { distances.Add(interactable.GetDistanceSqrToInteractor(this), interactable); } distances.TryGetValue(distances.Min(k => k.Key), out closestInteractable); outline = closestInteractable.transform.GetComponent(); outline.OutlineWidth = 10f; interactables.Clear(); distances.Clear(); } } private void Update() { OutlineClosestInteractable(); } }
Hi Andrew, I'm trying to follow this, in particular I want to use GetComponent() on the XRSocketInteractor in side the CanSelect override but I ran into this: CanSelect(XRBaseInteractable) has been deprecated. Use CanSelect(IXRSelectInteractable) instead. I tried using the new version but IXRSelectInteractable does not show me GetComponent() or CompareWithTag to that matter - any thoughts?
Since Interfaces don't have a direct connection to a gameObject like a MonoBehaviour. You'll need to go through "interactable.transform.CompareTag". Which, was manually setup via the Interface.
@@VRwithAndrew - Super that did the trick I see where I was going wrong in my thinking now - I had it in my head a transform was part of a GameObject not a GameObject is attached to a transform. So it goes Transform -> GameObject -> Component not GameObject -> Component (of which transform is a component)
Hey man, the socket works once when the sim starts, but once I puck up the object, it just doesn't attach to the socket anymore. No errors or anything comes out of it. Have you had issues like this with this particular script? I tested a regular socket interactor and it works every time.
I really like these XR scripting videos, seems like no one else cares to get into it. Would you know how to make the socket automatically attach the interactable whenever it hovers the socket, rather than waiting for the interactor to stop selecting it?
Much appreciated! It's possible, but it's since changed, so I'm not sure what the best option is. Originally, you could override "requireSelectExclusive", but that's been deprecated. The last time I did this was for my Bow and Arrow upgrade with the "QuickSelect" function. However, I'm not sure if this still works, or is the best way of doing it. github.com/C-Through/XRI-BowAndArrow/blob/main/Assets/_BowAndArrow/Scripts/Notch.cs
hi, further question, how can i achieve that if I want the socket to accept a series of gameobjects and at the same time it can identify which gameobjects they are?
Hi Andrew! I noticed that the socket interactable has an interaction layer mask. I thought that by choosing a specific layer, only objects with that layer would get socketed. However, that was not the case. Even with a specific layer in the interaction layer mask, every object that was grabbable was also socketable. When you show some code from the XRBaseInteractor they even call a function that is called "IsOnValidLayerMask()". Do you know why it doesn't work with the layers? I don't really need that to work because this tag check works well but I was just curious. Thanks for the video!
I've used it, it can just be a bit tricky to setup. Just make sure you're setting the correct layers for both the interactable, and the socket. If the Interactable is marked to be on a particular layer, make sure that layer is also checked within the socket for it to check.
Yeah, you can add/remove the object to specific interaction layers. It's a bit tricky to describe, but when the object is selected. You can remove the Interaction the player would normally use to grab the object. You would keep the socket on a separate layer so it can continue to hold onto the interactable. Then, you can have a custom function within the socket to edit the selected object via the buttons, and levers.
Hey Andrew, I can't add the script. It says "The script don't inherit a native class that can manage a script" which apparently is a missing monobehaviour? I use Unity 2020.2. I can't program, just copying by the way.. :) Any suggestion?
@@VRwithAndrew It worked! I simply rewrite the code, but this time rather than adding it to the inspector I called it from there adding the script as a component (I don't know if was that though)! Amazing function! I needed it so much. Thanks!
Hi, firstly thanks for your sharings. I wonder how to detect which game object attached to XR Socket Interactor. How can we return game object's tag name or name?
Not for this particular project, but it's been fixed with the following code with thin XR Socket. var shaderName = GraphicsSettings.currentRenderPipeline ? "Universal Render Pipeline/Lit" : "Standard"; var defaultShader = Shader.Find(shaderName);
Hey Andrew, great tutorial. I Managed to get it working instantly. One further question, since I'm a beginner in Unity: How would I check if both sockets are inheriting their desired object and for example call a particle effect if this condition is true? Thank you in advance!
This may be a more advanced solution, but you can listen for the selection event of both of the sockets. Then, do a check to see if "selectTarget" is not null for both of them. If the check passes, you'd play the particle effect.
Hey Andrew! First of all, thank you for your awesome content, really helping me out :-) Wanted to ask you whether you know if finger tracking for Valve Index currently works in OpenXR, because I can't seem to get it running :-(
If you're using anything beyond [1.0.0-pre.3] - 2021-03-18, XR Toolkit will now automatically show Serialized Fields. So, no need for the custom Inspector!
These are honestly the best most straight forward tutorials for Unity i've found. Great stuff
That's my goal, happy to help!
Exactly what I needed.
Please keep this way of explaining what you do. I usually have a hard time to follow your professionalism and high-math but this time I really had no problems and I learned something instead of doing copy-paste with your videos.
I shall if I have enough ideas! I got a couple other ideas for some pretty useful things. :)
Babe wake up VR with Andrew uploaded
Honey, Xzarations commented.
Big fan of you keeping it simple on the scope of the video, but then in the video getting pretty in depth. I.e. talking about overriding functions and calling the base function and why that's necessary, and then covering the editor GUI. For me, at least, those little pieces of nuance are extremely valuable; arguably more so than just for creating a tag check for XRSocketInteractor, but just learning Unity in practical ways. For someone who is a pro at Unity/C# perhaps they may feel it's a waste of time for you explaining those things, but they can fast forward through that to see the final code, whereas if you didn't cover that stuff to appeal to that audience then the more noob audience would be missing out, so I think it's a win-win when you do that. Or, a win-draw if that makes sense
Thanks, Shawn! Yeah, that was more/less my thinking. Which is why it's pretty lucky that it made it into a vid. I would've just put the project on Patreon and called it a day.
I'm hoping there are more use-cases like this so I make a video like this once a month. I do enjoy having a video that isn't just a massive project.
Awesome! I Would love some more XR inreraction toolkit tutorials on overriding functions. It's the one thing that's like higher mathematics for me. Great explenations.
More to come! As XR Toolkit hits 1.0, it'll be nice to have some more universal stuff.
DAMN! The thing that I was looking for 1 month ago, thanks!!! I wanna a Vr Jam
Hopefully, we'll get to do one later this year!
Freaking Thankyou Brother
Splendid! Thanks.
You're welcome!
I needed this, thank you!
Glad it was helpful!
Hi Andrew, the tutorial is wonderful and easy to follow. Can I ask if there is a way for the socket to accept more than one tag?
You can update the variable to be a list of strings. You can then use a foreach loop to compare each one.
@@VRwithAndrew I see! I'll try it out, thanks Andrew
This was fantastic. Got it to work right away. What if I wanted to only allow the socket to accept items that are held by the player's xrcontroller? For example, I have set the socket to follow just ahead and below the camera as a sort of pouch, however it hoovers up any grabbable that comes into proximity. Would I set each item's tag to "socketable" on select and then remove the tag when select ends?
You'd want to add some functionality within the "CanSelect" function. Something like, "return interactable.isSelected", however, I'm not super sure how well this will work. But, it will get you started on prevent the Socket from just picking up any Interactable by accident.
While this software works normally, it doesn't work when I work with hand tracking. I wonder why? I haven't been able to solve it.
I am trying to outline the object that is about to be grabbed. I am adding an outline to OnHoverEntered, the problem I'm running into is if multiple objects are in the collider, it will outline all of them. How do I know which object is the one that is going to be grabbed and isolate the hover outline to just that object? Thanks Andrew.
You may need to use a Highlight Nearest functionality. There's a measurer within the Interactor to find the nearest Interactable. I'd start with the logic of, whenever there is a Hover Enter/Exit, find the nearest Interactable and add the outline.
@@VRwithAndrew I did it!! Thank you for the guidance, a problem I ran into was that often OnHoverEnter / Exit, it was still registered as closest to the first object, but it wouldn't check again until there was an exit or enter, so if I wanted to grab after that check, I would often grab an object that wasn't highlighted while the first object was still highlighted. (Probably worth noting these objects are literally touching each other as its a color palette) So I had to put the functions to run in Update to keep it accurate and responsive. If you have any ideas to make it so the function only runs once or more optimized, let me know. Maybe I'll make this feature my first tutorial video, as it seems like a pretty common need in VR/AR development, but for some reason isn't a default feature in OpenXR.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using System.Linq;
public class DirectInteractorWithClosestObjects : XRDirectInteractor
{
[SerializeField] Dictionary distances = new Dictionary();
[SerializeField] List interactables = new List();
[SerializeField] IXRInteractable closestInteractable;
Outline outline;
protected override void Awake()
{
base.Awake();
Dictionary distances = new Dictionary();
List interactables = new List();
}
public void OutlineClosestInteractable()
{
if (outline != null)
{
outline.OutlineWidth = 0f;
}
GetValidTargets(interactables);
if (interactables.Count > 0)
{
foreach (IXRInteractable interactable in interactables)
{
distances.Add(interactable.GetDistanceSqrToInteractor(this), interactable);
}
distances.TryGetValue(distances.Min(k => k.Key), out closestInteractable);
outline = closestInteractable.transform.GetComponent();
outline.OutlineWidth = 10f;
interactables.Clear();
distances.Clear();
}
}
private void Update()
{
OutlineClosestInteractable();
}
}
Hi Andrew, I'm trying to follow this, in particular I want to use GetComponent() on the XRSocketInteractor in side the CanSelect override but I ran into this:
CanSelect(XRBaseInteractable) has been deprecated. Use CanSelect(IXRSelectInteractable) instead.
I tried using the new version but IXRSelectInteractable does not show me GetComponent() or CompareWithTag to that matter - any thoughts?
Since Interfaces don't have a direct connection to a gameObject like a MonoBehaviour. You'll need to go through "interactable.transform.CompareTag". Which, was manually setup via the Interface.
@@VRwithAndrew - Super that did the trick I see where I was going wrong in my thinking now - I had it in my head a transform was part of a GameObject not a GameObject is attached to a transform. So it goes Transform -> GameObject -> Component not GameObject -> Component (of which transform is a component)
Hey man, the socket works once when the sim starts, but once I puck up the object, it just doesn't attach to the socket anymore. No errors or anything comes out of it. Have you had issues like this with this particular script? I tested a regular socket interactor and it works every time.
Most likely a change in XR Toolkit, I haven't revised this project in a while. I'll see what I can do.
I really like these XR scripting videos, seems like no one else cares to get into it. Would you know how to make the socket automatically attach the interactable whenever it hovers the socket, rather than waiting for the interactor to stop selecting it?
Much appreciated! It's possible, but it's since changed, so I'm not sure what the best option is. Originally, you could override "requireSelectExclusive", but that's been deprecated. The last time I did this was for my Bow and Arrow upgrade with the "QuickSelect" function. However, I'm not sure if this still works, or is the best way of doing it.
github.com/C-Through/XRI-BowAndArrow/blob/main/Assets/_BowAndArrow/Scripts/Notch.cs
hi, further question, how can i achieve that if I want the socket to accept a series of gameobjects and at the same time it can identify which gameobjects they are?
That would be a bit tougher to do, sockets can only have on selected object. So, you'd probably have to cycle through the interactables it's hovering.
Hi Andrew! I noticed that the socket interactable has an interaction layer mask. I thought that by choosing a specific layer, only objects with that layer would get socketed. However, that was not the case. Even with a specific layer in the interaction layer mask, every object that was grabbable was also socketable. When you show some code from the XRBaseInteractor they even call a function that is called "IsOnValidLayerMask()". Do you know why it doesn't work with the layers? I don't really need that to work because this tag check works well but I was just curious. Thanks for the video!
I've used it, it can just be a bit tricky to setup. Just make sure you're setting the correct layers for both the interactable, and the socket. If the Interactable is marked to be on a particular layer, make sure that layer is also checked within the socket for it to check.
is there a way to lock an item in there? and your able to toggle it on and off through events? (e.g. buttons, lever)
Yeah, you can add/remove the object to specific interaction layers. It's a bit tricky to describe, but when the object is selected. You can remove the Interaction the player would normally use to grab the object. You would keep the socket on a separate layer so it can continue to hold onto the interactable. Then, you can have a custom function within the socket to edit the selected object via the buttons, and levers.
@@VRwithAndrew thank you very much!
Great Tutorial! What do we need to add to make multiple sockets?
Can you explain that further?
@@VRwithAndrew Thank you very much worked. Can we change the blue image when we trigger it? Is it the 'hover mesh material' that comes from our code?
@@yasarbaba2413 That's correct!
Hey Andrew, I can't add the script. It says "The script don't inherit a native class that can manage a script" which apparently is a missing monobehaviour? I use Unity 2020.2. I can't program, just copying by the way.. :) Any suggestion?
Are you getting any compiler errors? Also, have you added XR Toolkit and all that to your project?
@@VRwithAndrew No errors, and yes XR interaction toolkit is installed
@@essend0 Hmmm, probably something weird happened. You may want to try creating a new script, or reimporting the one you've already made.
@@VRwithAndrew It worked! I simply rewrite the code, but this time rather than adding it to the inspector I called it from there adding the script as a component (I don't know if was that though)! Amazing function! I needed it so much. Thanks!
Hi, firstly thanks for your sharings. I wonder how to detect which game object attached to XR Socket Interactor. How can we return game object's tag name or name?
There is a variable called selectTarget for any Interactor, that'll give you whatever gameObject the socket is currently holding.
Are you using URP? Because i remember that the XR sockets didn't work with URP when the game was built
Not for this particular project, but it's been fixed with the following code with thin XR Socket.
var shaderName = GraphicsSettings.currentRenderPipeline ? "Universal Render Pipeline/Lit" : "Standard";
var defaultShader = Shader.Find(shaderName);
@@VRwithAndrew alright, thank you!
Hey Andrew, great tutorial. I Managed to get it working instantly. One further question, since I'm a beginner in Unity: How would I check if both sockets are inheriting their desired object and for example call a particle effect if this condition is true? Thank you in advance!
This may be a more advanced solution, but you can listen for the selection event of both of the sockets. Then, do a check to see if "selectTarget" is not null for both of them. If the check passes, you'd play the particle effect.
Awesome thank you! :D
Sure thing!
life saver
Doin' our best!
Hey Andrew! First of all, thank you for your awesome content, really helping me out :-)
Wanted to ask you whether you know if finger tracking for Valve Index currently works in OpenXR, because I can't seem to get it running :-(
No, not that I'm aware of! I'm not sure what the status of it is either.
@@VRwithAndrew oh dear that's not good
My slot is way too big in the game, although it looks normal in the editor.
I'm not sure what that could be if the slot is childed to a scaled object. That could cause the issue.