PoligonVR

Documentation


  • Updated: 19 June, 2024

Avatar Socket

Avatar Socket is a web socket system which allows you to control parameters on the avatar you are wearing.

To connect to Avatar Socket, use the following address:

ws://127.0.0.1:9005

If you want to run the server on a different port, you can use the launch argument:

--avatar-socket-port 1234

When the connection is made, PoligonVR will respond with all the available parameters. Same applies when your avatar changes.

Messages and payloads are in the form of a JSON string. Heres an example on how to set a parameter on your avatar

{
    "type":"parameters",
    "parameters":[
        {
            "name": "MyIntParameter",
            "type": "Int",
            "value": 5
        },
        {
            "name": "MyFloatParameter",
            "type": "Float",
            "value": 3.14
        },
        {
            "name": "MyBoolParameter",
            "type": "Bool",
            "value": true
        }
    ]
}

You can write your application in any programming language that supports web sockets. One example is C# with websocket-sharp


CCK Avatars


Avatar Descriptor

Avatar Control

NOTE: The animator system is planned to receive a rework which will make use of Unitys playable layers in the future instead of PVR's animator merging system.

Avatars for PoligonVR runs on a hierarchy based animator system which allows for easy modifications to animators.

  1. Locomotion - General movement animations like walking, running etc.
  2. Additive - Used to expand the locomotion layer.
  3. Emote - Used for playing emotes like waving for example.
  4. Hands - Used for hand gestures.
  5. FX - Used for generic toggles like clothing etc.

It's very important to correctly assign corresponding animators in the predefined hierarchy. We also allow for additional 'FX' animators to create more modular features for your avatar.


View / Voice Positioning

In order for your avatar to work correctly you must assign the view & voice position. For additional customizations, you can set the parent of the voice position. By default the voice position is always parented to the head.


Lipsync

PoligonVR uses Oculus Lipsync which allows for 15 different visemes.


Eye Look

NOTE: This feature is currently not implemented in-game but will be very soon


Avatar Parameters

Avatar parameters is a system to effortlessly sync animator parameters with other users.

Behind The Scenes

All parameters are synced every second with a "passive synchronizer". This ensures no noticeable de-sync can occur between players. When a parameters value is changed, it's added to the NetIK's package which is sent every 100ms. The NetIK can hold up to 10 parameters per package.

Parameter Types

TypeDescription
IntA 8-Bit integer with a range between 0 to 255
FloatA 8-Bit floating point with a accuracy between -1.00 to 1.00
BoolA 1-Bit bit true/false value

You can currently only sync up to 256 bits of parameter memory


Avatar Menu

Coming soon


CCK Worlds


PVR_WorldDescriptor

Coming soon


PVR_Pickup

Fields

