Music Visualizer to Display inside of GUI

What is the best way to get spectrum data or music visualizer to display inside of a custom GUI created in Photoshop and imported as a sprite on a UI canvas or panel?
One way I did it and I’m sure it’s the wrong way, was to line the camera with the canvas attached and get the music visualizer which was a 3d scene with objects set to a C# script that animates the objects to the music, tweak it into position so the music visualizer could be seen inside of my GUI cutout window I had made for it. I keep thinking there must be a more proper way to do this. I’m Trying to do a little research to see if I can help my code guy out who is new to Unity but learning very quickly, see if I can save him some time. :slight_smile:

So you have a line renderer that you are altering the points of? You could use [Camera.ScreenToWorldPoint][1] or similarly [ViewportToWorldPoint][2] to find where your desired begin and end points of your line renderer should end up. It would still be a case of having a 3D ‘system’ overlayed with your 2D GUI, I don’t know of any good way of drawing a line or curve directly from the gui. Without seeing your full setup I can’t really give much more help than that, it looks like you are achieving a good result so unless it is significantly impacting performance then it’s probably not worth changing!

Here some example code for how I might use ScreenToWorldSpace to set up a line renderer, you would attach this code to your camera:

public Rect rect = new Rect(0, 0, 100, 100); //screen space rect to position in
public float[] spectrumData = new float[100]; //spectrum data, 100 is arbitrary, change as needed
public float maximumSpectrumData = 1; //the maximum value of any point in spectrumData
public float lineWidth = 0.1f;
public Color color;
int count;
LineRenderer lineRenderer;
GameObject this_gameObject;
float depth = 10;
Vector3 start;
Vector3 end;

void Start () {
	this_gameObject = gameObject; //save your gameobject to reduce get component calls
	count = spectrumData.Length; //number of spectrum data points
	
	//find or make a line renderer
	lineRenderer = this_gameObject.GetComponent<LineRenderer>();
	if(lineRenderer == null){
		lineRenderer = this_gameObject.AddComponent<LineRenderer>();
	}
	//change line renderer settings
	lineRenderer.SetVertexCount(count);
	lineRenderer.SetWidth(lineWidth, lineWidth);
	lineRenderer.SetColors(color, color);
	lineRenderer.useWorldSpace = false;
	
	//in order for this code to be somewhat efficient it needs to be used on your camera so that we can set world space to false and then we don't have to keep transferring between world and local camera positions
	RecalculateScreenSpace(rect);
}

void Update(){
	//this was just for me to test how it worked, you should assign your spectrum data here, note that at the start I also picked an arbitrary length of 100 for the spectrumdata, you should find out what you need and use the for all length and line renderer vertex count
	AssignTestSpectrum(ref spectrumData);
	
	//here I call the method to position the line renderers vertices correctly
	CalculateLine(lineRenderer, start, end, spectrumData, maximumSpectrumData);
	
	//pressing R will update the line renderers screen positioning
	if(Input.GetKeyDown(KeyCode.R)){
		RecalculateScreenSpace(rect);
	}
}

void AssignTestSpectrum(ref float[] data){
	for(int i = 0; i < data.Length; i++){
		float val = Mathf.Sin(Time.time + i/(Mathf.PI*10));
		val += 1;
		val *= 0.5f;
		data *= val;*
  • }*
    }

void RecalculateScreenSpace(Rect r){

  • //find the world equivalent of your screen rectangle in camera local space, (transform.InverseTransformPoint does world to local space for given transform)*
  • start = transform.InverseTransformPoint(camera.ScreenToWorldPoint(new Vector3(r.x, r.y, depth)));*
  • end = transform.InverseTransformPoint(camera.ScreenToWorldPoint(new Vector3(r.x+r.width, r.y+r.height, depth)));*
    }

void CalculateLine(LineRenderer lRenderer, Vector3 s, Vector3 e, float[] specData, float max){

  • int c = specData.Length;*
  • //find the change in x position per vertex position to spread it over desired witdth*
  • float xDif = (e.x-s.x)/c;*
  • //find the scaling factor to multiply the value by*
  • float hDif = (e.y-s.y)/max;*
  • Vector3 pos = s;*
  • for(int i = 0; i < c; i++){*
  •  pos.x += xDif;*
    

pos.y = s.y + (specData_*hDif);_

* //Set the line renderer positions*
* lRenderer.SetPosition(i, pos);*
* }*
}
Hope that’s useful, it looks like an interesting project you have going!
Scribe
_[1]: http://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html*_
_
[2]: http://docs.unity3d.com/ScriptReference/Camera.ViewportToWorldPoint.html*_