unity基础——3D画线
关键术语解释:
-
LineRenderer:
-
Unity的组件类,用于在3D空间绘制连续线段
-
主要属性:positions(坐标点集合)、width(线条粗细)、material(外观材质)
-
numCapVertices
:线端顶点数,影响端点圆滑度 -
numCornerVertices
:拐角顶点数,影响转角平滑度
-
-
Raycast:
-
物理检测方法,发射不可见射线检测碰撞体
-
ScreenPointToRay
:将屏幕坐标转换为3D空间射线 -
依赖Collider组件,用于准确定位绘制位置
-
-
List<Vector3>:
-
C#泛型集合,动态存储坐标序列
-
相比数组,支持动态扩容和便捷操作(Add/Clear等)
-
-
Vector3.Distance:
-
静态方法,计算两个三维点之间的欧几里得距离
-
用于判断鼠标移动量是否达到绘制阈值
-
-
UI Toggle:
-
Unity UI系统的开关组件
-
通过OnValueChanged事件绑定颜色/尺寸切换方法
-
脚本设计思路:
-
输入处理流程:
-
按下阶段:初始化新线条,记录起始点
-
持续阶段:每帧检测鼠标移动,满足条件时添加新点
-
释放阶段:清理数据,准备下次绘制
-
-
坐标获取机制:
-
使用主摄像机发射射线
-
依赖场景中的Collider获取准确坐标
-
Z轴偏移解决渲染重叠问题
-
-
渲染优化策略:
-
动态更新LineRenderer的positions数组
-
使用List管理坐标点,自动处理内存
-
通过顶点数配置提升线条视觉质量
-
-
模块化设计:
-
分离核心绘制逻辑(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
}