Destinations

Destinations

评价数不足
Play Area Manipulation
由 Rectus 制作
The VR play area is by default anchored to a static position in the world. By scripting, it is possible to manipulate the play area anchor in order to move the player around.

While this guide is written for Destinations, it should work exactly the same in SteamVR Home as well.
   
奖励
收藏
已收藏
取消收藏
Examples
Basics
Each player has a HMD Anchor entity associated with them, positioned on the ground at the center of the VR play area. While it is not possbile to move a player entity directly, the position and orientation of the anchor can be changed, moving the player with it. The ancor can also be parented to another entity such as an elevator or roller coaster, making the player move along with it.

There are some limitations to this though. In particular, the changing the anchors orientation on the picth or roll axis causes the Vive motion controllers to render in the wrong position, as if the play area was still upright. This will make the player unable to teleport or access the game menu, althoguh it may still be useful when the player doesn't need to use the controllers, such as during a roller coaster ride.

The only way to access the HMD Anchor is through the scripting system. It is done through the CBasePlayer::GetHMDAnchor() method avaliable in the script handls of the players.

This example shows how to iteate through evary player and accessing their anchor.
-- Iterates through each players HMD anchor. function EnumerateHMDAnchors() local player = Entities:FindByClassname(nil, "player") while player do local anchor = player:GetHMDAnchor() -- Should print the entity class name of the anchor. print(anchor:GetDebugName()) player = Entities:FindByClassname(player, "player") end end
Parenting the play area
To make the play area move along with another object such as an elevator, the anchor can be parented to it.

Example: Elevator

This example has a func_door elevator with a trigger_multiple parented to it. When the player walks/teleports onto the elevator, the trigger runs a script function that parents the players anchor to the elevator entity. When the player steps off the elevator, the anhor is unparented.

1. Creating the script
Use a text editor such as Notepad to write the script:

-- Parents the activating players play area to the elevator entity. function ParentPlayer(params) -- Check that a valid player activated the trigger. if params.activator and params.activator:GetClassname() == "player" then -- Get a reference to the elevator entity. local elevator = Entities:FindByName(nil, "elevator") params.activator:GetHMDAnchor():SetParent(thisEntity, "") end end -- Removes parenting for the activating player. function UnParentPlayer(params) -- Check that a valid player left the trigger. if params.activator and params.activator:GetClassname() == "player" then params.activator:GetHMDAnchor():SetParent(nil, "") end end

Save the script in \Destinations\game\steamtours_addons\playarea_example\scripts\vscripts\ (create the vscripts directory if needed), with the extension .lua.



2. Setting up the entitites
How to set up the elevator itself and the buttons is outside the scope of this guide.
Create the elevator, and add a trigger_multiple on top of it. Parent the trigger to the elevator, and set its Entity Scripts keyvalue to the file name of your script.


Add outputs on the trigger to call the script functions on itself.


If everything is set up correctly, the player should move with the elevator only when standing on it.

See the example map for a working elevator along with a roller coaster working on the same principle.
Moving and angling the play area
Moving the player of play area can be accomplished by setting the origin of the anchor to a new position using the CBaseEntity::SetOrigin() method. This can be useful for teleporting the player between different areas of the map.

This can also be used to move the player around (almost seamlessly), see the Barnacle Gun in my scripted item test range: https://psteamcommunity.yuanyoumao.com/sharedfiles/filedetails/?id=744116848

The angles of the changed using CBaseEntity::SetAngles() method, rotating the play area. Howvever note that this is buggy, and will cause the motion controller to appear in the wrong place.

Example: Player teleporter

1. Create the script
In the same way as in the above example, create a script with the following content, and place it in \Destinations\game\steamtours_addons\playarea_example\scripts\vscripts\:

-- Teleports the player to the location of a destination marker. function TeleportPlayer(params) -- Check that a valid player activated the trigger. if params.activator and params.activator:GetClassname() == "player" then local destination = Entities:FindByName(nil, "teleport_dest") local anchor = params.activator:GetHMDAnchor() -- Calculates the players postion relative to the anchor center using vector arithmetics. local localPlayerOrigin = anchor:GetOrigin() - params.activator:GetOrigin() anchor:SetOrigin(localPlayerOrigin + destination:GetOrigin()) end end