FieldDescription
TitleThe title of the pickup when the cursor is hovered over it (leave empty to disable it)
Max Pickup DistanceThe maximum distance the pickup can be picked up from
Physics Based*Experimental - Makes the pickup fully physical when picking it up
Hide HighlightDisables the highlight around the pickup
Pickup ModeThe behaviour of the pickup when picking it up (for P#'s OnUse events, it must be set to 'Toggle')
Force PositionForces the pickup into a different position relative to the controller
Force OrientationForces the pickup to align into a rotation. This is useful for weapons for example

P# Scripting System

P# or "PSharp" is a C# scripting system which is powered by a open-source CIL interpreter called dotnow. Due to it being fully interpreted, unexpected behaviours can occur. We are activly working together with the author of dotnow to fix these issues over time.
P# requires decent knowledge of Unity C#.


Important Information

There are some differences between Unity C# and P# that you must be aware of.

Doing GetComponent<PSharpBehaviour>() will not work due to current limitations regarding generic types.
Instead, you must do (PSharpBehaviour)gameObject.GetComponent(typeof(PSharpBehaviour))
Getting a non PSharpBehaviour such as GetComponent<PVR_Pickup>() will work just fine.

P# comes with its own Scripting Define Symbols which is called "PSHARP_RUNTIME". Other symbols such as "PVR_CCK_WORLDS" & "UNITY_EDITOR" works too!


Getting Started

Follow these steps to start creating amazing worlds.

  1. Create a fresh Unity project using the correct Unity version (you can find the Unity download in the next step).
  2. Download & import the latest CCK Worlds at our download page.
  3. Once imported, right click in the project folder > Create > PoligonVR > P# Script.
  4. Attach the script to a GameObject.
  5. Start scripting!

Lets create a simple "Hello World" script.

using PVR.PSharp;
using UnityEngine;

public class HelloWorld : PSharpBehaviour
{
    void Start()
    {
        Debug.Log("Hello World!");
    }
}

Method Overrides

Method overrides allows your script to receive events, such as player join/leave.

Within the "PSharpBehaviour", we provide the following override methods:

Method OverrideDescription
OnPlayerJoined(PSharpPlayer player)Fires when a player joins the world
OnPlayerLeft(PSharpPlayer player)Fires when a player leaves the world
OnOwnershipTransfer(PSharpPlayer newOwner)Fires when the object owner is changed
OnDeserialization()Fires when synced variables are changed over the network
OnDeserialization(string[] changedVariables)Same as OnDeserialization(), but this includes the variable names that were changed
OnNetworkReady()Fires when the network is ready.
OnMasterChanged(PSharpPlayer newMaster)Fires when the instance master is changed.
OnPlayerAvatarChanged(PSharpPlayer player)Fires when a player changes their avatar.
OnInteract()Fires when the local player interacts/presses on or picks up the object. *Object requires a collider (can be set to trigger)
OnUseDown()Fires when the local player presses down the trigger/left mouse if its picked up.
OnUseUp()Fires when the local player releases the trigger/left mouse if its picked up.
OnRelease()Fires when the local player drops a pickup or releases an interact.
OnHighlightEnter()Fires when the object is highlighted.
OnHighlightExit()Fires when the object is un-highlighted.
OnPlayerTriggerEnter(PSharpPlayer player)Fires when a player enters a trigger.
OnPlayerTriggerStay(PSharpPlayer player)Fires when a player is in a trigger.
OnPlayerTriggerExit(PSharpPlayer player)Fires when a player exits a trigger.

Heres an example of receiving a players join/leave event

using PVR.PSharp;
using UnityEngine;

public class JoinLeaveExample : PSharpBehaviour
{
    public override void OnPlayerJoined(PSharpPlayer player)
    {
        Debug.Log($"{player.Username} has joined");
    }

    public override void OnPlayerLeft(PSharpPlayer player)
    {
        Debug.Log($"{player.Username} has left");
    }
}

PSharpPlayer

Instanced Properties

PropertyTypeDescriptionAccess
UsernameStringThe players nameRead Only
PlayerIDByteThe players network idRead Only
IsLocalBoolIs the player local?Read Only
IsMasterBoolIs the player the master?Read Only
IsInstanceCreatorBoolIs the player the instance creator?Read Only
UsingVRBoolIs the player using a VR headset?Read Only
AvatarHeightFloatReturns the users avatar height (returns 0 if the avatar is null)Read Only
IsNullBoolIs the PSharpPlayer instance null?Read Only

Instanced Methods

MethodReturn TypeDescription
GetPosition()Vector3The position of the player
GetRotation()QuaternionThe rotation of the player
GetEulerAngles()Vector3The euler angles of the player
GetBonePosition(HumanBodyBones bone)Vector3Get the bone position in world space
GetBoneRotation(HumanBodyBones bone)QuaternionGet the bone rotation in world space

Static Properties

PropertyTypeDescriptionAccess
PSharpPlayer.LocalPlayerPSharpPlayerGet the local playerRead Only
PSharpPlayer.PlayersPSharpPlayer[]Get all the players in the worldRead Only
PSharpPlayer.MasterPlayerPSharpPlayerGet the current master playerRead Only
PSharpPlayer.WalkSpeedFloatSets the walk speed of the local playerRead/Write
PSharpPlayer.RunSpeedFloatSets the run speed of the local playerRead/Write
PSharpPlayer.StrafeSpeedFloatSets the strafe speed of the local playerRead/Write
PSharpPlayer.JumpPowerFloatSets the jump power of the local playerRead/Write

Static Methods

MethodReturn TypeDescription
PSharpPlayer.TryGetPlayer(byte playerId, out PSharpPlayer player)BoolReturns true if it found a player and sets the "out" to the player
PSharpPlayer.Teleport(Vector3 position, float yAng)VoidTeleports the local player
PSharpPlayer.AddVelocity(Vector3 direction)VoidAdds velocity to the local player
PSharpPlayer.SetVelocity(Vector3 direction)VoidSets the velocity to the local player
PSharpPlayer.SendHapticEvent(PVRHand hand, float amplitude, float duration)voidVibrates the players controller (if they are in VR)
PSharpPlayer.SetLeftHandIK(Vector3 position, Quaternion rotation, float posWeight, float rotWeight)voidSets the avatars left hand IK target offset to a world position
PSharpPlayer.SetRightHandIK(Vector3 position, Quaternion rotation, float posWeight, float rotWeight)voidSets the avatars right hand IK target offset to a world position
PSharpPlayer.ResetLeftHandIK()voidResets the avatars left hand IK target
PSharpPlayer.ResetRightHandIK()voidResets the avatars right hand IK target
PSharpPlayer.GetLeftControllerPosition()Vector3Returns the left controller's world position
PSharpPlayer.GetLeftControllerForward()Vector3Returns the left controller's forward direction
PSharpPlayer.GetLeftControllerRotation()QuaternionReturns the left controller's rotation
PSharpPlayer.GetRightControllerPosition()Vector3Returns the right controller's world position
PSharpPlayer.GetRightControllerForward()Vector3Returns the right controller's forward direction
PSharpPlayer.GetRightControllerRotation()QuaternionReturns the right controller's rotation
PSharpPlayer.GetMainCameraPosition()Vector3Returns the head/main camera's world position
PSharpPlayer.GetMainCameraForward()Vector3Returns the head/main camera's forward direction
PSharpPlayer.GetMainCameraRotation()QuaternionReturns the head/main camera's rotation

Heres an example of teleporting the player to the GameObject when pressing 'F'

using PVR.PSharp;
using UnityEngine;

public class TeleportExample : PSharpBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            PSharpPlayer.Teleport(transform.position);
        }
    }
}

