Jump to content
  • entries
    943
  • comments
    5,899
  • views
    923,202

Creating a VR Teleporter: Part 2


Josh

2,692 views

 Share

The next step is to put our scene into VR and look at everything. I'm about six feet tall and the player model seems the same height, so that all looks right. The controllers, as you can see below, are all working with full articulation of all controls. The teleport indicator looks good too.

Now we're going to start our VR player script. We start with a new script and initialize the VR environment in the Start() function. A camera is also created in code, and I deleted the camera from the scene.

function Script:Start()
	if VR:Enable()~=true then
		Print("Error: Failed to initialize VR environment.")
	end
	self.camera = Camera:Create()
end

I wanted to look at the controller models and see if there was a child that indicated where the tip of the controller was, for aiming a beam. The code below will wait until a controller model is loaded and then print out the names of all its children.

function Script:Start()
	if VR:Enable()~=true then
		Print("Error: Failed to initialize VR environment.")
	end
	self.camera = Camera:Create()
	
	self.partslisted=false
end

function Script:UpdateWorld()
	if self.partslisted==false then
		local model = VR:GetControllerModel(VR.Left)
		if model==nil then
			model = VR:GetControllerModel(VR.Right)
		end
		if model~=nil then
			self.partslisted = true
			local n
			for n=0,model:CountChildren()-1 do
				local subobject = model:GetChild(n)
				local name = subobject:GetKeyValue("name")
				System:Print(name)
			end
		end
	end
end

The result is below. Three blank lines mean that three subobjects in there have no names. You can tell what some of the subobjects are, but none of them look like what I am looking for.

body
button


led
lgrip
rgrip
scroll_wheel
status
sys_button

trackpad
trackpad_scroll_cut
trackpad_touch
trigger

None of those look like what I am looking for, so I am just going to use the controller model itself and hope for the best. The code below creates a box sticking out of the controller.

function Script:Start()
	if VR:Enable()==false then
		Print("Error: Failed to initialize VR environment.")	
	end
	self.camera = Camera:Create()
end

function Script:UpdateWorld()
	
	local controller = VR:GetControllerModel(VR.Right)
	if controller~=nil then
		if self.beam==nil then
			self.beam = Model:Box(0.05,0.05,4)
		end
		if self.beam:GetParent()~=controller then
			self.beam:SetPosition(0,0,0)
			self.beam:SetRotation(0,0,0)
			self.beam:SetParent(controller,false)
			self.beam:Move(0,0,-2)
		end
	end
	
end

As a result, we've got this funny light saber-looking thing:

Image2.thumb.jpg.79532db1e7410ab19ba4133b274dc264.jpg

Now let's replace the box with a sprite and apply our third teleport material to it. We'll make the sprite rotate around its own Z axis to face the camera using the SetViewMode() command.

function Script:Start()
	if VR:Enable()==false then
		Print("Error: Failed to initialize VR environment.")	
	end
	self.camera = Camera:Create()
end

function Script:UpdateWorld()
	
	local controller = VR:GetControllerModel(VR.Right)
	if controller~=nil then
		if self.beam==nil then
			self.beam = Sprite:Create()
			self.beam:SetViewMode(6)
			self.beam:SetSize(0.05,4)
			self.beam:SetColor(1,2,2)
			local mtl = Material:Load("Models/VR/teleport3.mat")
			if mtl~=nil then
				self.beam:SetMaterial(mtl)
				mtl:Release()
				mtl = nil
			end
		end
		if self.beam:GetParent()~=controller then
			self.beam:SetPosition(0,0,0)
			self.beam:SetRotation(0,0,0)
			self.beam:SetParent(controller,false)
			self.beam:Move(0,0,-2)
		end
	end
	
end

Now it really looks like a light saber!

Image4.thumb.jpg.bdcdca96fcfcadcf11b51f1406be9640.jpg

