How to Use VHL Interface Data in Custom Unity Scripts
This page describes how to use data from a Vortex VHL interface in a custom Unity script. This is a simply way to implement custom behavior or logic in Unity using data in a distributed Vortex simulation.
Overview
First of all, to manually create assets for the VHL Interface, a Unity project with the Vortex Integration Package is needed (such as VortexUnityTools or your own project).Â
For an overview of the assets workflow, refer to How to associate Vortex Objects with Unity prefabs. VHL Interface follows the same pattern as for other supported features:
- A prefab must be made and associated to a VHL Interface. They must share the same name.
- The prefab must have a component attached to it: the VortexVHL component.
- The prefab must be in an asset bundle. The asset bundle must have the same file name and path as the Vortex document (vxscene, mechanism, etc.) that contains the VHL interface.
Creating a Prefab for a VHL Interface
With the Vortex Studio Integration package installed, it is quite simple to create a prefab for a specific Vortex VHL interface. Here is a short guide:
- First, identify which VHL interface you want to access from Unity. This can be done by opening any Vortex file that supports VHL interfaces, such as mechanisms, assemblies, scenes and graphics galleries.
- Then, from the Unity Editor, create a new empty GameObject. This can be done by right-clicking the Hierarchy window and selecting Create Empty.
- Copy the name of your Vortex VHL instance, and set it as this new GameObject's name. This will be the root of your prefab.
- Add a VortexVHL component on this GameObject. This class allows to access VHL interface data from Unity.
- From there, the prefab's content and behavior is up to you, the user. Typically, a custom script is added to this GameObject, alongside VortexVHLÂ component. From the script, you can access any VHL input, output or parameter; as is described in the following section.
Using the VortexVHL Component in a Script
To use the data in a script, the prefab must contain a script component:Â it is in such a script that the VHL interface's data can be accessed. To do this, you first need to get a reference to the VortexVHL component. It is recommended to do this in the Start or Awake method, then re-use it as needed. From this reference, the following methods can be used to access the data from a VHL interface's field.
Return Data Type | Get Input Field Method | Get Output Field Method | Get Parameter Field Method | Additional Notes |
---|---|---|---|---|
bool | GetInputBool | GetOutputBool | GetParameterBool | |
int | GetInputInt | GetOutputInt | GetParameterInt | |
double | GetInputReal | GetOutputReal | GetParameterReal | |
string | GetInputString | GetOutputString | GetParameterString | |
UnityEngine.Vector2 | GetInputVector2 | GetOutputVector2 | GetParameterVector2 | Vortex Vector 2 of double values. |
UnityEngine.Vector3 | GetInputVector3 | GetOutputVector3 | GetParameterVector3 | Vortex Vector 3 of double values. |
UnityEngine.Vector3 | GetInputVector3AsPosition | GetOutputVector3AsPosition | GetParameterVector3AsPosition | Vector 3, assumed as position information. It is converted from Vortex to Unity coordinate system. |
UnityEngine.Vector4 | GetInputVector4 | GetOutputVector4 | GetParameterVector4 | Vortex Vector 4 of double values. |
UnityEngine.Color | GetInputColor | GetOutputColor | GetParameterColor | Vortex Color of float values |
UnityEngine.Matrix4x4 | GetInputMatrix | GetOutputMatrix | GetParameterMatrix | Vortex Matrix44 represented by Unity's Matrix4x4 type. No conversion is done whatsoever. |
Vortex.Types.PositionRotation | GetInputMatrixAsPositionRotation | GetOutputMatrixAsPositionRotation | GetParameterMatrixAsPositionRotation | Matrix4x4, interpreted as transform information into the PositionRotation class, which contains a position vector, rotation quaternion, and scale vector adapted from Vortex to Unity coordinate system. These can be used directly to assign to Unity Transform component's position, rotation and scale properties. |
string | GetInputExtensionName | GetOutputExtensionName | GetParameterExtensionName |
All these methods take the same argument: the string corresponding to the field name. When using these methods, if a field is not found, an error will appear in the log and the value returned will be a default value.
Please note that for your custom script to be tied to your asset bundle and usable with the default Vortex Unity application, you need to follow the process described in this guide:Â How to use custom scripts with Unity asset bundles.
VHL Interface Script Example
Here is an example of a script that uses a VHL interface to display some Vortex data in Unity.Â
using UnityEngine; using Vortex; public class DisplayVHLData : MonoBehaviour { private Vortex.VortexVHL vhl = null; public UnityEngine.UI.Text speedText = null; public UnityEngine.UI.Text distanceText = null; public UnityEngine.UI.Image engineImage = null; void Awake() { vhl = GetComponent<Vortex.VortexVHL>(); } void FixedUpdate() { if (speedText != null) { double speed = vhl.GetInputReal("Speed"); // Displays speed with 2 decimals format speedText.text = $"Current Speed: { speed.ToString("F2") }"; } if (engineImage != null) { bool engineOn = vhl.GetInputBool("Engine Active"); engineImage.enabled = engineOn; } if (distanceText != null) { double distance = vhl.GetOutputReal("Distance"); // Displays distance with 2 decimals format distanceText.text = $"Distance Moved: { distance.ToString("F2")}"; } } }
Here is how this script is attached to a prefab with the proper components and references to them:
And here is the VHL interface as defined in a mechanism in the Vortex Editor:
Once the asset bundle has been built and placed next to its corresponding mechanism, it can be loaded and the simulation can be started. The display will be added to the simulation and updated by the script.
.
Using VortexVHL dynamic fields
For ease of use, the VortexVHL component exposes dynamic fields. The member Inputs
, Outputs
and Parameters
are object extending C# System.Dynamic.DynamicObject
. For example, a VHL input property named "Velocity" can be access by writing vhl.Inputs.Velocity
. There is a few things to keep in mind while using this feature.
The dynamic fields are subject to the same limitations as C# DynamicObjectÂ
This means the properties can't be reserved words such asdouble
,return
,bool
, etc. This also means you can't use extension methods directly.// double myDouble = vhl.Inputs.double; // ERROR: double is a C# reserved keyword // Vector3 myPosition = vhl.Outputs.Position.MyExtensionMethod(); // ERROR: CS1973: Vector3<dynamic> has no applicable method named MyExtensionMethod() Vector3 myPosition = vhl.Outputs.Position; myPosition = myPosition.MyExtensionMethod(); // OK
- Property's names are case sensitive
- Non-alphanumeric characters are replaced with underscores
Vortex allows field's properties to contain character that can't be used to form valid C# identifiers such as space, parenthesis, punctuation to name a few. These properties can be access by replacing the non-alphanumeric values with underscores. For example, the VHL input property "Desired Velocity" can be access withvhl.Inputs.Desired_Velocity
, and the VHL output property "My output (5)" can be access withvhl.Outpus.My_output__5_
. Notice the double underscore betweenoutput
and5
: this is because the space and the opening parenthesis both account for one underscore. - Values are returned as raw values
Objects like Vector3 and Matrix4x4 are returned as raw values. A Vector3 representing a position in Vortex frame of reference would need to be converted to Unity referential withÂConversionUtilities.VortexToUnityVector
. Similarly, a Matrix4x4 transformation matrix in the Vortex frame of reference also needs to be converted withÂConversionUtilities.VortexToUnityPositionRotation
.
Dynamic Field Usage Example
The following figures shows a VHL interface configuration and a script sample demonstrating how to use the dynamic fields.
using UnityEngine; using Vortex; public class DynamicVHLData : MonoBehaviour { private Vortex.VortexVHL vhl = null; public bool myBool = false; public Color myColor = null; public string myString = null; void Awake() { vhl = GetComponent<Vortex.VortexVHL>(); } void FixedUpdate() { myBool = vhl.Inputs.isActive; // yields true myColor = vhl.Outputs.My_color; // yields a new UnityEngine.Color(1,1,1,1) myString = vhl.Parameters.Texture; // yields "default texture" } }