Prefs

PSharp Prefs is an easy way to save and preserve data on the users machine. This can range from settings to a users score for example.

MethodReturn TypeDescription
PSharpPrefs.Load()VoidLoads the current worlds prefs
PSharpPrefs.Save()VoidLoads the current worlds prefs
PSharpPrefs.Load(string worldIdOverwrite)VoidLoads the prefs from another world
PSharpPrefs.Save(string worldIdOverwrite)VoidLoads the prefs from another world
PSharpPrefs.GetFloat(string key, float defaultValue)FloatGets the float value from the given key
PSharpPrefs.GetInt(string key, int defaultValue)IntGets the int value from the given key
PSharpPrefs.GetBool(string key, bool defaultValue)BoolGets the bool value from the given key
PSharpPrefs.GetString(string key, string defaultValue)StringGets the string value from the given key
PSharpPrefs.SetFloat(string key, float defaultValue)VoidSets the float value from the given key
PSharpPrefs.SetInt(string key, int defaultValue)VoidSets the int value from the given key
PSharpPrefs.SetBool(string key, bool defaultValue)VoidSets the bool value from the given key
PSharpPrefs.SetString(string key, string defaultValue)VoidSets the string value from the given key

NOTE: The "worldIdOverwrite" is used to write/load save data from others worlds.
Keep in mind that you as the world author can only access/write data from other worlds that you have uploaded.

Heres an example of retrieving & saving a score value

using PVR.PSharp;
using UnityEngine;

public class PrefsExample : PSharpBehaviour
{
    private void Awake()
    {
        // We need to load the prefs for this world first
        PSharpPrefs.Load();

        // We retrieve the saved score value.
        // If it has not been set, it will default to 0.
        int score = PSharpPrefs.GetInt("score", 0);
        Debug.Log($"We currently have a score of {score}");

        // We increasse the score by 1
        score++;

        // We set the new score value
        PSharpPrefs.SetInt("score", score);

        // Save the prefs for this world
        PSharpPrefs.Save();
    }
}

Web

PSharp Web is an easy & secure way to send GET requests or retreive a Texture2D from the web.

MethodDescription
PSharpWeb.Get(string url, Action<WebCallback> callback)Sends a GET request to the target URL
PSharpWeb.GetTexture(string url, Action<Texture2D> callback)Downloads a texture from the web

NOTE: Keep in mind that PSharpWeb uses PVR_SecureURL which is enabled by default on the client.
The client has to enable "allow untrusted URL's" in their settings or trust the URL you are trying to contact.

Heres an example on how to send a GET request

using PVR.PSharp;
using UnityEngine;

public class WebRequestExample : PSharpBehaviour
{
    private void Awake()
    {
        PSharpWeb.Get("https://example.com", (callback) =>
        {
            //Response in text form
            Debug.Log(callback.text);

            //Status code
            Debug.Log(callback.code);
        });
    }
}

Utils

PSharpUtils is a helper class to make your life a little bit easier

MethodReturn TypeDescription
ArrayAdd<T>(ref T[] array, T item)VoidAdds a item to an array.
ArrayAddRange<T>(ref T[] array, T[] items)VoidAdds the items of another array to the array
ArrayInsert<T>(ref T[] array, int index, T item)VoidInserts an item at the given index
ArrayRemove<T>(ref T[] array, T item)VoidRemoves a specific item from an array
ArrayRemoveRange<T>(ref T[] array, int index, int count)VoidRemoves multiple items from an array
ArrayRemoveAt<T>(ref T[] array, T item)VoidRemoves a item from an array at the given index
ArrayContains<T>(T[] array, T item)BoolRemoves a item from an array at the given index
ArrayClear<T>(ref T[] array)VoidRemoves a item from an array at the given index