The next step is to add picking so we can use the beam to place the teleporter. I deleted the teleport indicator prefab from the map and loaded a copy of the prefab up in the Start() function:

function Script:Start()
	if VR:Enable()==false then
		Print("Error: Failed to initialize VR environment.")	
	end
	
	--Create the player camera
	self.camera = Camera:Create()
	
	--Load the teleport indicator prefab
	self.teleportindicator = Prefab:Load("Models/VR/teleport.pfb")
	self.teleportindicator:Hide()
end

function Script:UpdateWorld()
	
	local controller = VR:GetControllerModel(VR.Right)
	if controller~=nil then
		
		--Create the teleporter beam
		if self.beam==nil then
			self.beam = Sprite:Create()
			self.beam:SetViewMode(6)
			self.beam:SetSize(0.05,4)
			self.beam:SetColor(1,2,2)
			local mtl = Material:Load("Models/VR/teleport3.mat")
			if mtl~=nil then
				self.beam:SetMaterial(mtl)
				mtl:Release()
				mtl = nil
			end
		end
		
		--Reparent the beam, if needed
		if self.beam:GetParent()~=controller then
			self.beam:SetPosition(0,0,0)
			self.beam:SetRotation(0,0,0)
			self.beam:SetParent(controller,false)
			self.beam:Move(0,0,-2)
		end
		
		if VR:GetControllerButtonDown(VR.Right,VR.TouchpadButton)==true then
			local world = self.entity.world
			local pickinfo = PickInfo()
			local p0 = controller:GetPosition(true)
			local p1 = Transform:Point(0,0,-4,controller,nil)
			if world:Pick(p0, p1, pickinfo, 0, true)==true then
				self.teleportindicator:SetPosition(pickinfo.position)
				self.teleportindicator:Translate(0,0.05,0)
				self.teleportindicator:Show()
			end
		end
		
	end
	
end

We can move the teleporter indicator around. It climbs straight up walls and there are lots of problems, but you can see the beginnings of a teleporter:

The next thing we want to do is add a normal check to prevent the teleporter from working if the picked slope is too high. You can get the slope in degrees of any normal with the following bit of code:

local slope = 90 - Math:ASin(pickinfo.normal.y)

We're also going to hide the indicator when a valid teleportation destination isn't picked. Here's the complete code:

function Script:Start()
	if VR:Enable()==false then
		Print("Error: Failed to initialize VR environment.")	
	end
	
	--Create the player camera
	self.camera = Camera:Create()
	
	--Create teleporter beam
	self.beam = Sprite:Create()
	self.beam:SetViewMode(6)
	self.beam:SetSize(0.05,20)
	self.beam:SetColor(1,2,2)
	local mtl = Material:Load("Models/VR/teleport3.mat")
	if mtl~=nil then
		self.beam:SetMaterial(mtl)
		mtl:Release()
		mtl = nil
	end
	self.beam:Hide()
	
	--Load the teleport indicator prefab
	self.teleportindicator = Prefab:Load("Models/VR/teleport.pfb")
	self.teleportindicator:Hide()
end

function Script:UpdateWorld()
	
	self.teleportindicator:Hide()
	self.beam:Hide()
	
	local controller = VR:GetControllerModel(VR.Right)
	if controller~=nil then
		
		--Reparent the beam, if needed
		if self.beam:GetParent()~=controller then
			self.beam:SetPosition(0,0,0)
			self.beam:SetRotation(0,0,0)
			self.beam:SetParent(controller,false)
			self.beam:Move(0,0,-10)
		end
		
		--Activate teleporter
		if VR:GetControllerButtonDown(VR.Right,VR.TouchpadButton)==true then
			local world = self.entity.world
			local pickinfo = PickInfo()
			local p0 = controller:GetPosition(true)
			local p1 = Transform:Point(0,0,-20,controller,nil)
			if world:Pick(p0, p1, pickinfo, 0, true)==true then
				local slope = 90 - Math:ASin(pickinfo.normal.y)
				if slope<35 then
					self.teleportindicator:SetPosition(pickinfo.position)
					self.teleportindicator:Translate(0,0.05,0)
					self.teleportindicator:Show()
					self.beam:Show()
				end
			end
		end
		
	end
	
