FEATURED · 精选文章

Unity标记固定颜色及投影标记

发布时间 / 2026/9/6 3:03:05
来源 / 创域科博编辑部
栏目 / 资讯中心
Unity标记固定颜色及投影标记 1 结构2 CameraDisplay和DrawingOverlay为Raw Image3 ProjectorCanvas可以直接复制上面的Canvas然后删除其他不用的。最后留下的只是渲染原来的标记。4 游戏组件设置Main CameraProjectorCameraCanvasusing System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; public class FixedOneColor : MonoBehaviour { [Header(底层显示摄像头)] public RawImage CamRaw; [Header(顶层绘图面板(同尺寸全屏))] public RawImage DrawRaw; [Header(投影端RawImage)] public RawImage projectorRaw; private WebCamTexture _camTex; private Texture2D _drawTex; private int _w, _h; private bool _isDraw; private ListVector2 _curPoints new ListVector2(); private ListStroke _history new ListStroke(); // 当前画笔颜色默认红色 private Color _currentColor Color.red; [Serializable] class Stroke { public ListVector2 pts new ListVector2(); public Color col; } void Start() { // 初始化相机 var device WebCamTexture.devices[0]; _camTex new WebCamTexture(device.name, 1280, 720); _camTex.Play(); CamRaw.texture _camTex; // 初始化顶层绘图纹理 Invoke(nameof(InitDrawTex), 0.5f); } void InitDrawTex() { _w _camTex.width; _h _camTex.height; _drawTex new Texture2D(_w, _h, TextureFormat.RGBA32, false); _drawTex.wrapMode TextureWrapMode.Clamp; ClearDrawTex(); DrawRaw.texture _drawTex; if (projectorRaw ! null) projectorRaw.texture _drawTex; } void Update() { if (_drawTex null) return; // 键盘快捷键切换画笔颜色与按钮功能一致 if (Input.GetKeyDown(KeyCode.R)) SetRedColor(); if (Input.GetKeyDown(KeyCode.G)) SetGreenColor(); if (Input.GetKeyDown(KeyCode.B)) SetBlueColor(); // 原有快捷键 if (Input.GetKeyDown(KeyCode.C)) ClearAll(); if (Input.GetKeyDown(KeyCode.S)) SaveImg(); DealMouse(); RenderDraw(); } // 三个颜色切换方法供UI按钮点击调用 public void SetRedColor() { _currentColor Color.red; } public void SetGreenColor() { _currentColor Color.green; } public void SetBlueColor() { _currentColor Color.blue; } void DealMouse() { // 按下 if (Input.GetMouseButtonDown(0)) { _isDraw true; _curPoints.Clear(); _curPoints.Add(GetMouseTexPos()); } // 拖动 if (Input.GetMouseButton(0) _isDraw) { var p GetMouseTexPos(); if (Vector2.Distance(p, _curPoints.Last()) 2f) _curPoints.Add(p); } // 抬起 if (Input.GetMouseButtonUp(0) _isDraw) { _isDraw false; if (_curPoints.Count 2) { _curPoints.Clear(); return; } // 使用当前选中的颜色创建新笔画默认红色 _history.Add(new Stroke { pts new ListVector2(_curPoints), col _currentColor }); _curPoints.Clear(); } } // 鼠标屏幕坐标 → 纹理像素坐标 Vector2 GetMouseTexPos() { RectTransform rect DrawRaw.rectTransform; RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, Input.mousePosition, null, out Vector2 local); float x Mathf.Lerp(0, _w, (local.x / rect.rect.width) 0.5f); float y Mathf.Lerp(0, _h, (local.y / rect.rect.height) 0.5f); x Mathf.Clamp(x, 0, _w - 1); y Mathf.Clamp(y, 0, _h - 1); return new Vector2(x, y); } // 渲染所有笔画 void RenderDraw() { ClearDrawTex(); // 历史正式线条 foreach (var s in _history) DrawLineList(s.pts, s.col); // 当前临时预览线条使用当前选中颜色 if (_isDraw _curPoints.Count 1) DrawLineList(_curPoints, _currentColor); _drawTex.Apply(); } void DrawLineList(ListVector2 pts, Color col) { for (int i 0; i pts.Count - 1; i) DrawBresenham(pts[i], pts[i 1], col, 3); } // 画线 void DrawBresenham(Vector2 p1, Vector2 p2, Color col, int size) { int x0 (int)p1.x, y0 (int)p1.y; int x1 (int)p2.x, y1 (int)p2.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) { DrawPoint(x0, y0, col, size); if (x0 x1 y0 y1) break; int e2 2 * err; if (e2 -dy) { err - dy; x0 sx; } if (e2 dx) { err dx; y0 sy; } } } void DrawPoint(int x, int y, Color col, int r) { for (int dx -r; dx r; dx) for (int dy -r; dy r; dy) { if (dx * dx dy * dy r * r) { int px x dx; int py y dy; if (px 0 px _w py 0 py _h) _drawTex.SetPixel(px, py, col); } } } void ClearDrawTex() { if (_drawTex null) return; Color[] clear new Color[_w * _h]; for (int i 0; i clear.Length; i) clear[i] Color.clear; _drawTex.SetPixels(clear); } void ClearAll() { _history.Clear(); _curPoints.Clear(); _isDraw false; ClearDrawTex(); } void SaveImg() { RenderTexture rt new RenderTexture(_w, _h, 24); rt.Create(); CamRaw.texture _camTex; DrawRaw.texture _drawTex; Texture2D saveTex new Texture2D(_w, _h); saveTex.ReadPixels(new Rect(0, 0, _w, _h), 0, 0); saveTex.Apply(); byte[] png saveTex.EncodeToPNG(); string path Application.persistentDataPath /cam_draw.png; System.IO.File.WriteAllBytes(path, png); Debug.Log(保存成功 path); } void OnDestroy() { if (_camTex ! null) _camTex.Stop(); } }ProjectorCanvasProjectorCanvas下面的DrawingOverlay直接复制上在的效果主屏可以显示而且投影可以显示标记。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