清洁游戏开发:鼠标快速拖动绘制直线断线及SetPixel优化求助
清洁类游戏快速拖动鼠标绘制线条断裂问题解决
我正在开发一款清洁类游戏,遇到这样的问题:快速拖动鼠标绘制直线(清洁区域)时线条会出现断裂,慢速拖动时绘制的直线显示正常。

问题根源
你的代码里有个关键逻辑:计算当前鼠标位置与上一次绘制位置的曼哈顿距离,若小于7则直接跳过绘制。快速拖动时,鼠标每帧移动的跨度可能超过7,但中间那些距离不够的帧会被跳过;就算触发绘制,也只在当前点刷一次刷子,两点之间的空白区域完全没填充,最终导致线条断裂。
解决方案
核心思路是填充鼠标移动路径上的所有像素点,而不是只处理离散的帧位置。具体修改如下:
- 移除原代码中距离判断的跳过逻辑
- 使用直线算法(比如Bresenham)计算两次鼠标位置之间的所有像素点,逐个用刷子覆盖
- 封装绘制逻辑,避免代码冗余
修改后的完整代码
private void Update() { if (Input.GetMouseButton(0)) { if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out RaycastHit hit)) { Vector2 textureCoord = hit.textureCoord; int pixelX = (int)(textureCoord.x * _templateDirtMask.width); int pixelY = (int)(textureCoord.y * _templateDirtMask.height); Vector2Int currentPaintPos = new Vector2Int(pixelX, pixelY); // 第一次绘制初始化上一次位置 if (lastPaintPixelPosition == Vector2Int.zero) { lastPaintPixelPosition = currentPaintPos; PaintAtPosition(currentPaintPos); return; } // 绘制上一次位置到当前位置的连续线条 DrawLineBetween(lastPaintPixelPosition, currentPaintPos); lastPaintPixelPosition = currentPaintPos; } } } // 在指定像素位置绘制刷子 private void PaintAtPosition(Vector2Int position) { int pixelXOffset = position.x - (_brush.width / 2); int pixelYOffset = position.y - (_brush.height / 2); for (int x = 0; x < _brush.width; x++) { for (int y = 0; y < _brush.height; y++) { int targetX = pixelXOffset + x; int targetY = pixelYOffset + y; // 边界检查,防止访问纹理外的像素 if (targetX < 0 || targetX >= _templateDirtMask.width || targetY < 0 || targetY >= _templateDirtMask.height) continue; Color pixelDirt = _brush.GetPixel(x, y); Color pixelDirtMask = _templateDirtMask.GetPixel(targetX, targetY); float removedAmount = pixelDirtMask.g - (pixelDirtMask.g * pixelDirt.g); dirtAmount -= removedAmount; _templateDirtMask.SetPixel(targetX, targetY, new Color(0, pixelDirtMask.g * pixelDirt.g, 0)); } } _templateDirtMask.Apply(); } // 使用Bresenham算法绘制两点间的连续线条 private void DrawLineBetween(Vector2Int start, Vector2Int end) { int x0 = start.x; int y0 = start.y; int x1 = end.x; int y1 = end.y; int dx = Mathf.Abs(x1 - x0); int dy = Mathf.Abs(y1 - y0); int sx = x0 < x1 ? 1 : -1; int sy = y0 < y1 ? 1 : -1; int err = dx - dy; while (true) { PaintAtPosition(new Vector2Int(x0, y0)); if (x0 == x1 && y0 == y1) break; int e2 = 2 * err; if (e2 > -dy) { err -= dy; x0 += sx; } if (e2 < dx) { err += dx; y0 += sy; } } }
关键修改说明
- 删掉了原代码中
paintPixelDistance < maxPaintDistance的跳过逻辑,不会再漏掉任何需要绘制的帧 - 新增
PaintAtPosition方法封装刷子绘制逻辑,代码更简洁易维护 - 用Bresenham直线算法遍历鼠标移动路径上的所有像素点,确保快速拖动时线条完全连续
- 添加纹理边界检查,避免因坐标越界导致的报错
内容的提问来源于stack exchange,提问作者Newboy11
相关产品推荐
相关产品推荐

