0

我有统一的线。她的尺寸是64点。其实重点是什么,但重点是我需要在类似于spriteShape的线下区域绘制,我很乐意使用它,但我还是想不通。这是该行的代码。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class soundVisualize : MonoBehaviour {

    public float range = 5000f;

    public int number = 64;
    public float[] oldSpc;

    public LineRenderer line;

    public int spec;

    [Range(0, 1)]
    public float speedAnimation;

    private void Awake() 
    {
        for(int i = 0;i < number; i++)
        {
            Vector3 posInArray = new Vector3(0,0,0);
            if(i>0)
                posInArray = line.GetPosition(i-1);
            line.SetPosition(i,posInArray+new Vector3(0.2f,0,0));
        }    
    }
    
    void Update () {
        float[] spectrum = new float[spec];
        GetComponent<AudioSource>().GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);

        for(int i = 0;i < number; i++)
        {
            line.SetPosition(i,Vector3.Lerp(line.GetPosition(i),new Vector3(line.GetPosition(i).x,(range * spectrum[i] + oldSpc[i])/2),speedAnimation));
            oldSpc[i] = range * spectrum[i];
        }
    }


}

我们有

这个

但我们需要

这个

4

2 回答 2

1

这有点棘手,但我会尝试解释我在做什么;)

基本上你想要做的是创建一个只包含两条​​线的新网格

  • 您当前的行位置
  • 底线

所以我所做的是在开始时通过创建这两条线并将它们与三角面连接来创建网

然后稍后我只需将线渲染器的位置复制到新网格的顶行。

所以它可能看起来有点像

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SoundVisualizer : MonoBehaviour
{
    public LineRenderer line;

    // Best already reference these via the Inspector
    [SerializeField] private AudioSource _audioSource;
    [SerializeField] private MeshFilter _meshFilter;

    public int number = 64;
    public float[] oldSpc;
    public float range = 5000f;

    public int spec;

    [Range(0, 1)] public float speedAnimation;

    // Stores the line positions
    private Vector3[] positions;
    // Stores the mesh reference
    private Mesh _mesh;

    private void Awake()
    {
        // As fallback get it ONCE on runtime
        if (!_audioSource) _audioSource = GetComponent<AudioSource>();
        if (!_meshFilter) _meshFilter = GetComponent<MeshFilter>();

        _mesh = _meshFilter.mesh;

        // Set the point amount via code
        line.positionCount = number;

        // Note that it is way more efficient to use GetPositions and SetPositions
        // instead of using GetPosition and SetPosition multiple times!
        positions = new Vector3[number];
        line.GetPositions(positions);
        
        for (var i = 0; i < number; i++)
        {
            positions[i] = Vector3.right * (0.2f* i);
        }

        line.SetPositions(positions);

        if (spec < number) spec = number;

        oldSpc = new float[spec];

        // Now initialize the mesh once
        // After having set up all the faces etc it is enough to only update
        // The vertex positions
        InitializeMesh();
    }

    private void Update()
    {
        var spectrum = new float[spec];
        _audioSource.GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);

        // Update the values inside of the array you already have
        // -> no need to use GetPositions again
        for (var i = 0; i < number; i++)
        {
            var position = positions[i];

            positions[i] = Vector3.Lerp(position, new Vector3(position.x, (range * spectrum[i] + oldSpc[i]) / 2), speedAnimation);

            oldSpc[i] = range * spectrum[i];
        }

        line.SetPositions(positions);

        UpdateMesh();
    }

    private void InitializeMesh()
    {
        _mesh.Clear();

        // Basically we will create a bottom and a top line each with "number" vertices
        // Then later we create triangulated faces between these two lines
        var vertices = new Vector3[number * 2];

        for (var i = 0; i < number; i++)
        {
            vertices[i] = i * 0.2f * Vector3.right + Vector3.up * 1; // This will be the top line, for debugging set it to y = 1
            vertices[i + number] = i * 0.2f * Vector3.right; // This will be the bottom line
        }

        var triangles = new int[2 * (number - 1) * 3]; // This is "number - 1" * amount f faces per segment (2) * vertices per face ( 3)

        // Now lets create triangulated faces using these vertices and connecting the two lines
        for (var i = 0; i < number - 1; i++)
        {
            triangles[6 * i] = i;
            triangles[6 * i + 1] = i + 1;
            triangles[6 * i + 2] = i + number;

            triangles[6 * i + 3] = i + 1;
            triangles[6 * i + 4] = i + number + 1;
            triangles[6 * i + 5] = i + number;
        }

        _mesh.vertices = vertices;
        _mesh.triangles = triangles;
        _mesh.RecalculateNormals();
    }

    private void UpdateMesh()
    {
        // Basically we will simply update the positions of the top line in the mesh
        // (= the first half of the vertices array)
        // The rest (faces etc) will be updated automatically

        var vertices = _mesh.vertices;
        for (var i = 0; i < number; i++)
        {
            vertices[i] = positions[i];
        }

        _mesh.vertices = vertices;
    }
}

所以只是为了展示它,我给这条线一个不同的颜色

在此处输入图像描述

所以最后要做的是调整厚度,或者换句话说,调整到底线的偏移量。我实际上会简单地降低底线

// In this line simply add some negative offset on Y
//
//                                              |
//                                              V
vertices[i + number] = i * 0.2f * Vector3.right - Vector3.up ; // This will be the bottom line

现在它看起来像这样:)

在此处输入图像描述

请注意,在当前版本中,您将无法在运行时调整 Inspector 的所有值;)

另请注意,LineRenderer 组件当然功能更强大,因为它还可以自动生成一些平滑的角落和东西

于 2020-10-06T10:16:08.657 回答
0

我不认为你可以用 LineRenderer 做到这一点。您应该尝试在运行时创建和修改它。您将在顶部边缘有 64 个三角形,在左下角和右下角有 2 个三角形。

有关更多信息,请参阅官方文档

于 2020-10-06T10:10:42.437 回答