La historia de una línea (paquete de dibujo basado en LineRenderer)

Los pasos generales para usar LineRenderer para dibujar segmentos de línea en el desarrollo de Unity:
1. Crear un objeto
2. Agregar el componente LineRenderer
3. Escribir un script para especificar LineRenderer para dibujar segmentos de línea a través del LineRenderer especificado.
De hecho, si solo gasta una línea , no parece tan complicado. Pero si tengo un requisito y necesito dibujar 100 elementos, esta operación sería demasiado pervertida. . .
Tal vez algunos estudiantes inteligentes digan, entonces puedo convertirlo en una casa prefabricada, y cada casa prefabricada tiene un objeto para dibujar líneas. Obviamente, esto es mucho más simple que el método anterior.
Pero también surge la pregunta: si todavía necesito administrar la adición, eliminación, modificación y verificación de estos segmentos de línea, ¿necesito escribir un Administrador para administrar todos los segmentos de línea?
Permítanme simplemente escribir un LineManager para administrar todas las funciones de dibujo lineal en el proyecto. . .

Comencemos con el objeto Línea. En primer lugar tenemos que pensar qué métodos o atributos debe tener una gestión de segmento de línea más básica. . .
No lo pienses, déjame darte algunas ideas. Echa un vistazo a la interfaz ILine a continuación. Por supuesto, si crees que puedes agregar otros atributos o métodos, puedes intentar implementarlo tú mismo. . .

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

¿Es similar a las propiedades y métodos de LineRenderer? Sí, porque los métodos y propiedades de LineRenderer ya son muy completos. Hay más métodos que LineRenerer, a saber, AddPosition, RemovePosition, Clear y Dispose. Otros no son tan completos como LineRenderer. Si es necesario más adelante, puedes agregar propiedades y métodos a la interfaz. Aquí solo enumeramos los más utilizados.

Luego hemos escrito la interfaz del segmento de línea y luego comenzaremos a escribir el 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();
    }
}

Sí, las funciones actuales de LineManager son relativamente pocas y se utilizan básicamente para manejar la creación y eliminación, ¡oh! También hay un conteo lineCount. Durante el proceso de desarrollo posterior, si se necesitan funciones de administración más complejas, puede agregarlas lentamente.

Ahora que hemos escrito las plantillas para los segmentos de línea y los administradores, el siguiente paso es implementar estas dos interfaces y listo.

Línea:

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 línea:

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, por cierto, el reciclaje de Line solo recicla LineRenderer. Hice un grupo de objetos simple LineRendererPool para LineRenderer. ¿Quieres
preguntar por qué se recicla LineRenderer en lugar de Line? Porque me temo que algunos pequeños lindos aún conservarán la referencia a Line después de que se recicle la Line, luego, como no lo sé, usarán esta referencia reciclada para realizar algunas operaciones, lo que puede afectar la nueva Line creada. A través del grupo de objetos. Estoy preocupado. Ah. . .

No, no puedo decirte cómo usarlo. Está bien. ¡Déjame escribir sobre cómo crear una línea! ! !
Mire con atención, es un gran movimiento. . . . . . . . . . . .
Línea línea = LineManager.instance.CreateLine<Line>();
Listo.

Supongo que te gusta

Origin blog.csdn.net/weixin_42498461/article/details/130644382
Recomendado
Clasificación