Unity Package Getting Started Guide
Unity Version: 2020.3.27f1
Supported ICD Rev: H1
Supported VictoR Firmware Revision:
Application Firmware Rev: 03.080
Co-Processor Firmware Rev: 01.001
Kernel Module Firmware Rev: 01.001
BLE Firmware Rev: 03.032
Supported Build Types:
Universal Windows Platform
Android
NOTE: As a result of using the Windows BLE stack, Unity projects built with the VictoR SDK can only be run on the target platform during development. Running the application within the editor is currently not supported.
Introduction
To enable development for the VictoR device in the Unity engine, a Unity package is available which contains the relevant Android and Windows libraries used to communicate with a VictoR device, along with example C# scripts and Unity gameobjects and example scene that demonstrate one of many ways users could incorporate the VictoR SDK into their Unity project. The following will walk users through importing the Unity package into their project and give a general overview of the provided scripts, gameobjects, and example scene.
Importing the VictoR SDK Unity Package
The VictoR SDK Unity package is of .unitypackage file type. Users can import this package into an existing Unity project by navigating to Assets/Import Package/Custom Package:
Once the Unity package has been imported, users should have a set of new assets available in their project’s Assets folder. This should include:
A plugins folder containing the necessary libraries to build either a UWP application or an Android application
Prefabs for a basic UI to allow for…
Scanning for VictoR devices over USB or BLE
Connecting to scanned devices
Reading the Device Configuration and Device Information service on the device
Writing to the Device Configuration service
Disconnecting from connected VictoR devices
Scripts utilizing the Windows and Android VictoR SDK, along with prefabs using said scripts
An example scene bringing the above items together for a buildable UWP or Android application
Prefabs and Scripts
The prefabs for the example project can be split between two spaces: UI and VictoR SDK.
VictoR SDK Prefabs
The VictoR SDK prefab makes use of the libraries contained in the Plugins folder to communicate with a VictoR device, through the attached VictorController script. The libraries used are determined by the platform the project has been set to. Currently, Universal Windows platform and Android are supported. The VictorController script also serves as both an example on how to use the Victor SDK for both platforms and is the primary script users should utilize when interfacing with the VictoR device from within a Unity project. It’s primary function is to use the appropriate device manager (Windows or Android SDK), dependent on the platform the application is running on. Once the appropriate device manager is instantiated, calls to Scan, Connect, Read/Write, and Subscribe/Unsubscribe can be made through the VictorController. The following will walk through how the Windows and Android DeviceManagers are handled through a Unity project.
UWP
When building a project for UWP, the VictorSDK classes can be used directly to communicate with VictoR devices. As a result, the VictorController script simply uses these classes directly. Users can reference the Victor SDK Getting Started Guide for Windows for example code on how to work with the Windows edition of the SDK.
Android
When building a project for Android, the VictorSDK for Android requires an additional layer of bindings in order to interface with the SDK in C#. The VictorAndroidDeviceManager script under the Scripts folder provides these bindings and is what users should leverage when making calls to the Android SDK. The example code below simply gives users a look into how these bindings are done. The core of this layer resides in Unity’s AndroidJNIModule in the UnityEngine library. This allows for using android java objects and making calls on said objects. The following demonstrates how these calls are made as they relate to the VictoR SDK:
Scanning For Devices
In order to scan for devices using the Android SDK from within a Unity project, users must first create an AndroidJavaObject representing the Java SDK’s VictorBleDeviceManager. In the example script, this is done inside the constructor. Once the device manager object has been created, the actual scan method is able to use the AndroidJavaObject to call the “scanForDevices” method. As this is a CompletableFuture on the Java side, this call is made inside of a Task on the C# side. An important item to note is that in order to properly call this function, users must first attach the current thread to a Java VM. Remember that the Unity package contains a VictorAndroidDeviceManager script that has performed this binding already for the user.
public class VictorAndroidDeviceManager : IVictorDeviceManager
{
AndroidJavaClass m_AJCUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject m_AJOActivity;
AndroidJavaObject m_AJODeviceManager;
public VictorAndroidDeviceManager(bool useUSB)
{
m_AJCUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
m_AJOActivity = m_AJCUnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
string classNamePrefix = "com.fn.victorcommunications.";
string className;
if (useUSB)
{
className = "VictorUsbDeviceManager";
}
else
{
className = "VictorBleDeviceManager";
}
m_AJODeviceManager = new AndroidJavaObject(classNamePrefix + className, m_AJOActivity);
m_useUSB = useUSB;
}
public async Task<HashSet<VictorDeviceInfo>> ScanForDevices()
{
AndroidJavaObject ajoScannedDevices = await Task<AndroidJavaObject>.Run(() =>
{
AndroidJNI.AttachCurrentThread();
AndroidJavaObject ajo = m_AJODeviceManager.Call<AndroidJavaObject>("scanForDevices");
return ajo.Call<AndroidJavaObject>("get");
});
return ToHashSet(ajoScannedDevices);
}
}
Now that this function has been defined for an Android project, users can then call this scan function directly in their project’s code
public async Task Scan(int scan)
{
VictorDeviceScanParameters scanParameters = new VictorDeviceScanParameters();
scanParameters.ScanTime = scan;
scanParameters.DeviceName = "victor";
scanParameters.CaseSensitive = false;
var result = await m_deviceManager.ScanForDevices(scanParameters);
}
Connecting To A Device
Connecting to a device follows a similar pattern as scanning for devices. A binding to the Android SDK must first be defined to call the connect method. This is already defined in the VictorAndroidDeviceManager script
public async Task<bool> Connect(string deviceAddress)
{
return await Task<bool>.Run(() =>
{
AndroidJNI.AttachCurrentThread();
AndroidJavaObject ajo = m_AJODeviceManager.Call<AndroidJavaObject>("connect", deviceAddress);
return ajo.Call<AndroidJavaObject>("get").Call<bool>("booleanValue");
});
}
The most important item of note here is the return of the function. The Android SDK’s Connect method returns a Boolean wrapped in a CompletableFuture.
In order to retrieve this return in the java binding, it is important to call the CompletableFuture’s “get” method to retrieve the return value, as well as the “booleanValue” method of the Java side Boolean to retrieve the underlying bool. Now that this function has been defined in our Unity project, we can simply call the Connect function on our VictorAndroidBLEDeviceManager object.
Callbacks
Callbacks when using the Android SDK requires not only a binding to the underlying Java call, but also defining the Callback abstract class in the Android SDK. Once again, the VictorAndroidDeviceManager provides an implementation for how both of these. First, the VictorDeviceCallback in the Android SDK is defined on the C# side. In the provided example, the VictorEventHandler and VictorEventHandlerMap in the Windows SDK is leveraged to manage passed in events.
Now that this callback has been defined, this object can be passed to the Android SDK’s version of the Subscribe and Unsubscribe functions.
With both items defined, users can create their own Event to pass to the VictorAndroidDeviceManager to be notified of attribute changes (for attributes that have the Notify flag enabled), connection state events, and device found events. It is important to remember that these callbacks will occur in a separate thread and should be especially noted if working on Unity Gameobjects that rely on these callbacks for modifications, as many operations on Unity Gameobjects can only be done on the main thread.
UI Prefabs
The UI prefab consists of a collection of controls that allow for scanning for devices, connecting/disconnecting to/from the device, and reading/writing to the device. Additionally, a Log prefab is used by the VictorUIManager script to print out a number of informational, warning, and error logs in the scroll view of the UI. Any reads made on the device will be printed out in the scroll view, as well as notifications of the state of a scan, connect, or disconnect call. One item of note is the USB toggle. If users wish to scan/connect to devices over USB, please ensure that the USB toggle has been turned on.
Building The Unity Project
Windows
Latest Windows SDK Supported: 10.1.19041.685
Below lists the settings used to build and run a UWP project in Unity when using the Victor SDK package.
NOTE: When attempting to build an app that intends to communicate with the device over USB, it is important that permissions for accessing serial devices has been added to the .appxmanifest for the resulting UWP build. Subsequent builds in the same folder will not overwrite this entry, however it is important to keep this in mind for any fresh builds. The best workflow for UWP builds is to perform an initial build and modify the .appxmanifest in the project’s build folder before running the application for the first time.
Android
Latest Android SDK Supported: 32
Below lists the settings used to build and run a an Android project in Unity when using the Victor SDK package. It is important to note that a device plugged into the development machine has been detected and will be the target device the application runs on once the build succeeds and deploys to the device.