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
}
相关推荐
不伤欣12 小时前
游戏设计模式 - 子类沙箱
游戏·unity·设计模式
Magnum Lehar14 小时前
vulkan游戏引擎test文件memory实现
游戏引擎
Magnum Lehar14 小时前
vulkan游戏引擎test_manager实现
java·算法·游戏引擎
lingling00918 小时前
迁移科技3D视觉系统:重塑纸箱拆垛场景的智能革命
科技·3d
快乐觉主吖18 小时前
Unity的日志管理类
android·unity·游戏引擎
WarPigs1 天前
Unity性能优化笔记
笔记·unity·游戏引擎
T.D.C1 天前
【业务框架】3C-相机-Cinemachine
unity
子燕若水2 天前
daz3d + PBRSkin (MDL)+ SSS
3d
一线灵2 天前
跨平台游戏引擎 Axmol-2.6.1 发布
游戏引擎
灏瀚星空2 天前
Python数学可视化:3D参数曲面与隐式曲面绘制技术
开发语言·python·3d