The Bigger the Brighter

Example tutorial for creating a scalable XR object that brightens and LED the larger it gets.

What is needed

  • A VR-capable computer
  • Meta Quest 2
  • Adafruit Feather ESP32 V2 Board
  • Unity with Android (API 32 or lower) installed

Step by Step

Create Two Hand Grip Object

  • Complete Part 1 of the Connecting a VR headset and Microcontroller Instructable 
  • In the Hierarchy, add a 3D Object (a sphere). Scale and position the object so that it is within the player’s reach.
  • Add the component XR Grab Interactable and change the following:
    • Select Focus: Multiple
    • Focus Mode: Multiple
    • Use Dynamic Attach: Checked
  • In the Rigid Body component, turn off “Use Gravity” and increase “Drag” to 1000.
  • Add the component XR General Grab Transformer, and change the following:
    • Allow two hand scaling: Checked
    • Scale multiplier: 1
    • You can change the “Clamp Scaling: Min and Max” to whatever you like.

Debug the actual scale of the object

  • In your 3D object’s inspector, create a new script via add component named “changeScale”. Open the script by double clicking on the generated script file
  • Add to the “using” list at the top of your script:
using UnityEngine.XR.Interaction.Toolkit.Transformers;
  • Create two new class parameters (around line 8):
// variables declared outside functions are variables all 
//functions can access
private float minScale;
private float maxScale;
  • In the Start() function add the following:
// grab XR General Grab Transformer object and store in variable
XRGeneralGrabTransformer transformer = gameObject.<XRGeneralGrabTransformer>();
minScale = transformer.minimumScaleRatio * transform.localScale.x;
// use the XR General Grab Transformer’s minimum and maximum scale ratio to calculate the minimum and maximum scale values
maxScale = transformer.maximumScaleRatio * transform.localScale.x;
  •  Create a new function at the end of the class block (right before the last } ).
// function that calculates the scale change as a level brightness 
private void SendScalePeriodically(){
// The brightness of an LED ranges from 1 to 255
// Normalize the object’s scale as value between 1 and 255 
   int normalizedScale = (int)Mathf.Lerp(1f, 255f, Mathf.InverseLerp(minScale, maxScale, transform.localScale.x));

// send value to ESP32
   FindAnyObjectByType<ExampleCommunicator>().SendScale(normalizedScale);
}
  • Add this new function at the end of the Start() function 
// InvokeRepeating can call functions periodically during runtime
// 2f is a 2 second delay, 0.5f calls the function every 0.5 seconds
// if the light’s brightness does not change later in the tutorial, try changing 0.5f to 1f. Some setups need more time.
InvokeRepeating(“SendScalePeriodically”,2f,0.5f);
  • Save and return to Unity. Initially you will receive a compiling error (“SendScale” is missing from the ExampleCommunicator). To amend this, open the ExampleCommunicator script and add the function “SendScale” at the end of the class block.
// function that sends normalized scale value to ESP32 
private void SendScale(int scale){
// display text in unity build 
   _debugText.text = scale.ToString(); 
// messages to ESP32 must be a string value
// send scale value to ESP32
   mySingularityManager.sendMessage(scale.ToString(), myDevice);
}

Receive the scale on the ESP32

  • Open the “setup_esp32_simple_return.ino” Arduino code
  • At the end of void setup() add the following:
// print received message for debugging
// when running your unity build, click the magnifying glass in the top right corner of the Arduino window to open the Serial Monitor
// Make sure the Serial Monitor is set to 9600
Serial.begin(9600);

Add the following in void loop(), after “String data:

BTSerial.readStringUntil(‘\n’);”:
// .toInt() converts the string data into an integer value
// if the data value is NOT 0
if(data.toInt() != 0){
// store data in the scale variable
        int scale = data.toInt();
// analogWrite compared to digitalWrite, allows you to set a
// degree of brightness from 1 to 255
// write to builtin LED pin 13
  analogWrite(13, scale);
// print scale value for debugging
  Serial.println(scale);
}
  • Comment out the following lines in void loop() by adding “//” at the beginning of each line. You can comment out a group of lines at once by highlighting and pressing CTRL+/ or CMND+/
// digitalWrite(13, LOW);

AND

// if (data == "1"){
//   // the 1 turns on the LED on the board
//   digitalWrite(13, HIGH);
//   // this script sends back the following message if a 1 is received
//   BTSerial.println("LED Turned On!");
// }
  • This will change the brightness of the ESP32’s LED when the object is scaled.

Example tutorial by Tyler Beatty