what is up everyone last week we talked about doing continuous movement in xr and in this
video we're talking about teleportation so I hope you enjoy and uh let's jump into it as usual I'm
going to set up an open xr vr project so if you have already watched some of my videos and know
how to do that skip to this timestamp and I'll see you guys in a minute if you don't know how to set
up an xr rig I'm going to go through it really fast here but if you want a more in-depth video
make sure to check out my introduction to unity vr we go to edit project settings click on package
manager enable preview packages and then we go to window package manager unity registry
find open xr plugin install that it'll ask you to restart your project so just hit yes it's going to
change the input system from the old system to the new system and we're also going to want to install
the xr interaction toolkit and make sure to grab the sample default input actions off of that now
back into the project settings we're going to go down to xr plugin management check open xr preview
hit the exclamation point and fix all go to features and check the device that you're using
so I'm using oculus so we're going to use oculus touch controller now your project is set up to use
xr and we can start implementing teleportation now before we add our xr rig we want to go into the
assets samples xr interaction toolkit whatever package you installed and default input actions
and inside of here we want to um we want to add each one of these to our action based controllers
and now we can finally add our xr rig so right click in the hierarchy go down to xr and add a
room scale xr rig action based this will go ahead and add an xr interaction manager and an xr rig
with a camera offset and a main camera left hand controller right controller inside of the xr rig
make sure to add an input action manager and inside of the action assets we want to
drag the xri default into that and now if you played the scene you'd be able to jump in and
you would see some lines coming out of your hands and you'd be able to move around your controllers
and your hmd but that's not enough for us we want to move so let's add a locomotion system so right
click on the xr rig go down to xr and add a action based locomotion system this will automatically
come with a teleportation provider and a snap turn provider inside of the snap turn we don't want to
use both thumb sticks to snap turn so we're going to uncheck the left and the locomotion system is
automatically going to find this xr rig but just to speed up our startup time I'm going to drag
the xr rig over here and set that oh and also make sure your xr rig transform is set to zero mine got
offset at some point now we're actually pretty close to being set up for teleportation one other
thing we need is to add a teleportation area to the location that we want to teleport to so
we're going to select the ground and then over here in the inspector add a component and we're
going to search for teleportation area you get two options here you can do an area or you can
do an anchor when you teleport to an area you can teleport to anywhere on the surface of that
object when you teleport to an anchor however it sends you to the anchor point of that object so
to the center and it adjusts your position and your rotation to that specific spot so if you
want to have your player only be able to teleport to specific locations or very specific areas then
you use anchors throughout your scene else you can just use an area and set the area like you
would at nav mesh for this we're going to use area and now you can teleport already you can teleport
by holding down the grip button and pointing wherever you want to go and if the line interactor
is hovering over anything that is a teleportation area it'll send you there but the he issue is it's
going to keep sending you to that spot even if you hold down the reticle and this is going to
cause some issues and it's not really the behavior we want to have the player teleport somewhere when
they try to grab something it doesn't really make sense in my head why this would be the default for
the teleportation so we're going to make some adjustments now in most games you're able to
teleport by pushing the thumbstick and that will start the teleportation sequence so you'll have
a line that arcs out and lands and has a reticle that shows you where you're going to teleport to
and the position that you have your thumb stick is also going to be the rotation that you end
up when you teleport to that specific spot and that is completely different than pressing the
grip button and being able to hold the grip button and teleport to anywhere on the teleportation area
it's bizarre to me why they coded the default like this so we're gonna we're gonna make some changes
first off let's make the line look a little bit better we're going to use the left hand controller
as the primary teleportation controller and we're going to use the right hand as the snap turn
controller so actually we're going to go into the right hand controller and just take away the line
interactor stuff so we're only going to have an xr controller and a transform inside of the right
hand now on the left hand we can go into the xr interactor line visual and inside of here we can
decrease the width so I'm going to go to .01 which is about half the width and you can also add a
gradient to the line and a invalid color gradient so you can make this transparent on one end and
it gets more solid when it gets to the other end and you can change the color to green or
whatever you want and also there's a width curve so you can also have your line be smaller on one
end and larger on the other and there is a reticle and that's going to be what shows up when it
hits an object and one more change we're going to make is going up to the xr interactor and
instead of having a line type being a straight line we're going to use a projectile curve
and I'm going to change the velocity down to about 5. that way it's not reaching out and arcing away
super super far you'll see what I mean when we test it again all right let's do some coding now
go into your locomotion system and we're going to add a component and I'm going to call this
teleportation manager create a new script and before we go into the editor and start working on
this script i want to show you some of the input actions we're going to be using so let's go into
samples xr interaction toolkit package and the default input action so inside of your xri left
hand because that's what we're going to be using you'll notice that you already have a teleport
select a teleport mode activate and a teleport mode cancel the difference between selecting
and activating is actually the direction that you press the thumbstick so you activate it by
pushing the thumbstick forward and then select the thumbstick can be any direction i played around
with this a little bit and I'm not actually even going to use the teleport select we're just going
to use this move down here which is just a primary 2d axis 2d vector and that's going to give us the
thumb stick position and I'm actually going to go in here and select everything for the directions
make sure you go in here and hit auto save and then we can exit out of that and start to go into
the code so open up your teleportation manager script in order to access those actions we need to
call an input actions asset you may end up having a missing reference for this so you can auto
import it or you can type in using unity engine dot input system up here at the top now let's
grab the activate action the cancel action and the thumb stick move action and it create a variable
I'm gonna call this one activate and in order to get the asset I'm going to call action asset dot
bind action map and then you type in the name of the action map that you want so this one is going
to be xri left hand and then dot bind action and then again the name of the action so this one is
going to be teleport mode activate and then for each of these actions that we get we also need
to enable them so activate dot enable make sure you do capital e enable with parentheses at the
end and then I'm going to do the same thing for cancel and one more time for the move direction
but I'm going to call this one thumbstick just so we can remember what it actually is and some
stick we're actually going to want to use later on in the code and to do that I'm going to make
it a global variable by putting it up here and then the way I usually code things is I designate
global private variables with an underscore in the front here that's why I'm doing that all right
so now we want something to happen whenever you activate or cancel a teleportation action so below
the update method I'm going to create two more methods one is going to be on teleport activate
and the other is going to be on teleport cancel and we're going to subscribe to these methods
anytime that teleportation is activated or any time the teleportation is cancelled respectively
and to do that we say activate dot performed and then we're going to use plus equals and then the
method we want to use on teleport activate and we do not put the parentheses and you're going to get
an error here and that's because activate.perform sends a context and we need to receive that in
our method so I'm going to type that in here and of course we're going to have the same issue for
the canceled as well so I'm going to just copy and paste this and below cancelled we can say cancel
dot performed plus equals on teleport cancel now any time this action is performed the this method
is going to run and it's much more efficient than doing this method inside of the update
call because it's not running every single frame it's just only when this action is performed the
next thing we're going to add to this class is the raycast that we're using to tell the
game where the player wants to teleport to we're going to do that the same way
by serializing the field and this is going to be an xr ray interactor and I'm going to name it ray
interactor and then in the start method we're actually just going to start out by disabling
the ray interactor to do that we type in ray interactor enabled equals false because the idea
is to only show the line when you're pushing the stick forward because when you release it's going
to automatically teleport you and then when you push the stick forward it starts the teleportation
and then you should be able to cancel it by pressing the grip button that's how the process
is going to work or that's at least how it works in my mind so we know when on teleport activate
is called we want to enable the raycast that makes sense so inside of here we're going to
say ray interactor dot enabled equals true and then we also want the opposite to happen if we
cancel ray interactor enabled equals false that makes sense now the tricky part of this is finding
out where the position of the raycast is when we release it so if we tried to grab the position
here in the activate method that wouldn't be the right spot because that's wherever you first
started the teleportation but you haven't finished it yet and you could start it and then move to
a different position and then release but if we tried to get the position right when it activated
it would just send you back to the first position no matter what so we don't want to do that and
the best way I've come up to do this is to have a toggle that says okay the teleportation ray
is active and then at the very last moment when it becomes not active that's when we want to grab the
position and that's when we want to teleport and we're going to perform that inside of the update
method so I'm going to create an if statement inside of the update method and it's going to
have a new variable called is active let me use my editor to go ahead and create that so this is
running every frame so if is active is false we want the rest of the code to just not even run
so I'm going to flip is active and then just type return underneath it so now if it is not active
if the teleportation ray is not active then we're just going to escape and not do anything if it is
active we can continue and do code underneath here but where is this variable actually going to be
set we're actually going to set it down here in the on teleport activate method that makes
sense so we're going to set this one to true if on teleport activate is activated and also don't
forget to throw is active equals false inside of the on teleport cancel because when we cancel
we obviously want it to deactivate so now continuing on in the update method we're going
to actually start to use this thumbstick here so if the thumbstick is re-centered and in order to
check for that we say thumbstick dot triggered we also want to return so now we have two conditions
one is if the actual teleport is not active we're not going to continue and the second one is if the
thumb stick is still pushed forward then that that means that the player doesn't want to teleport yet
so we're just gonna leave still and now at this point in the update method the thumbstick has
been pushed forward the teleportation has been activated and then it's also been released the
trigger is back to zero so thumbstick.triggered is gonna be false so that means that the user
now wants to teleport and so we're gonna have to get a raycast and try to get a hit off of
it so this is where we're going to use the ray interactor and we're going to use a method called
get current raycast hit and this is going to give us back a raycast hit variable and we can actually
use this as another if statement just like we did before it's going to keep doing if statements
and then we'll need to invert this if statement because if it comes back false that means that
we didn't hit anything the player tried to teleport to something that doesn't exist so
we're just going to exit but this one's going to be a little bit different than the first two
because the user has stopped trying to teleport so we also want to turn off the ray interactor and we
also want to turn is active off so we're going to set ray interactor enabled equal to false and is
active equal to false but if it does hit something we can now use the teleportation provider which we
need to bring in to the code up here we're going to serialize field private teleportation provider
and I'm just going to call it provider and then down here we can say provider view teleportation
request and then this needs a teleportation request object so we're going to make that up
here say teleportation teleport request going to be equal to a new request and then there's four
different variables you can put inside of here there is a destination position a destination
rotation a match orientation and a request time and you don't actually have to fill out all of
these the only one you actually really need is the position and that position is going to be our hit
dot point I'm not going to do the match orientation or the request time but in an
effort to be transparent like I really want to be on this channel I could not figure out how
to do the rotation for the teleportation in my head it makes sense and I tried it and I just
couldn't get it to work so that kind of presents an opportunity for you guys if you come up with
the solution for how to set the rotation using the thumb stick so when you push the thumbstick out it
sets the position and then when you release it I want to be able to rotate towards the
last position of the thumb stick but the issue is if we tried to get the thumb stick location
now it would always be zero because we only teleport when the thumb stick is back centered
and so i tried a little bit with getting the last one or last couple thumbstick positions but I
couldn't figure out how to work it so if someone comes up with an idea of how to do a quaternion
here and give me a rotation I would be forever grateful and I will do an update video and I will
mention you and give you a big shout out because um I'm learning and you guys are learning and I
think it's best when we all learn together I don't want to say I know everything and just be this top
dog xr guy I'm learning the same as you guys so so if someone comes up with a solution to this I will
do an update video and give you a big shout out so for the time being I'm going to comment that out
and put a question mark here and then let's put the request into the teleportation request method
and that should request our teleportation and then this will check to see is it a valid teleportation
request if so it will teleport us and then at the very end we want to set ray interactor to
false and is active to false I believe that is everything so make sure you save and then we're
going to go back to unity and go ahead and set these serialized fields so we need the action
asset we need the array interactor that's attached to the controller and then we need the provider
which is in the same component and now let's test it and see how it works so you can see when I push
my thumbstick down the ray comes out and then when I release I teleport and then the ray disappears
and then when I push the thumbstick up again the ray comes back out and when I release teleport
and if I try to teleport to something that doesn't exist it's like outside here I release and the ray
interactor goes away and I don't teleport which is the exact behavior that we want from here you can
play around with the line however you want add a new material add a transparency add some particle
effects add a reticle here in the game object spot any kind of shape game object will do you
can throw that in here just to make it a little more obvious circle of where the user is going to
teleport to there you go I really hope this helped and remember my challenge to you if you figure out
how to get the rotation working then send me a comment or an email and I will do an update video
and give you a big shout out and speaking of shout outs there are a couple of people that I am
excited to give a shout out to him and Austin are new to the Patreon gang and it absolutely blows
me away that both of them would want to support me and my work with a few dollars every month
so thank both of you Tim and Austin for being so supportive and if you're interested in becoming
a Patreon there is a link down in the description you will get access to all of the source code from
this video and all the previous videos I've ever done you get the whole project code everything and
there's also a couple other tiers where you get exclusive live streams with me and also any of the
games I develop you get access to so check that out see if that's something that would interest
you and as always free of charge if you guys run into any issues with any of the videos i do or if
you just run into a issue coding or something just leave a comment below any of my videos and I will
respond within an hour or two and try to help you out i really enjoy doing the one-on-one comments
and interactions with you guys so keep posting comments and I'll see you in the next video