当前位置: 首页 > article >正文

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事件处理区域

实现代码: 

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
}


http://www.kler.cn/a/583991.html

相关文章:

  • 【MySQL】MySQL服务器——mysqld
  • C语言实现十六进制转十进制
  • 分布式事务中XA 事务 和 两阶段提交(2PC)应该如何理解?
  • NineData 社区版:从 MySQL 到 TiDB 数据复制新选择
  • 网络安全反渗透 网络安全攻防渗透
  • 【javaEE】文件操作--io
  • 使用mybatis-plus自定义分页实现一对多的分页功能
  • Unity引擎架构介绍及代码示例
  • Nature最新报道:分析四大主流AI工具、性能测评、推荐使用场景
  • Vim忍者速成秘卷:让你的键盘冒出残影の奥义
  • 如何通过ibd文件恢复MySql数据
  • 鸿蒙编译框架插件HvigorPlugin接口的用法介绍
  • 蓝桥杯备考:数据结构堆之 除2!
  • STM32Cubemx-H7-9-串口接受不定长度数据并识别
  • 解决 VSCode SSH 连接报错:“REMOTE HOST IDENTIFICATION HAS CHANGED” 的问题
  • Nginx 多协议代理功能(Nginx Multi Protocol Proxy Function)
  • windows11 LTSC 24h2 访问NAS问题的安全高效解决
  • C语言:计算并输出三个整数的最大值 并对三个数排序
  • 图解AUTOSAR_CP_ServiceDiscovery
  • Unix 域套接字(本地套接字)