一条线的故事(基于LineRenderer的绘制封装)

编程入门 行业动态 更新时间:2024-10-10 09:20:54

<a href=https://www.elefans.com/category/jswz/34/1758545.html style=一条线的故事(基于LineRenderer的绘制封装)"/>

一条线的故事(基于LineRenderer的绘制封装)

在Unity开发中使用LineRenderer绘制线段的一般步骤:
1.创建一个物体
2.添加组件LineRenderer
3.写脚本指定LineRenderer在通过指定的LineRenderer来绘制线段
其实如果只花一条线,好像也没有那么复杂哈。但是如果我有一个需求需要画100条,这种操作就太变态了吧。。。
也许有聪明的同学会说,那我可以做成预制体啊,每个预制体上就有一个画线的对象。这样显然比上面那种方法要简便了太多太多。
但是问题也来了,如果我还需要管理这些线段的增删改查,是不是还要在写一个Manager来管理所有的线段。
干脆一点,直接我来写一个LineManager来管理工程中的所有画线功能吧。。。

从Line对象开始吧。首先我们要想,一个最基本的线段管理要具备哪些方法或属性呢。。。
别想了,我来抛砖引玉吧,看下面的ILine接口,当然如果你们感觉还可以加其他的属性或方法也可以哦,自己试着实现吧。。。

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();}
}

是不是和LineRenderer中的属性和方法差不多。是的,因为LineRenderer的方法和属性已经很全面了,这里比LineRenerer 多的方法也就AddPosition、RemovePosition、Clear、Dispose。其它的没有LineRenderer全面,如果后期有需要可以向接口中添加属性和方法,这里只是把最常用的给罗列出来。

那么我们把线段的接口给写出来了,下面开始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();}
}

对的,目前LineManager的功能确实是比较少的,基本上都是用来处理创建和删除的,哦!还有一个计数lineCount,后期开发过程中,如果需要更复杂的管理功能,可以在慢慢加嘛。

那么现在我们把线段和管理者的模板已经给写出来了,接下来就是实现这两个接口,然后就大功告成了。

Line:

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;}}
}

LineManager:

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);}}
}

哦 对了,Line的回收只回收了LineRenderer 做了一个LineRenderer的简单的对象池LineRendererPool
是不是想问为什么回收LineRenderer而不是回收Line? 因为 我怕一些小可爱在Line回收之后还保留着Line的引用,然后因为不知道,再用这个已经回收的引用,做一些操作,有可能会影响通过对象池创建的新Line,操碎了心啊。。。

不会吧,不会还让写怎么用吧。 好吧。 我还是写一写怎么创建一条线吧!!!
看仔细了,发大招了。。。。。。。。。。。。
Line line = LineManager.instance.CreateLine<Line>();
完事。

更多推荐

一条线的故事(基于LineRenderer的绘制封装)

本文发布于:2024-03-14 09:13:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1736140.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:一条线   故事   LineRenderer

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!