end

And now we will add the actual teleport mechanic. We take the picked position, subtract the camera's current XZ position, and add to the existing VR offset. This took a little trial and error, but it works perfectly:

--Check if teleporter is active and the button was released
if self.beam:Hidden()==false then
	if VR:GetControllerButtonDown(VR.Right,VR.TouchpadButton)==false then
		local offset = VR:GetOffset()
		local pos = self.teleportindicator:GetPosition()
		local campos = self.camera:GetPosition(true)
		pos.x = pos.x - campos.x + offset.x
		pos.y = pos.y - 0.05
		pos.z = pos.z - campos.z + offset.z
		VR:SetOffset(pos)
	end
end

Here it is in action. We can not yet teleport up to the highest blocks, but we can freely move around the map.

Next we will make the beam arc so we can climb up to platforms above us.

  • Like 1
 Share

5 Comments


Recommended Comments

The VR stuff is shaping up nicely.

I have a game idea I worked on some time ago I might return to for checking out VR.... 

cbv7MlR.jpg

 

Obviously the template has a clear VR focus and needs to stay on track, but I'd like to mention that I think it would be really good if we had a VR template (or engine support) to show a mechanism of downgrading to run in a NON-VR state as well (wasd and mouse, or controller).  Dishonoured uses a teleport feature just fine. and you pick stuff up. Should we really make our games ONLY accessible via VR?  Are they really un-workable or immersion braking on a WASD + mouse or controller setup? Maybe the answers for some people is yes and yes.  But if some think no why exclude them? 

A nice example of degrading from VR, or extending to VR (whichever way you want to look at it) is a useful feature for a template (or engine) to handle.  Yeah we could all code our own solutions but I'm pretty sure a good few users would appreciate a solid template or detailed example.

Keep up the good work. Looking forward to how this develops.

 

  • Like 1
Link to comment

Wait, I thought you said lua's garbage collection would get in the way of VR? Shouldn't this be done in C++ or you're prototyping this first?

Link to comment
13 hours ago, reepblue said:

Wait, I thought you said lua's garbage collection would get in the way of VR? Shouldn't this be done in C++ or you're prototyping this first?

If you have a lot of game logic you definitely want to use C++.

13 hours ago, mdgunn said:

Obviously the template has a clear VR focus and needs to stay on track, but I'd like to mention that I think it would be really good if we had a VR template (or engine support) to show a mechanism of downgrading to run in a NON-VR state as well (wasd and mouse, or controller).  Dishonoured uses a teleport feature just fine. and you pick stuff up. Should we really make our games ONLY accessible via VR?  Are they really un-workable or immersion braking on a WASD + mouse or controller setup? Maybe the answers for some people is yes and yes.  But if some think no why exclude them? 

I think you will find that standing VR games are extremely different from a regular game on a flat monitor. It would be possible to double-code some items but it would create a lot of extra code, making it hard to understand, and there would eventually be things I want to do that don't work without VR at all.

Link to comment

Turns out the code I found have for Temples and Towers was massively behind where I got up to with it and didn't include any of the map I did above.  It's probably backed up onto some hard drive somewhere but god knows where.  Would be starting pretty much from scratch.  Shame.

 

Link to comment
5 hours ago, mdgunn said:

Turns out the code I found have for Temples and Towers was massively behind where I got up to with it and didn't include any of the map I did above.  It's probably backed up onto some hard drive somewhere but god knows where.  Would be starting pretty much from scratch.  Shame.

If it's playable, I would just release it first and then keep working on it. There's always a reason to hide things away just a little longer.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...