As etapas gerais para usar o LineRenderer para desenhar segmentos de linha no desenvolvimento do Unity:
1. Crie um objeto
2. Adicione o componente LineRenderer
3. Escreva um script para especificar o LineRenderer para desenhar segmentos de linha através do LineRenderer especificado.
Na verdade, se você gastar apenas uma linha , não parece tão complicado. Mas se eu tiver um requisito e precisar sacar 100 itens, essa operação seria muito pervertida. . .
Talvez alguns estudantes inteligentes digam: então posso transformá-lo em uma casa pré-fabricada, e cada casa pré-fabricada tem um objeto para desenhar linhas. Obviamente, isso é muito mais simples do que o método acima.
Mas também surge a questão: se ainda preciso gerenciar a adição, exclusão, modificação e verificação desses segmentos de linha, preciso escrever um gerente para gerenciar todos os segmentos de linha?
Deixe-me simplesmente escrever um LineManager para gerenciar todas as funções de desenho de linha do projeto. . .
Vamos começar com o objeto Line. Primeiro de tudo, temos que pensar sobre quais métodos ou atributos um gerenciamento de segmento de linha mais básico deve ter. . .
Não pense nisso, deixe-me apresentá-lo. Dê uma olhada na interface ILine abaixo. Claro, se você acha que pode adicionar outros atributos ou métodos, você pode tentar implementá-lo sozinho. . .
using UnityEngine;
namespace S
{
public interface ILine
{
ILineManager lineManager { get; }
/// <summary>
/// 材质
/// </summary>
Material material { get; set; }
/// <summary>
/// 开始颜色
/// </summary>
Color startColor { get; set; }
/// <summary>
/// 结束颜色
/// </summary>
Color endColor { get; set; }
/// <summary>
/// 开始宽度
/// </summary>
float startWidth { get; set; }
/// <summary>
/// 结束宽度
/// </summary>
float endWidth { get; set; }
/// <summary>
/// 是否使用世界坐标
/// </summary>
bool useWorldSpace { get; set; }
/// <summary>
/// 是否循环
/// </summary>
bool loop { get; set; }
/// <summary>
/// 坐标点的数量
/// </summary>
int positionCount { get; set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="lineManager">管理者</param>
void Init(ILineManager lineManager);
/// <summary>
/// 增加一个坐标
/// </summary>
void AddPosition(Vector3 position);
/// <summary>
/// 减少一个坐标
/// </summary>
/// <param name="index">索引</param>
void RemovePosition(int index);
/// <summary>
/// 设置一个坐标
/// </summary>
/// <param name="index">索引</param>
/// <param name="position">坐标</param>
void SetPosition(int index,Vector3 position);
/// <summary>
/// 设置多个坐标
/// </summary>
/// <param name="positions">坐标数组</param>
void SetPositions(Vector3[] positions);
/// <summary>
/// 得到一个坐标
/// </summary>
/// <param name="index">索引</param>
/// <returns></returns>
Vector3 GetPosition(int index);
/// <summary>
/// 得到所有的坐标
/// </summary>
/// <returns></returns>
Vector3[] GetPositions();
/// <summary>
/// 清空绘制内容
/// </summary>
void Clear();
/// <summary>
/// 释放对象
/// </summary>
void Dispose();
}
}
É semelhante às propriedades e métodos do LineRenderer? Sim, porque os métodos e propriedades do LineRenderer já são muito abrangentes.Existem mais métodos do que o LineRenerer, nomeadamente AddPosition, RemovePosition, Clear e Dispose. Outros não são tão abrangentes quanto o LineRenderer. Se necessário posteriormente, você pode adicionar propriedades e métodos à interface. Aqui listamos apenas os mais usados.
Depois escrevemos a interface do segmento de linha e começaremos a escrever o LineManager.
using System.Collections.Generic;
using UnityEngine;
namespace S
{
public interface ILineManager
{
public GameObject gameObject { get; }
public Transform transform { get; }
int lineCount { get; }
/// <summary>
/// 创建一条ILine
/// </summary>
/// <returns></returns>
T CreateLine<T>()where T:ILine,new();
/// <summary>
/// 管理器中是否存在指定ILine
/// </summary>
/// <param name="line"></param>
/// <returns></returns>
bool HasLine(ILine line);
/// <summary>
/// 删除一条ILine
/// </summary>
/// <param name="line">目标ILine</param>
void DeleteLine(ILine line);
/// <summary>
/// 删除一些ILine
/// </summary>
void DeleteLines(ILine[] lines);
/// <summary>
/// 删除一些ILine
/// </summary>
/// <param name="lines"></param>
void DeleteLines(List<ILine> lines);
/// <summary>
/// 删除所有ILine
/// </summary>
void DeleteAll();
}
}
Sim, as funções atuais do LineManager são relativamente poucas e são basicamente usadas para lidar com a criação e exclusão, ah! Há também uma contagem lineCount.Durante o processo de desenvolvimento posterior, se forem necessárias funções de gerenciamento mais complexas, você poderá adicioná-las lentamente.
Agora que escrevemos os modelos para segmentos de linha e gerentes, a próxima etapa é implementar essas duas interfaces e pronto.
Linha:
using System;
using System.Collections.Generic;
using UnityEngine;
namespace S
{
public static class LineRendererPool
{
private static Queue<LineRenderer> queue= new Queue<LineRenderer>();
public static int Count => queue.Count;
public static int maxCount = 10;
public static LineRenderer Dequeue()
{
LineRenderer lr = null;
while (lr==null&&Count>0)
{
lr = queue.Dequeue();
}
if (lr==null)lr = new GameObject("Line").AddComponent<LineRenderer>();
return lr;
}
public static void EnQueue(LineRenderer lr)
{
if (lr == null) return;
if (queue.Contains(lr)) return;
if (Count>=maxCount)
{
UnityEngine.Object.Destroy(lr.gameObject);
return;
}
queue.Enqueue(lr);
}
}
public class Line : ILine
{
protected LineRenderer lineRenderer { get; private set; }
public ILineManager lineManager { get; private set; }
public Material material
{
get => lineRenderer.material;
set => lineRenderer.material = value;
}
public Color startColor
{
get => lineRenderer.startColor;
set => lineRenderer.startColor = value;
}
public Color endColor
{
get => lineRenderer.endColor;
set => lineRenderer.endColor = value;
}
public float startWidth
{
get => lineRenderer.startWidth;
set => lineRenderer.startWidth = value;
}
public float endWidth
{
get => lineRenderer.endWidth;
set => lineRenderer.endWidth = value;
}
public bool useWorldSpace
{
get => lineRenderer.useWorldSpace;
set => lineRenderer.useWorldSpace = value;
}
public bool loop
{
get => lineRenderer.loop;
set => lineRenderer.loop = value;
}
public int positionCount
{
get => lineRenderer.positionCount;
set => lineRenderer.positionCount = value;
}
public void Init(ILineManager lineManager)
{
if (lineManager==null)throw new Exception("Line Init 失败,LineManager不可为null");
this.lineManager = lineManager;
lineRenderer = LineRendererPool.Dequeue();
lineRenderer.transform.SetParent(lineManager.transform);
lineRenderer.transform.localScale=Vector3.one;
lineRenderer.transform.localPosition=Vector3.zero;
Clear();
Inited();
}
protected virtual void Inited()
{
}
public void AddPosition(Vector3 position)
{
int index = positionCount;
positionCount++;
SetPosition(index,position);
}
public void RemovePosition(int index)
{
if (index < 0 || index >= positionCount) return;
if (index == positionCount - 1)
{
positionCount--;
return;
}
for (int i = index+1; i < positionCount; i++)
{
SetPosition(i-1,GetPosition(i));
}
positionCount--;
}
public void SetPosition(int index, Vector3 position)
{
lineRenderer.SetPosition(index,position);
}
public void SetPositions(Vector3[] positions)
{
lineRenderer.SetPositions(positions);
}
public Vector3 GetPosition(int index)
{
return lineRenderer.GetPosition(index);
}
public Vector3[] GetPositions()
{
Vector3[] points=new Vector3[lineRenderer.positionCount];
lineRenderer.GetPositions(points);
return points;
}
public void Clear()
{
if (lineRenderer == null) return;
positionCount = 0;
}
void ILine.Dispose()
{
Clear();
LineRendererPool.EnQueue(lineRenderer);
lineRenderer = null;
lineManager = null;
}
}
}
Gerente de linha:
using System.Collections.Generic;
using UnityEngine;
namespace S
{
public class LineManager : MonoBehaviour,ILineManager
{
private static LineManager _instance;
public static LineManager instance
{
get
{
if (_instance==null)
{
_instance = FindObjectOfType<LineManager>();
if (_instance==null)
{
_instance=new GameObject("LineManager").AddComponent<LineManager>();
DontDestroyOnLoad(_instance.gameObject);
}
}
return _instance;
}
}
public int lineCount => lines.Count;
private List<ILine> lines= new List<ILine>();
public T CreateLine<T>()where T:ILine,new()
{
T line = new T();
line.Init(this);
lines.Add(line);
return line;
}
public bool HasLine(ILine line)
{
if (line==null||lineCount == 0) return false;
return lines.Contains(line);
}
public void DeleteLine(ILine line)
{
if (!HasLine(line)) return;
lines.Remove(line);
line.Dispose();
}
public void DeleteLines(ILine[] lines)
{
int Count = lines == null ? 0 : lines.Length;
if (Count == 0) return;
for (int i = 0; i < Count; i++)
{
DeleteLine(lines[i]);
}
}
public void DeleteLines(List<ILine> lines)
{
int Count = lines == null ? 0 : lines.Count;
if (Count == 0) return;
for (int i = 0; i < Count; i++)
{
DeleteLine(lines[i]);
}
}
public void DeleteAll()
{
DeleteLines(lines);
}
}
}
Ah, a propósito, a reciclagem do Line recicla apenas o LineRenderer. Eu criei um pool de objetos simples LineRendererPool para o LineRenderer. Você quer perguntar
por que recicla o LineRenderer em vez de reciclar o Line? Porque temo que alguns fofos ainda retenham a referência à reciclagem Linha após Linha e depois usem essa referência reciclada para fazer algumas operações porque não sei, o que pode afetar a nova Linha criada através do pool de objetos. estou preocupado. ah. . .
Não, não posso te dizer como usá-lo. Tudo bem. Deixe-me escrever sobre como criar uma linha! ! !
Olhe com atenção, é uma grande jogada. . . . . . . . . . . .
Linha linha = LineManager.instance.CreateLine<Line>();
Concluído.