The function in this script moves the play area to the destionation marker, but adds the offest beween the player and the anchor to it, so that the player ends up on the marker.

2.
Create a trigger_multiple to teleport from, and add the script to it. Add an output from it to call the script function to teleport the player. Also create an info_target entity for the destionation, and name it teleport_dest.


Now when stepping into the teleport trigger, the player should appear on to of the destination marker.

The example map has a working version of this, as well as an example that also rotates the play area, letting players walk on walls.
34 条留言
KartMakerBrosU 3 月 1 日 下午 12:57 
Ok, Thank you!
Rectus  [作者] 2 月 14 日 下午 3:24 
I don't think I've seen anything that can detect it. Running a think function is probably the best option.
KartMakerBrosU 2 月 14 日 下午 2:39 
Is there a way to detect when the player has teleported to another area? I'm trying to get an object to follow them and my current solution is to simply set a think function that gets called every frame then set its location to the player.
Rectus  [作者] 2023 年 1 月 8 日 上午 8:49 
SetAngles or SetAbsAngles should work if I remember right.
klarix 2023 年 1 月 8 日 上午 8:44 
Hello... me again ^^,
I was wondering if you had any idea on how to change the player orientation using the anchor after the teleport, I tried to use anchor:SetAngles(pitch, roll, yaw) & anchor:SetAngularVelocity(pitch, roll, yaw); but none seems to work and I can't find other function that looks to do what I want to acheive in the scripting API reference.
Have a great day and thanks again for all the hints so far :-) !
klarix 2023 年 1 月 2 日 上午 10:32 
Haaaaaaaa, indeed it works with this port 😀 ! Thanks for clarifying ! I’m impressed by your knowledge… I didn’t find those informations anywhere !
Rectus  [作者] 2023 年 1 月 1 日 下午 1:20 
Oh, sorry, the correct port is 29009, that should make it work when launched from SteamVR.
klarix 2023 年 1 月 1 日 下午 12:54 
Ok I found what the problem was, leaving a message here to explain in case it can help someone else...
When launching SteamVR from the steam app, and then using the SteamVR menus as described below "SteamVR --> Workshop --> Create/Modify an environment", it don't work !
BUT
if I launch the "steam environment" app without using those menus from SteamVR (directly launching "C:\SteamLibrary\steamapps\common\SteamVR\tools\steamvr_environments\game\bin\win64\"steamtourscfg.exe" then it will launch SteamVR as well and I have all console output !
I don't know why it behave like this but it works doing so...
klarix 2023 年 1 月 1 日 上午 11:39 
I can't make it work... I probably do something wrong...
I'm using SteamVR --> Workshop --> Create/Modify an environment which launch "SteamVR Home" and the "Asset browser", from there I launch Hammer to make my map in which I make use of your Lua script to teleport the player.
I found a vconsole2.exe file in SteamLibrary\steamapps\common\SteamVR\tools\steamvr_environments\game\bin\win64\ So i guess this is the right one, and made a connection to both 29000 & 29001, but when I add a print statement at the beginning of the function like this :

function TeleportPlayer(params)
print("IM THERE...")
...
end

Nothing is coming out of the console, in fact there is nothing at all in the console :-/
I searched almost the whole day, and can't find any documentation on how to debug a piece of script for SteamVR environment on internet... Any clue what I'm doing wrong ?
And sorry to bother you with all my questions by the way, feel free to tell me if I'm too annoying :-)
Rectus  [作者] 2023 年 1 月 1 日 上午 10:10 
You can open the the console in most tool windows from Tools->VConsole, or finding vconsole2.exe in the same place the app excutable is. If you are mapping for SteamVR Home, it is by default set to the wrong port, so you will have to click the blue plus sign in the top left corner and add a connection to port 29001 to get output.