unity基础——3D画线

关键术语解释:

  1. LineRenderer

    • Unity的组件类,用于在3D空间绘制连续线段

    • 主要属性:positions(坐标点集合)、width(线条粗细)、material(外观材质)

    • numCapVertices:线端顶点数,影响端点圆滑度

    • numCornerVertices:拐角顶点数,影响转角平滑度

  2. Raycast

    • 物理检测方法,发射不可见射线检测碰撞体

    • ScreenPointToRay:将屏幕坐标转换为3D空间射线

    • 依赖Collider组件,用于准确定位绘制位置

  3. List<Vector3>

    • C#泛型集合,动态存储坐标序列

    • 相比数组,支持动态扩容和便捷操作(Add/Clear等)

  4. Vector3.Distance

    • 静态方法,计算两个三维点之间的欧几里得距离

    • 用于判断鼠标移动量是否达到绘制阈值

  5. UI Toggle

    • Unity UI系统的开关组件

    • 通过OnValueChanged事件绑定颜色/尺寸切换方法

脚本设计思路:

  1. 输入处理流程

    • 按下阶段:初始化新线条,记录起始点

    • 持续阶段:每帧检测鼠标移动,满足条件时添加新点

    • 释放阶段:清理数据,准备下次绘制

  2. 坐标获取机制

    • 使用主摄像机发射射线

    • 依赖场景中的Collider获取准确坐标

    • Z轴偏移解决渲染重叠问题

  3. 渲染优化策略

    • 动态更新LineRenderer的positions数组

    • 使用List管理坐标点,自动处理内存

    • 通过顶点数配置提升线条视觉质量

  4. 模块化设计

    • 分离核心绘制逻辑(AddPosition)

    • 独立坐标获取方法(GetMousePoint)

    • 清晰的UI事件处理区域

实现代码:

cs 复制代码
using System.Collections.Generic;
using UnityEngine;

public class Mapaint : MonoBehaviour
{
    // 画笔颜色属性 和 画笔大小属性
    public Color paintColor = Color.red;
    public float paintSize = 0.1f;
    // 当前画线
    public LineRenderer Currentline;
    // 画线的材质
    public Material lineMaterial;
    //存储线条点的坐标集合
    private List<Vector3> positions = new List<Vector3>();
    // 鼠标按下状态标志
    private bool isMouseDown = false;
    // 鼠标上一帧位置
    private Vector3 lastMousePosition = Vector3.zero;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 创建新的游戏对象承载LineRenderer组件
            GameObject go = new GameObject();
            go.transform.SetParent(this.transform);  // 挂载到当前物体下
            Currentline = go.AddComponent<LineRenderer>();  // 添加LineRenderer组件

            // 设置材质
            Currentline.material = lineMaterial;
            // 设置宽度
            Currentline.startWidth = paintSize;
            Currentline.endWidth = paintSize;
            // 设置颜色
            Currentline.startColor = paintColor;
            Currentline.endColor = paintColor;

            Currentline.numCapVertices = 5;  // 设置顶点数
            Currentline.numCornerVertices = 5;  // 设置角点数

            // 初始化第一个点
            Vector3 position = GetMousePoint();
            position.z -= 1f;
            positions.Clear();
            AddPosition(position);  // 调用AddPosition方法
            lastMousePosition = position; // 记录初始位置

            // 标记鼠标按下状态
            isMouseDown = true;


        }
        // 持续按住鼠标时持续添加点
        if (isMouseDown)
        {
            Vector3 currentPos = GetMousePoint();
            currentPos.z -= 1f;
           
            // 鼠标移动时,距离大于0.01时才添加点
            if (Vector3.Distance(currentPos, lastMousePosition) > 0.01f)
            {
                AddPosition(currentPos);
                lastMousePosition = currentPos;
                Debug.Log("加点");
            }
        }

        // 鼠标松开时结束绘制
        if (Input.GetMouseButtonUp(0))
        {
            Currentline = null;
            // 清空历史坐标点
            positions.Clear();
            isMouseDown = false;
        }

        // 添加坐标点到当前线条
        void AddPosition(Vector3 position)
        {
            positions.Add(position);

            // 更新LineRenderer数据
            Currentline.positionCount = positions.Count;
            Currentline.SetPositions(positions.ToArray());

        }
        // 通过射线检测获取鼠标在场景中的坐标(需要场景中存在碰撞体)
        Vector3 GetMousePoint()
        {
            // 创建从摄像机发射的射线
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;  // 存储射线碰撞信息的结构体

            // 进行物理射线检测(最大距离默认为无限)
            bool isCollider = Physics.Raycast(ray, out hit);
            if (isCollider)
            {
                return hit.point;  // 返回碰撞点的世界坐标
            }

            return Vector3.zero;  // 安全返回值

        }
    }

    #region
    public void OnRedColorChanged(bool isON)
    {
        if (isON)
        {
            paintColor = Color.red;
        }
    }
    public void OnGreenColorChanged(bool isON)
    {
        if (isON)
        {
            paintColor = Color.green;
        }
    }
    public void OnBlueColorChanged(bool isON)
    {
        if (isON)
        {
            paintColor = Color.blue;
        }
    }
    public void OnPaint1Changed(bool isON)
    {
        if (isON)
        {
            paintSize = 0.1f;
        }
    }
    public void OnPaint2Changed(bool isON)
    {
        if (isON)
        {
            paintSize = 0.2f;
        }
    }
    public void OnPaint3Changed(bool isON)
    {
        if (isON)
        {
            paintSize = 0.4f;
        }
    }
    #endregion
}
相关推荐
weixin_505154467 小时前
打破传统界限:Bowell Studio引领3D作业指导新纪元
人工智能·3d·制造·数据安全·数字孪生·数据可视化
七夜zippoe10 小时前
OpenClaw 内置工具详解
unity·ai·游戏引擎·openclaw·内置工具
mxwin15 小时前
Unity Shader 细节贴图技术在不增加显存开销的前提下,有效提升近距离纹理细节的渲染质量
unity·游戏引擎·贴图
魔士于安17 小时前
unity 低多边形 动物 带场景 有氛围感
游戏·unity·游戏引擎·贴图
小贺儿开发18 小时前
Unity3D 摩斯与中文电码转换工具
科技·unity·人机交互·工具·实践·实用·科普应用
3D小将18 小时前
3DXML转GLTF技术文档(推荐免费在线转换网站)
3d·solidworks模型·ug模型·rhino模型·sketchup模型·igs模型·迪威模型网
魔士于安18 小时前
unity 动物包 大象 鹿 狐狸
游戏·unity·游戏引擎·贴图·模型
孪生引擎观星台20 小时前
WSBK专业赛车场3D数字孪生Demo快速开发与系统落地实战指南
人工智能·3d
Yao.Li21 小时前
PVN3D ONNX 转换与测试记录
人工智能·3d·具身智能
mxwin21 小时前
Unity URP 中 Mipmap 纹理多级渐远技术 解决远处纹理闪烁(摩尔纹)与性能优化的完整指南
unity·游戏引擎