- Home /
C# create linerenderer line copy based on spectrum data
Hi im doing a simple visualization here and i want to create a copy of the drawn linerenderer of every frame or second without copying the gameobject which the script is attached to...Any ideas? Thanks.
public class AudioVisualizer : MonoBehaviour
private AudioSource aSource;
//A float array that stores the audio samples
public float[] samples = new float[64];
//A renderer that will draw a line at the screen
private LineRenderer lRenderer;
//A reference to the cube prefab
public GameObject cube;
//The transform attached to this game object
private Transform goTransform;
//The position of the current cube. Will also be the position of each point of the line.
private Vector3 cubePos;
//An array that stores the Transforms of all instantiated cubes
private Transform[] cubesTransform;
//The velocity that the cubes will drop
private Vector3 gravity = new Vector3(0.0f,0.25f,0.0f);
void Awake ()
{
//Get and store a reference to the following attached components:
//AudioSource
this.aSource = GetComponent();
//LineRenderer
this.lRenderer = GetComponent();
//Transform
this.goTransform = GetComponent();
}
void Start()
{
//The line should have the same number of points as the number of samples
lRenderer.SetVertexCount(samples.Length);
//The cubesTransform array should be initialized with the same length as the samples array
cubesTransform = new Transform[samples.Length];
//Center the audio visualization line at the X axis, according to the samples array length
goTransform.position = new Vector3(-samples.Length/2,goTransform.position.y,goTransform.position.z);
//Create a temporary GameObject, that will serve as a reference to the most recent cloned cube
GameObject tempCube;
//For each sample
for(int i=0; i();
//Make the cube a child of this game object
cubesTransform[i].parent = goTransform;
}
}
void Update ()
{
//Obtain the samples from the frequency bands of the attached AudioSource
aSource.GetSpectrumData(this.samples,0,FFTWindow.Blackman);
//For each sample
for(int i=0; i= cubesTransform[i].position.y)
{
//Set the cube to the new Y position
cubesTransform[i].position = cubePos;
}
else
{
//The spectrum line is below the cube, make it fall
cubesTransform[i].position -= gravity;
}
/*Set the position of each vertex of the line based on the cube position.
* Since this method only takes absolute World space positions, it has
* been subtracted by the current game object position.*/
lRenderer.SetPosition(i, cubePos - goTransform.position);
}
}
Answer by APTEM59 · Oct 14, 2020 at 09:26 PM
(2020) check this and edit for yourself:
public class AudioVisualizer : MonoBehaviour
{
//C#
public int bufferSampleSize;
public float samplePercentage;
public float emphasisMultiplier;
public float retractionSpeed;
public float ScaleSpeed;
public int a1;
public int amountOfSegments;
public float radius;
public float bufferSizeArea;
public float maximumExtendLength;
float average;
public GameObject lineRendererPrefab, canvas,disk;
public Material lineRendererMaterial;
public VisualizationMode visualizationMode;
public Gradient colorGrandientA = new Gradient();
public Gradient colorGrandientB = new Gradient();
private float sampleRate;
private float[] samples;
private float[] spectrum;
private float[] extendLengths;
private LineRenderer[] lineRenderers;
private AudioSource audioSource;
private void Awake()
{
audioSource = GetComponent<AudioSource>();
sampleRate = AudioSettings.outputSampleRate;
samples = new float[bufferSampleSize];
spectrum = new float[bufferSampleSize];
InitiateRing();
}
private void InitiateRing()
{
extendLengths = new float[amountOfSegments + 1];
lineRenderers = new LineRenderer[extendLengths.Length];
for (int i = 0; i < lineRenderers.Length; i++)
{
GameObject go = Instantiate(lineRendererPrefab);
go.transform.SetParent(this.transform);
go.transform.localPosition = new Vector3(0, 0, -50);
go.transform.localScale=new Vector3(1,1,1);
LineRenderer lineRenderer = go.GetComponent<LineRenderer>();
lineRenderer.sharedMaterial = lineRendererMaterial;
lineRenderer.sortingLayerName = "Foreground";
lineRenderer.positionCount = 2;
lineRenderer.useWorldSpace = false;
lineRenderers[i] = lineRenderer;
}
}
private void Update()
{
// if(FindObjectOfType<beatDetector>().average==0f)
// disk.transform.localScale=default;
if (canvas.GetComponent<AudioSource>().clip != null)
{
canvas.GetComponent<AudioSource>().GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);
UpdateExtends();
OnBeatDetected();
if (visualizationMode == VisualizationMode.Ring)
{
UpdateRing();
}
}
}
public void OnBeatDetected()
{
average = FindObjectOfType<beatDetector>().average*5;
Vector3 _localScale = disk.transform.localScale;
float _x;
if(average<1.2f)
_x=1f;
else
{
_x=average;
}
_localScale=new Vector3(Mathf.Lerp(_localScale.x,_x,Time.deltaTime/ScaleSpeed),Mathf.Lerp(_localScale.y,_x,Time.deltaTime/ScaleSpeed),1);
disk.transform.localScale=_localScale;
}
private void UpdateExtends()
{
int iteration = 0;
int indexOnSpectrum = 0;
int averageValue = (int)(Mathf.Abs(samples.Length * samplePercentage) / amountOfSegments);
if (averageValue < 1)
{
averageValue = 1;
}
while (iteration < amountOfSegments)
{
int iterationIndex = 0;
float sumValueY = 0;
while (iterationIndex < averageValue)
{
sumValueY += spectrum[indexOnSpectrum];
indexOnSpectrum++;
iterationIndex++;
}
float y = sumValueY / averageValue * emphasisMultiplier;
extendLengths[iteration] -= retractionSpeed * Time.deltaTime;
if (extendLengths[iteration] < y)
{
extendLengths[iteration] = y;
}
if (extendLengths[iteration] > maximumExtendLength)
{
extendLengths[iteration] = maximumExtendLength;
}
iteration++;
}
}
private void UpdateRing()
{
for (int i = 0; i < lineRenderers.Length; i++)
{
float t = i / (lineRenderers.Length - 2f);
float a = t * Mathf.PI * 2f;
Vector2 direction = new Vector2(Mathf.Cos(a+a1), Mathf.Sin(a+a1));
float maximumRadius = (radius + bufferSizeArea + extendLengths[i]);
lineRenderers[i].SetPosition(0, direction * radius);
lineRenderers[i].SetPosition(1, direction * maximumRadius);
lineRenderers[i].startWidth = Spacing(radius/2.5f);
lineRenderers[i].endWidth = Spacing(maximumRadius/2.5f);
GradientColorKey[] colorkey=new GradientColorKey[2];
if(average>1.2f)
colorkey[0].color=new Color(1f,Mathf.Lerp(colorGrandientA.Evaluate(0f).g,1, ScaleSpeed),Mathf.Lerp(colorGrandientA.Evaluate(0f).b,1,ScaleSpeed));
else
colorkey[0].color=new Color(1f,Mathf.Lerp(colorGrandientA.Evaluate(0f).g,26/255, ScaleSpeed),Mathf.Lerp(colorGrandientA.Evaluate(0f).b,106/255, ScaleSpeed));
colorkey[0].time=1f;
colorkey[1].color= Color.magenta;
colorkey[1].time=0f;
GradientAlphaKey[] alphakey =new GradientAlphaKey[2];
alphakey[0].alpha=1f;
alphakey[0].time=0f;
alphakey[1].alpha=1f;
alphakey[1].time=1f;
colorGrandientA.SetKeys(colorkey,alphakey);
lineRenderers[i].startColor = colorGrandientA.Evaluate(0);
lineRenderers[i].endColor = colorGrandientA.Evaluate((extendLengths[i] - 1) / (maximumExtendLength - 1f));
}
}
private float Spacing(float radius)
{
float c = 2f * Mathf.PI * radius;
float n = lineRenderers.Length;
return c / n;
}
}
Answer by idbrii · Oct 17, 2020 at 09:19 AM
i want to create a copy of the drawn linerenderer of every frame or second
Where you do this:
lRenderer.SetPosition(i, cubePos - goTransform.position);
Save the position in a Vector3[]:
m_Position[i] = cubePos - goTransform.position;
lRenderer.SetPosition(i, m_Position[i]);
And then make another MonoBehaviour that copies those position values into another LineRenderer.
If you wanted to copy it every second, do it in a coroutine.
If your visualization isn't working, check out this answer.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Draw shortest distance between 2 points on a sphere 1 Answer
Line Renderer Issues 1 Answer