Skip to content

Commit

Permalink
Smart Contract Sample (#27)
Browse files Browse the repository at this point in the history
* Smart Contract Integration

* Move 2D input to event driven architecture

* Add Blockchain Example
  • Loading branch information
vmohan7 authored Oct 4, 2021
1 parent 90984ed commit c699fef
Show file tree
Hide file tree
Showing 17 changed files with 4,825 additions and 49 deletions.
Binary file added Images~/blockchain.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 74 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

This SDK package is built based on [Unity Render Streaming](https://docs.unity3d.com/Packages/[email protected]/manual/index.html) and [Unity WebRTC](https://docs.unity3d.com/Packages/[email protected]/manual/index.html). By using this package, you can stream any Unity scene from the the Unity Editor or a Standalone build to a WebXR client on the FusedVR Website : [https://fusedvr.com/rendering](https://fusedvr.com/rendering). To try this this package, it is as simple as dragging the included **Render Streaming Services** prefab into your Unity scene that you would like to stream and setting up the connect to the WebRTC server.

For an overview of this package, please refer to this video tutorial on the FusedVR Youtube Channel: [Streaming Your First WebXR Unity Game to Oculus Quest](https://youtu.be/di18sWRlbFs)
For an overview of this package, please refer to this video tutorial on the FusedVR Youtube Channel: [Streaming Your First WebXR Unity Game to Oculus Quest](https://www.youtube.com/watch?v=di18sWRlbFs&list=PLihwab7Zw-Ky7nE47-QZopD3TneZlsiP4&index=9)

[![CloudXR WebXR Hello World](https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/hello-world.jpg)](https://youtu.be/di18sWRlbFs)
<p align="center">
<a href="https://www.youtube.com/watch?v=di18sWRlbFs&list=PLihwab7Zw-Ky7nE47-QZopD3TneZlsiP4&index=9"><img src="https://i.ytimg.com/vi/di18sWRlbFs/maxresdefault.jpg" /> </a>
<br />
How To Setup CloudXR to WebXR
</p>

# Setup

Expand Down Expand Up @@ -38,18 +42,78 @@ On the **Render Streaming Service** Game Object, there are a few configuration o
<img src="https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/render-streaming-service.png" />
<br />
VR Broadcast Component
</p>

# Samples

Provided with the package are several samples to help with quick testing the SDK : **HDRP**, **VRTK Integration** , **Asymmetrical Multiplayer** , **Blockchain Testing**. These samples can be imported via the Package Manager once you have imported the SDK into your Unity project.

## High Definition Render Pipeline

The first one uses the Unity HDRP Built In Template to show case streaming a scene with the [High Definition Render Pipeline](https://docs.unity3d.com/Packages/[email protected]/manual/index.html) into WebXR. This is one of the very few ways to play a HDRP game / app within Oculus Quest / WebXR. In order to utilize this sample, import the High Definition RP package from the Unity registry.

#### Watch how to setup the project on [Youtube](https://youtu.be/yXta-2aHH18)

<p align="center">
<a href="https://youtu.be/yXta-2aHH18"><img src="https://i.ytimg.com/vi/yXta-2aHH18/maxresdefault.jpg" /> </a>
<br />
HDRP Streaming
</p>

## VRTK Input Integration

The second provided sample shows integration with [VRTK](https://www.vrtk.io/) to showcase how to utilize the input that is streamed from the WebXR client into Unity. Using this input, we can build an Archery Sandbox. Simply pick up the bow and then grab arrows from behind your back to begin shooting. Please note that to you use this sample you will need to manually also import the following [VRTK Tilia Packages](https://www.vrtk.io/tilia.html):

- **io.extendreality.tilia.camerarigs.trackedalias.unity**
- **io.extendreality.tilia.interactions.interactables.unity**
- **io.extendreality.tilia.interactions.snapzone.unity**

#### Watch how to setup the project on [Youtube](https://youtu.be/Bc__t2MLarc)

<p align="center">
<a href="https://youtu.be/Bc__t2MLarc"><img src="https://i.ytimg.com/vi/Bc__t2MLarc/maxresdefault.jpg" /> </a>
<br />
VRTK Bow & Arrow
</p>

## Asymmetrical Multiplayer

The third provided sample shows an example of creating a asymmetrical multiplayer experience, where up to 4 users can enter the application either in VR or in 2D as a laptop or mobile user to view an apartment. VR users will be able to teleport around using the enabled [VRTK](https://www.vrtk.io/) integration. Please note that to you use this sample you will need to manually also import the following [VRTK Tilia Packages](https://www.vrtk.io/tilia.html):

- **io.extendreality.tilia.locomotors.teleporter.unity**
- **io.extendreality.tilia.indicators.objectpointers.unity**

![Apartment](https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/apartment.png)

## Blockchain Testing

The forth sample shows an example of interacting with the Blockchain. This sample shows you how to use each feature of the Blockchain interaction highlighted above. Due to documented UI issues with Unity Render Streaming, this sample is a bit unstable to setup. If you are testing within Unity, please make sure the Game View is selected; otherwise input will fail to be recognized by the Editor Canvas. If you are running into trouble, please follow this [README](https://github.com/Unity-Technologies/UnityRenderStreaming/blob/develop/com.unity.renderstreaming/Documentation~/browser_input.md) guide from Render Streaming in order to setup browser input. There is also a work around script (RemoteInput.cs) that has been implemented to avoid the bug caused in this [issue](https://github.com/Unity-Technologies/UnityRenderStreaming/issues/542).

#### Some recommendations
- **In Project Setting->Player->Other Setting, check Allow 'unsafe' code**
- **For UnityEditor, Open Window->Analysis->Input Debugger and turn on Lock Input to Game View in Options**

![Blockchain UI](https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/blockchain.png)

# Camera Eye Resolution

At this time, the WebXR Client sends the resolution required to render per eye based on the connected VR device to Unity in order to adapt the resolution that is sent. However, IPD data is not sent and is hard-coded to a standard default IPD of 64mm. If you would like to adjust the resolution yourself, you may change the [VRInputManager](https://github.com/FusedVR/VRStreaming/blob/master/Runtime/Scripts/VRInputManager.cs) and change the code related to the VRDataType.Display.

# Cloud Support

This project has been tested to work on AWS EC2 leveraging Nvidia's Gaming AMIs. See the following videos for documentation on how to setup your Unity VR Streaming project and get it deployed on the Cloud.
This project has been tested to work on AWS EC2 leveraging Nvidia's Gaming AMIs. See the following videos for documentation on how to setup your Unity VR Streaming project and get it deployed on the Cloud : [**Windows**](https://youtu.be/UFsbQ8YlboU) / [**Linux**](https://youtu.be/3p0tzqD-s-c)

- Windows Server with Tesla T4 GPU Accelerated Graphics : https://youtu.be/UFsbQ8YlboU
- Ubuntu 18.04 with Tesla T4 GPU Accelerated Graphics : https://youtu.be/3p0tzqD-s-c
<p align="center">
<a href="https://youtu.be/UFsbQ8YlboU"><img src="https://i.ytimg.com/vi/UFsbQ8YlboU/maxresdefault.jpg" /> </a>
<br />
Windows Server with Tesla T4 GPU Accelerated Graphics
</p>

<p align="center">
<a href="https://youtu.be/3p0tzqD-s-c"><img src="https://i.ytimg.com/vi/3p0tzqD-s-c/maxresdefault.jpg" /> </a>
<br />
Ubuntu 18.04 with Tesla T4 GPU Accelerated Graphics
</p>

# GPU Recommendations

Expand Down Expand Up @@ -84,41 +148,21 @@ In order to support decentralized payments, the SDK now supports the ability to
- **GetAccount()** : returns the currently active Blockchain account
- **Signature(string message)** : returns the signed hash of the input message
- **SendTransaction(string to, string value)** : returns the transaction hash for the ethereum transaction that will send *value* ethereum to the *to* address from the active web wallet account
- **RegisterContract(string contractAddres , string abi)** : registers the smart contract address with an associated abi on the clients. This enables the client to make calls to the Smart Contract instead of the server bundling the request into the data field of the SendTransaction
- **RunTransaction(string contractAddress, string functionName, string[] args)** : runs the smart contract transaction on the client. If it is a read-only transaction, the client will return the value from the blockchain i.e. name / symbol. if the function requires writting to the blockchain, then the client will return a transaction hash.

Once any of these methods has been called, the data will be sent over each Client's Data Channel to be processed on the client. If the Client supports the Web Wallet, then the message will be processed and returned back to the server. From Unity, you can listen from the return values on the BlockchainData.CryptoEvent event handler, which will return the event name and the result depending on which method was called.
Once any of these methods has been called, the data will be sent over each Client's Data Channel to be processed on the client. If the Client supports the Web Wallet, then the message will be processed and returned back to the server. From Unity, you can listen from the return values on the **BlockchainData.CryptoEvent** event handler, which will return the event name and the result depending on which method was called. Please refer to the Blockchain Testing sample above for instructions on how to use the functionality.

## How To Use
## How To Use Blockchain Support

The most common scenario where this can be integrated is when a VR device like Oculus Quest **NOT** support Blockchain integration and would like to have a secondary device (i.e. smart phone) to be paired with the headset in order to authorize payments. A user could simply connect both the VR headset and phone to the same server and the headset would be responsible for displaying VR, while the phone / computer would be responsible for authorizing any payments using Metamask.

To implement this, you will need to :

- Increase the number of clients that can connect to the server from 1 to 2.
- If desired, create a specific CLientStreamer prefab dedicated for Blockchain support and assign that prefab to the **VRBroadcast**. If unchanged, the video stream will be passed through, which may or may not be desired.
- If desired, create a specific ClientStreamer prefab dedicated for Blockchain support and assign that prefab to the **VRBroadcast**. If unchanged, the video stream will be passed through, which may or may not be desired.

## More Blockchain Requests?

Please file [Github feature request issues](https://github.com/FusedVR/VRStreaming/issues) for additional methods and web wallet support that you would like to see implemented on clients.

# Samples

Provided with the package are two samples to help with quick testing the SDK : **HDRP & VRTK**. Both these samples can be imported via the Package Manager once you have imported the SDK into your Unity project.

The first one uses the Unity HDRP Built In Template to show case streaming a scene with the [High Definition Render Pipeline](https://docs.unity3d.com/Packages/[email protected]/manual/index.html) into WebXR. This one of the very few ways to play a HDRP game / app within Oculus Quest / WebXR. In order to utilize this sample, import the High Definition RP package from the Unity registry.

![High Definition Render Pipeline](https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/hdrpvr.png)

The second provided sample shows integration with [VRTK](https://www.vrtk.io/) to showcase how to utilize the input that is streamed from the WebXR client into Unity. Using this input, we can build an Archery Sandbox. Simply pick up the bow and then grab arrows from behind your back to begin shooting. Please note that to you use this sample you will need to manually also import the following [VRTK Tilia Packages](https://www.vrtk.io/tilia.html):

- **io.extendreality.tilia.camerarigs.trackedalias.unity**
- **io.extendreality.tilia.interactions.interactables.unity**
- **io.extendreality.tilia.interactions.snapzone.unity**

![VRTK Archery](https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/archery-sample.png)

The third provided sample shows an example of creating a asymmetrical multiplayer experience, where up to 4 users can enter the application either in VR or in 2D as a laptop or mobile user to view an apartment. VR users will be able to teleport around using the enabled [VRTK](https://www.vrtk.io/) integration. Please note that to you use this sample you will need to manually also import the following [VRTK Tilia Packages](https://www.vrtk.io/tilia.html):

- **io.extendreality.tilia.locomotors.teleporter.unity**
- **io.extendreality.tilia.indicators.objectpointers.unity**

![Apartment](https://raw.githubusercontent.com/FusedVR/VRStreaming/master/Images~/apartment.png)
29 changes: 28 additions & 1 deletion Runtime/Scripts/BlockchainData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static class BlockchainData
/// Enums for the Block Chain Data Events. Use DataEvent.ToString() to convert to event name
/// </summary>
public enum DataEvents {
account, sign, sendTx
account, sign, sendTx, setContract, runContract
}
#endregion

Expand Down Expand Up @@ -55,6 +55,33 @@ public static void SendTransaction(string to, string value) {
SendEvent( DataEvents.sendTx, JsonConvert.SerializeObject(payload) );
}

/// <summary>
/// Sends a transaction to register the contract with the client based on the address and abi
/// This contract once registered can then be called while the client is connected
/// </summary>
public static void RegisterContract(string contractAddress, string abi) {
Dictionary<string, string> payload = new Dictionary<string, string> {
["addr"] = contractAddress,
["abi"] = abi
};

SendEvent(DataEvents.setContract, JsonConvert.SerializeObject(payload));
}

/// <summary>
/// Run a smart contract that has already been Registered With the Client
/// Pass the relevant function name and arguments
/// </summary>
public static void RunTransaction(string contractAddress, string functionName, string[] args) {
Dictionary<string, object> payload = new Dictionary<string, object> {
["addr"] = contractAddress,
["fn"] = functionName,
["args"] = args
};

SendEvent(DataEvents.runContract, JsonConvert.SerializeObject(payload));
}

/// <summary>
/// Generic Send Event method that works with the Broadcaster to send the message over the data channel
/// </summary>
Expand Down
36 changes: 28 additions & 8 deletions Runtime/Scripts/CameraControls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class CameraControls : MonoBehaviour {
public float shiftAdd = 25.0f; // Amount to accelerate when shift is pressed
public float maxShift = 100.0f; // Maximum speed when holding shift
public float camSens = 0.15f; // Mouse sensitivity

public VRInputManager inputManager;
#endregion

#region Private Properties
Expand All @@ -28,9 +30,19 @@ public class CameraControls : MonoBehaviour {
#endregion

#region Public Methods
private void Start() {
inputManager.onDeviceChange += OnDeviceChange;
}

private void OnDeviceChange(InputDevice device, InputDeviceChange change) {
if (change == InputDeviceChange.Added)
AddDevice(device);
else if (change == InputDeviceChange.Removed)
RemoveDevice(device);
}

/// <summary>
/// Add a Unity Input Device (Mouse, Touch, Keyboard) to this controller to be used for Camera Controls
/// Used in the VR Input Manager to assign devices
/// </summary>
public void AddDevice(InputDevice device) {
switch (device) {
Expand All @@ -49,14 +61,22 @@ public void AddDevice(InputDevice device) {
}

/// <summary>
/// Reset and Remove all Devices that have prior assigned
/// Used in the VR Input Manager to remove devices for the camera control on disconnect
/// Remove the Specified Device (Mouse, Touch, Keyboard) from the controls
/// </summary>
public void RemoveDevices() {
myMouse = null;
myKeyboard = null;
myTouch = null;
lastPointer = null;
public void RemoveDevice(InputDevice device) {
switch (device) {
case Mouse mouse:
myMouse = null;
lastPointer = null;
break;
case Keyboard keyboard:
myKeyboard = null;
break;
case Touchscreen touch:
myTouch = null;
lastPointer = null;
break;
}
}
#endregion

Expand Down
19 changes: 19 additions & 0 deletions Runtime/Scripts/ClientStreams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace FusedVR.VRStreaming {
/// </summary>
public class ClientStreams : MonoBehaviour
{
#region Variables
/// <summary>
/// Data Channel for the client
/// </summary>
Expand All @@ -35,6 +36,24 @@ public class ClientStreams : MonoBehaviour
/// Connection ID for client
/// </summary>
private string myConnection;
#endregion

#region Events
/// <summary>
/// Static events for when a client joins or leaves
/// </summary>
public delegate void OnClientStream(ClientStreams player);
public static OnClientStream OnClientAdded;
public static OnClientStream OnClientLeft;

private void OnEnable() {
OnClientAdded?.Invoke(this);
}

private void OnDisable() {
OnClientLeft?.Invoke(this);
}
#endregion

/// <summary>
/// Set the connection based on the signalling data from the client on an Offer
Expand Down
17 changes: 13 additions & 4 deletions Runtime/Scripts/VRInputManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Unity.WebRTC;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;

namespace FusedVR.VRStreaming {
/// <summary>
Expand Down Expand Up @@ -119,28 +120,36 @@ public class VRPoseData : UnityEvent<Source, Vector3, Quaternion> {
/// </summary>
public delegate void OnCryptoData(BlockchainData.DataEvents evt, string result);
public static OnCryptoData CryptoEvent;

public event Action<InputDevice, InputDeviceChange> onDeviceChange;
#endregion

#region Methods

private void Awake() {
if (enableKeyboardTouchControls) {
camControls = gameObject.AddComponent<CameraControls>();
camControls.inputManager = this;
}
}

public override void SetChannel(string connectionId, RTCDataChannel channel) {
if (channel == null) {
if (remoteInput != null) {
remoteInput.Dispose();
camControls.RemoveDevices();

onDeviceChange?.Invoke(remoteInput.RemoteKeyboard, InputDeviceChange.Removed);
onDeviceChange?.Invoke(remoteInput.RemoteMouse, InputDeviceChange.Removed);
onDeviceChange?.Invoke(remoteInput.RemoteTouchscreen, InputDeviceChange.Removed);

remoteInput = null;
}
} else {
remoteInput = RemoteInputReceiver.Create();
camControls.AddDevice(remoteInput.RemoteKeyboard);
camControls.AddDevice(remoteInput.RemoteMouse);
camControls.AddDevice(remoteInput.RemoteTouchscreen);
onDeviceChange?.Invoke(remoteInput.RemoteKeyboard , InputDeviceChange.Added);
onDeviceChange?.Invoke(remoteInput.RemoteMouse, InputDeviceChange.Added);
onDeviceChange?.Invoke(remoteInput.RemoteTouchscreen, InputDeviceChange.Added);

channel.OnMessage += remoteInput.ProcessInput;
}

Expand Down
Loading

0 comments on commit c699fef

Please sign in to comment.