This guide builds upon part 1 which covers some basics of plugin building
In this guide we will touch on:
I'm not an advanced VaM scripter so this might not be the best, most efficient way to achieve my goal but serves as a learning exercise anyway and works well enough. Nevertheless, comment if there is a better way for those people just looking for a solution.
If you're not interested in learning about plugins or this implementation, just grab the plug-in from the download button at the top. (remove the .txt extension, drop it in VaM/Custom/scripts. In your scene add a new cube and attach this plugin to it.)
My Implementation
In another guide, I explain how to use Collision Triggers.
Once I have my cube specified in the CollisionTrigger filter, to be the atom that will kick-off an animation, my idea for the plugin was to have it update said cube's position, each frame, to be the same as the VR head position.
Additionally, on-load of the plugin I'd like to set the containing-atom (said cube) to be small and/or transparent.
Script
Side note: To figure out how to change an object property programmatically, you can;
Credit to MacGruber for the pointers on this
containingAtom // The atom you applied the plugin to)
GetStorableByID() // Find a storable to change using an ID. e.g. CubeMat or scale
?. // if GetStorableByID() doesn't find anything, it will return a Null, and Null does not contain a method called GetFloatJSONParam(). The ?. prevents an error in this case.
GetFloatJSONParam() // gets handle on the parameter within the storable that you want to tweak with code.
Armed with this knowledge, here is the script complete with handy comments.
Maybe you could take this and extend it. Add another 2 cubes one for each VR hand. Maybe you need to name your atoms so you can identify them in the plugin script? So that you can update the position of the appropriate cube to be the same as your hands.
tip (thanks again MacGruber):
Comment if you find any issues or would like more guides.
Cheers
In this guide we will touch on:
- VR controller positions
- Use script to change atom scale, position, alpha (and any other changeable property)
- Collision triggers (to trigger an animation)
I'm not an advanced VaM scripter so this might not be the best, most efficient way to achieve my goal but serves as a learning exercise anyway and works well enough. Nevertheless, comment if there is a better way for those people just looking for a solution.
If you're not interested in learning about plugins or this implementation, just grab the plug-in from the download button at the top. (remove the .txt extension, drop it in VaM/Custom/scripts. In your scene add a new cube and attach this plugin to it.)
My Implementation
In another guide, I explain how to use Collision Triggers.
Once I have my cube specified in the CollisionTrigger filter, to be the atom that will kick-off an animation, my idea for the plugin was to have it update said cube's position, each frame, to be the same as the VR head position.
Additionally, on-load of the plugin I'd like to set the containing-atom (said cube) to be small and/or transparent.
Script
Side note: To figure out how to change an object property programmatically, you can;
- Create an empty scene, add a cube, tweak knobs and dials and save.
- In the saved scene files, you will find a json file with a reference to the properties that have been changed. Something like this:
JavaScript:
{
"id" : "Cube",
"on" : "true",
"type" : "Cube",
...
"storables" : [
{
"id" : "CubeMat",
"Alpha Adjust" : "-0.998"
},
{
"id" : "scale",
"scale" : "0.03"
},
...
]
...
}
- In your plugin, use these methods to get a handle on the storable and change it - observe the correlation with the JSON (CubeMat and Alpha Adjust):
C#:
JSONStorableFloat jsonAlpha = containingAtom.GetStorableByID("CubeMat")?.GetFloatJSONParam("Alpha Adjust");
if (jsonAlpha != null) jsonAlpha.val = -0.998f;
containingAtom // The atom you applied the plugin to)
GetStorableByID() // Find a storable to change using an ID. e.g. CubeMat or scale
?. // if GetStorableByID() doesn't find anything, it will return a Null, and Null does not contain a method called GetFloatJSONParam(). The ?. prevents an error in this case.
GetFloatJSONParam() // gets handle on the parameter within the storable that you want to tweak with code.
Armed with this knowledge, here is the script complete with handy comments.
C#:
using System;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading.Tasks; // VaM throws an error when this is left included. Not needed?
namespace NoButYeaNS
{
class NBYControllerCollision2: MVRScript
{
private float nextActionTime = 0.0f; // just for logging every 10 seconds or so - avoid logs every frame
public float period = 10; // log interval - number of seconds
public override void Init()
{
pluginLabelJSON.val = "Controller Collision";
}
// Runs once when plugin loads - after Init()
protected void Start()
{
// check we have applied to a cube or sphere only
if(!(containingAtom?.type == "Cube" || containingAtom?.type == "Sphere"))
{
SuperController.LogMessage("Add plugin to Cube or Sphere only");
return;
}
// show a message
SuperController.LogMessage(pluginLabelJSON.val + " Loaded");
// change scale
JSONStorableFloat jsonScale = containingAtom.GetStorableByID("scale")?.GetFloatJSONParam("scale");
if(jsonScale != null) jsonScale.val = 0.03f;
// turn phyisics off - prevents the atom getting stuck when walking through walls etc.
JSONStorableBool jsonPhysicsEnabled = containingAtom.GetStorableByID("control")?.GetBoolJSONParam("physicsEnabled");
if (jsonPhysicsEnabled != null) jsonPhysicsEnabled.val = false;
// make semi transparrent here
string matName = (containingAtom?.type == "Cube") ? "CubeMat" :"SphereMat"; // for a Sphere, the material name is different
JSONStorableFloat jsonAlpha = containingAtom.GetStorableByID(matName)?.GetFloatJSONParam("Alpha Adjust");
if (jsonAlpha != null) jsonAlpha.val = -0.998f;
// SuperController.LogMessage("Atom name: " + containingAtom.name);
// SuperController.LogMessage("Atom type: " + containingAtom.type);
}
// A Unity thing - runs every physics cycle
public void FixedUpdate()
{
// put code here
}
// Unity thing - runs every rendered frame
public void Update()
{
// each frame, copy the camera position and rotation accross to the containing atom
containingAtom.mainController.transform.position = CameraTarget.centerTarget.transform.position + new Vector3(0f, 0.05f, 0f);
containingAtom.mainController.transform.rotation = CameraTarget.centerTarget.transform.rotation;
// debug info... just prints position data every 10 seconds - left in for reference.
/*
if(Time.time > nextActionTime)
{
nextActionTime = Time.time + period;
SuperController.LogMessage(
"atom pos:" + containingAtom.mainController.transform.position.ToString() +
":: cam pos:" + CameraTarget.centerTarget.transform.position.ToString() +
":: type: " + containingAtom?.type
);
}
*/
}
}
}
Maybe you could take this and extend it. Add another 2 cubes one for each VR hand. Maybe you need to name your atoms so you can identify them in the plugin script? So that you can update the position of the appropriate cube to be the same as your hands.
tip (thanks again MacGruber):
- SuperController.singleton.leftHand
- SuperController.singleton.rightHand
Comment if you find any issues or would like more guides.
Cheers