Networking

PSharps networking allows you to easily create script logic that is networked between players.

Most of the complex networking is automatically handled by P# itself. For example when a player leaves and they were the object owner, the master of the instance will automatically become the owner of that object. And if it was the master that left, a new master will be assigned and the object will be claimed by them.


Ownership

What is and why "ownership"? When you become the owner of an object, it lets your game client know that you are now responsible to sync this object with other players. This keeps the networking organized and not chaotic. Keep in mind that ownerships are based per GameObject and not the script instance itself.

Static Methods

MethodReturn TypeDescription
PSharpNetworking.SetOwner(PSharpPlayer player, GameObject gameObject)VoidSets the object owner of the GameObject
PSharpNetworking.IsOwner(PSharpPlayer player, GameObject gameObject)BoolReturns true if the specified player is the owner
PSharpNetworking.GetOwner(GameObject gameObject)PSharpPlayerReturns the current owner

The most optimized way to perform a owner check on the current object is by doing "IsObjectOwner".
This will return true if the local client is the owner.


Synced Variables

Syncing variables is probably the most crucial feature when it comes to PSharps networking.
You can choose if you want to manually synce the variable or have it automatically sync.

Synced variable example:

// Automatic sync
[PSharpSynced]
public float automaticSyncedFloat1;
// Or
[PSharpSynced(SyncType.Automatic)]
public float automaticSyncedFloat2;

// Manual sync mode
[PSharpSynced(SyncType.Manual)]
public float manualSyncedFloat;

// Automatic sync with a "OnValueChanged" callback
[PSharpSynced(SyncType.Automatic, nameof(OnValueChangedCallback))]
public float syncedFloatWithCallback;

Synced variable with callback example:

NOTES:
The "OnValueChanged" will execute even if you are the object owner or not.
The "OnValueChanged" will execute one frame later after its been set.

When the value is changed over the network, data loss can occur due to the network update rate.
An example would be a fast counter thats synced over the network. Only the "most updated value" will be called.

[PSharpSynced(SyncType.Automatic, nameof(OnScoreChanged))]
public int score;

// Executes when the score is changed
public void OnScoreChanged()
{
    Debug.Log($"New value: {score}");
}

The "Sync" method is included within the PSharpBehaviour. To sync a manually synced variable, you must do the following:

Sync("myVariableName");

In order for a client to change the value of a synced variable, they must be the object owner.
Check the Ownership documentation for more info.
When the value is changed over the network, OnDeserialization will be called.

Sync Type's

TypeDescription
SyncType.AutomaticAutomatically syncs if the value is changed.
SyncType.ManualRequires Sync("name") to sync with others.

Supported variable types

Type
string
string[]
char
char[]
float
float[]
double
double[]
sbyte
sbyte[]
byte
byte[]
short
short[]
ushort
ushort[]
int
int[]
uint
uint[]
long
long[]
ulong
ulong[]
bool
bool[]
Vector3
Quaternion

Events

NOTE: It's very important to mark your event methods with "[PSharpEvent]". This lets P# know that this method is expected to receive events, primarily for security reasons.

Events are used to directly invoke specific methods over the network.

Heres an example of sending an event to everyone

using PVR.PSharp;
using UnityEngine;

public class EventExample : PSharpBehaviour
{
    public override void OnInteract()
    {
        SendNetworkedEvent(NetworkEventTarget.All, nameof(DoSomething));
    }

    [PSharpEvent]
    public void DoSomething()
    {
        Debug.Log("Someone interacted with this object!");
    }
}

Heres an example of sending an event with parameters

NOTE: When sending parameters with an event, it is very important that the parameter count, parameter order and parameter types matches the target method.

using PVR.PSharp;
using UnityEngine;

public class EventParametersExample : PSharpBehaviour
{
    public override void OnInteract()
    {
        SendNetworkedEvent(NetworkEventTarget.All, nameof(DoSomething), "This is parameter 1", true, 3.14f);
    }

    [PSharpEvent]
    public void DoSomething(string stringValue, bool boolValue, float floatValue)
    {
        Debug.Log($"String: {stringValue} - Bool: {boolValue} - Float: {floatValue}");
    }
}

NetworkEventTarget's

TargetDescription
NetworkEventTarget.AllSends the event to everyone in the world
NetworkEventTarget.OwnerSends the event to the current object owner
NetworkEventTarget.LocalOnly invokes the event for the local client