淘先锋技术网

首页 1 2 3 4 5 6 7

Unity LineRenderer折线图谱

最近公司软件有个新的需求,实时显示玩家唱歌的音浪的折线图,我能获知的是玩家的音浪值,第一时间就想到了用LineRenderer组件来实现这个功能,趁着星期天,自己做个小Demo测试一下可行性。

作为直来直去的程序员,直接上代码

因为玩家在唱歌时,可能需要停顿,所以需要处理LineRenderer的断线操作,那么一个LineRenderer肯定是不能胜任这种操作了,所以我写了一个LineRenderer控制类LineRendererManager,如下:
这个类负责控制所有的LineRenderer折线,里面实现了简单的对象池来优化性能,这是一个全局唯一的单例类,没有继承MonoBehaviour,所以选择借助继承了MonoBehaviour的Test类来启动协程代替Update进行更新数据

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

public class LineRenderManager
{
    private static LineRenderManager _instance;
    public static LineRenderManager instance {
        get {
            if (_instance == null)
            {
                _instance = new LineRenderManager();
            }
            return _instance;
        }
    }

    public List<LineRenderItem> lineItems;
    public LineRenderItem curLineItem;


    
    public float speed=5;
    public float x = 0.1f;
    public float y = 0.1f;
    public float valueRatio=0.01f;

    public bool isAddPoint = true;
    public bool isMove
    {
        get
        {
            return LineRenderItem.isMove;
        }
        set
        {
            LineRenderItem.isMove = value;
        }
    }

    private List<LineRenderItem> itemPool;




    private LineRenderManager() {
        itemPool = new List<LineRenderItem>();
        lineItems = new List<LineRenderItem>();
        Test.instance.StartCoroutine(Update());
        isMove = false;
        isAddPoint = false;
        CreateLine();
    }

  


    public void CreateLine() {
        LineRenderer lr = null;
        if (itemPool.Count > 0)
        {
            curLineItem = itemPool[0];
            curLineItem.gameObject.SetActive(true);
            lr = curLineItem.GetComponent<LineRenderer>();
            itemPool.RemoveAt(0);
        }
        else {
            GameObject line = new GameObject("line");
            lr = line.AddComponent<LineRenderer>();
            line.transform.parent = GameObject.Find("Canvas").transform;
            curLineItem = line.AddComponent<LineRenderItem>();
        }
        curLineItem.v3List.Clear();
        lr.positionCount =0;
        lineItems.Add(curLineItem);
        curLineItem.Init();
    }

    public void DestroyLine(LineRenderItem lineRenderItem) {
        lineRenderItem.gameObject.SetActive(false);
        lineItems.Remove(lineRenderItem);
        itemPool.Add(lineRenderItem);
    }

    public void DestroyLine(int id) {
        if (id<=lineItems.Count-1)
        {
            lineItems[id].gameObject.SetActive(false);
            itemPool.Add(lineItems[id]);
            lineItems.RemoveAt(id);  
        }
    }
    

    IEnumerator Update() {

        while (true)
        {
            yield return null;

            if (isAddPoint)
            {
                curLineItem.AddPoint(new Vector3(0, Random.Range(-100, 100) * valueRatio));
            }
            
        }

    }


}


具体的LineRenderItem 控制类,每一个对象代表一个折线图,如下:

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

public class LineRenderItem : MonoBehaviour
{
    private LineRenderer lr;
 
    public List<Vector3> v3List = new List<Vector3>();

    public static bool isMove;
  

    public void Init()
    {
        lr = GetComponent<LineRenderer>();
        lr.material = new Material(Shader.Find("Sprites/Default"));
        lr.startWidth = 0.1f;                                    //设置画线开始宽度
        lr.endWidth = 0.1f;                                      //设置画线结束宽度
        lr.startColor = Color.red;                               //设置画线开始颜色
        lr.endColor = Color.red;                                 //设置画线结束颜色

    }



    //增加一个点
    public void AddPoint(Vector3 v3)
    {
        v3List.Add(v3);
        UpdateLineRenderPoint();
    }




    public void UpdateLineRenderPoint()
    {
        lr.positionCount = v3List.Count;
        lr.SetPositions(v3List.ToArray());
    }

    private void Update()
    {
        if (isMove)
        {
            for (int i = 0; i < v3List.Count; i++)
            {
                v3List[i] += Vector3.left * Time.deltaTime *LineRenderManager.instance.speed;
            }
            UpdateLineRenderPoint();
        }
    }

}

启动类Test,控制折线图的生成,移动,暂停等控制,如下:

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

public class Test : MonoBehaviour
{
    public static Test instance;
    LineRenderManager lineMgr;

    public Button playBtn;
    public Button stopBtn;
    public Button createNewLineBtn;
    public Button deleteFirstLineBtn;
    private void Awake()
    {
        instance = this;
       lineMgr =  LineRenderManager.instance;
    }

    private void Start()
    {
        playBtn.onClick.AddListener(Play);
        stopBtn.onClick.AddListener(Stop);
        createNewLineBtn.onClick.AddListener(CreateNewLine);
        deleteFirstLineBtn.onClick.AddListener(DeleteFirstLine);
    }

    public void Play() {
        lineMgr.isMove = true;
        lineMgr.isAddPoint = true;
    }

    public void Stop() {
        lineMgr.isAddPoint = false;
        lineMgr.isMove = false;

    }

    public void CreateNewLine() {
        lineMgr.isAddPoint = false;
        Invoke("Create",1);
    }


    void Create() {
        lineMgr.CreateLine();
        Play();
    }

    void DeleteFirstLine() {
        lineMgr.DestroyLine(0);
    }


}

只需要把Test脚本挂在Canvas上然后拖入对应的控制按钮就可启动程序

效果图

在这里插入图片描述