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上然后拖入对应的控制按钮就可启动程序