- Home /
,How to store multiple Vector3s inside of a single variable every frame?
Hi all.
I am building an interactive VR experience using the HTC Vive and the SteamVR Unity plugin. My experience involves navigating a space filled with "Sound Spheres" that generate sound when colliding with the Vive controllers. These Sound Spheres are static i.e they sit still in space. I am attempting to write code that triggers haptic feedback when the controllers are held in the vicinity of a Sound Sphere. I am trying to accomplish this using a Vector3.Distance function that compares the location of each controller and Sound Sphere, every frame. When the distance is less than 0.4 units, haptics should be fired in the specific controller that is near a Sound Sphere at that moment in time.
I am running into issues when I attempt to compare the locations of every GameObject (controllers and Sound Spheres) every frame. How could I create a variable that contains the Vector3.transform.position of every controller, every frame? Concurrently, how could I create a variable that contains the Vector3.transform.position of every Sound Sphere, every frame?
My pseudo-code solution is here. This code at the moment does not run because I receive the error message "Cannot implicitly convert type 'UnityEngine.Vector3' to 'UnityEngine.Vector3[]'". Am I going in the right direction by trying to create an array of Vector3 values and them comparing them every frame? Or should I be trying a different approach? Your help would be greatly appreciated.
public class ControllerHaptics : MonoBehaviour {
SteamVR_TrackedObject trackedObject;
SteamVR_Controller.Device device;
[SerializeField] GameObject[] controllers;
[SerializeField] GameObject[] soundSpheres;
Vector3[] controllerPositions;
Vector3[] soundSpherePositions;
float distance;
// Use this for initialization
void Start()
{
trackedObject = GetComponent<SteamVR_TrackedObject>();
device = SteamVR_Controller.Input((int)trackedObject.index);
controllers = GameObject.FindGameObjectsWithTag("Controller"); //VR Controllers
soundSpheres = GameObject.FindGameObjectsWithTag("Grabbable"); //Sound Spheres
}
//Update is called once per frame
void Update()
{
GetControllerPositions();
GetSoundSpherePositions();
FireHapticsBasedOnDistance();
}
void GetControllerPositions()
{
for (int i = 0; i < controllers.Length; i++)
{
controllerPositions = controllers[i].transform.position;
}
}
void GetSoundSpherePositions()
{
for (int i = 0; i <soundSpheres.Length; i++)
{
soundSpherePositions = soundSpheres[i].transform.position;
}
}
void FireHapticsBasedOnDistance()
{
distance = Vector3.Distance(controllerPositions, soundSpherePositions);
if (distance < 0.4)
{
device.TriggerHapticPulse(500);
}
}
}
Answer by Captain_Pineapple · Jul 01, 2018 at 09:21 PM
Hey there, perhaps an update function like this might help you:
public void Update()
{
foreach(GameObject cont in controllers)
{
foreach(GameObject soundSp in soundSpheres)
{
if((cont.transform.position - soundSp.transform.position).magnitude < 0.4f)
{
//we have found something close to a controller:
device.TriggerHapticPulse(500);
break;
}
}
}
}
The question that bothers me here is: Does the haptic feedback get trigger per controller? Or can you also just trigger it on one controller? Because then you still have to differentiate between the cases of each controller beeing close to something.
Hope this helps. If you have any questions feel free to ask.
Wow! That's a much simpler way of getting the same functionality. Thanks for that. I still have a problem though, as you pointed out. The haptic feedback should get triggered only on the controller that is currently near the Sound Sphere. At the moment, if one controller is near a Sound Sphere then the haptics on both controllers are triggered. Do you have any idea on how I could differentiate between each controller? Interestingly enough, when the haptics are triggered inside of an OnCollisionEnter function using the same "device.TriggerHapticPulse" then the haptics are differentiated perfectly: only the controller that has collided with the Sound Sphere produces haptics.
Hey,
i'll just guess some things here: the script you are using now is attached to each controllers ingameobject? And the variable device is filled with the current controller handle?
Then the solution should be simple: Since you have an instance of the script on both controllers, each controller will also check if the other controller is close to something.
So simplifying the code to this might fix your problem:
public void Update()
{
foreach(GameObject soundSp in soundSpheres)
{
if((transform.position - soundSp.transform.position).magnitude < 0.4f)
{
//we have found something close to a controller:
device.TriggerHapticPulse(500);
break;
}
}
}
you might have to slightly modify it if my assumptions on the scripts locations are false...
Holy shit! This is such a simple solution and it is exactly the functionality I was looking for. Thank you very much!
This is my first time learning to program; it boggles my $$anonymous$$d that there are so many different ways to solve a problem like this: it's kind of shocking to see a working solution that has 3 lines of code compared to the giant mess I was trying to wade through.
I'm also just reflecting now on how I approached this problem from a super "top-down" perspective, convinced that I needed to gather and store every single position of every single game object in the scene and then compare those positions and then fire haptics. No wonder it quickly turned into a mess!
It seems like you started from a more "low-level" assumption of just needing the position of one controller and every sound sphere - and then comparing the vector length to fire haptics. I guess this style of thinking just comes with time and practice?
Your answer
Follow this Question
Related Questions
How do I make an array of vectors? 1 Answer
How can i get the index of an array[] as int? 0 Answers
Initialize Vector3 2 Dimensional Array 1 Answer
Read variable from txt to Vector3 1 Answer
Random.Range Vector3 2 Answers