千家信息网

Unity怎么实现VR中在黑板上写字效果

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章主要为大家展示了"Unity怎么实现VR中在黑板上写字效果",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Unity怎么实现VR中在黑板上写字效果"
千家信息网最后更新 2026年11月03日Unity怎么实现VR中在黑板上写字效果

这篇文章主要为大家展示了"Unity怎么实现VR中在黑板上写字效果",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Unity怎么实现VR中在黑板上写字效果"这篇文章吧。

具体内容如下

一、工具

1.开发用的是Unity 5.6.2版本

2.VR中的物理交互用的是VRTK插件,这个插件集成了比较好的物理交互功能;

3.HTC Vive

二、概述

实现的功能: 在一个白板上,用不同颜色的笔,在白板画出任何想要的图形;

因为只是一个初级篇所以只是用两个脚本简单的实现,而且并没有黑板擦等功能 ,也不能两个笔同时画画,这些功能将会在未来的升级篇中写出;

三、知识点

其实这个功能很简单,只是简单的运用Unity Texure2D类中的两个函数:

public void SetPixels32(int x, int y, int blockWidth, int blockHeight, Color32[] colors, int miplevel = 0);

前面4个参数相当于一个矩形,x和y就是矩形的左下角的那个点,blockWidth和blockHeight分别是矩形的宽和高,这个矩形所代表的范围就是blockWidth*blockHeight个像素所在的位置,不妨称这个矩形范围为一个色块;

colors这个参数的大小必须等于blockWidth*blockHeight,因为这个方法就是给坐标(x,y)开始,从左到右,从下到上,一行一行的对矩形范围内的每个像素赋值;

也就是把colors[0]~colors[blockWidth - 1]分别赋值到坐标为(x,y)~(x + blockWidth,y)的像素,以此类推;

最后一个参数,因为我们用的图片把Generate Min Maps这个选项关闭了,所以用默认的可选参数0;

public void Apply(bool updateMipmaps = true, bool makeNoLongerReadable = false);

当对图片改动完成以后,需要调用这个方法,才能让改动真正的应用在图片上;

四、场景搭建

1.画板

在场景中建一个Quad,把它的x和y方向的Scale分别设置为1.92和1.08(或者其它尺寸);注意这个Quad一定要用Mesh Collider作为碰撞体,不然到时候射线获取的纹理坐标有误,并为它设置一个Tag为Board;

2.笔

建一个尺寸合适的笔,创建一个空的子物体,命名为SnapPoint,并设置SnapPoint的Z方向指向笔尖方向,这个子物体就是,手柄拿笔的位置就是,并且保证笔的姿态是相当于人正常拿笔的样子;

3.其它

创建一个放笔的物体,让笔处于比较好拿的位置;

我的场景中代表画板的是WhiteBoard下的Board物体;

五、代码实现功能

这个脚本是挂在代表画板的物体上的:

using System.Linq;using UnityEngine;///

/// 画板/// public class Board : MonoBehaviour{ //当画笔移动速度很快时,为了不出现断断续续的点,所以需要对两个点之间进行插值,lerp就是插值系数 [Range(0, 1)] public float lerp = 0.05f; //初始化背景的图片 public Texture2D initailizeTexture; //当前背景的图片 private Texture2D currentTexture; //画笔所在位置映射到画板图片的UV坐标 private Vector2 paintPos; private bool isDrawing = false;//当前画笔是不是正在画板上 //离开时画笔所在的位置 private int lastPaintX; private int lastPaintY; //画笔所代表的色块的大小 private int painterTipsWidth = 30; private int painterTipsHeight = 15; //当前画板的背景图片的尺寸 private int textureWidth; private int textureHeight; //画笔的颜色 private Color32[] painterColor; private Color32[] currentColor; private Color32[] originColor; private void Start() { //获取原始图片的大小 Texture2D originTexture = GetComponent().material.mainTexture as Texture2D; textureWidth = originTexture.width;//1920 textureHeight = originTexture.height;//1080 //设置当前图片 currentTexture = new Texture2D(textureWidth, textureHeight, TextureFormat.RGBA32, false, true); currentTexture.SetPixels32(originTexture.GetPixels32()); currentTexture.Apply(); //赋值给黑板 GetComponent().material.mainTexture = currentTexture; //初始化画笔的颜色 painterColor = Enumerable.Repeat(new Color32(255, 0, 0, 255), painterTipsWidth * painterTipsHeight).ToArray(); } private void LateUpdate() { //计算当前画笔,所代表的色块的一个起始点 int texPosX = (int)(paintPos.x * (float)textureWidth - (float)(painterTipsWidth / 2)); int texPosY = (int)(paintPos.y * (float)textureHeight - (float)(painterTipsHeight / 2)); if (isDrawing) { //改变画笔所在的块的像素值 currentTexture.SetPixels32(texPosX, texPosY, painterTipsWidth, painterTipsHeight, painterColor); //如果快速移动画笔的话,会出现断续的现象,所以要插值 if (lastPaintX != 0 && lastPaintY != 0) { int lerpCount = (int)(1 / lerp); for (int i = 0; i <= lerpCount; i++) { int x = (int)Mathf.Lerp((float)lastPaintX, (float)texPosX, lerp); int y = (int)Mathf.Lerp((float)lastPaintY, (float)texPosY, lerp); currentTexture.SetPixels32(x, y, painterTipsWidth, painterTipsHeight, painterColor); } } currentTexture.Apply(); lastPaintX = texPosX; lastPaintY = texPosY; } else { lastPaintX = lastPaintY = 0; } } /// /// 设置当前画笔所在的UV位置 /// /// /// public void SetPainterPositon(float x, float y) { paintPos.Set(x, y); } /// /// 画笔当前是不是在画画 /// public bool IsDrawing { get { return isDrawing; } set { isDrawing = value; } } /// /// 使用当前正在画板上的画笔的颜色 /// /// public void SetPainterColor(Color32 color) { if (!painterColor[0].IsEqual(color)) { for (int i = 0; i < painterColor.Length; i++) { painterColor[i] = color; } } }}public static class MethodExtention{ /// /// 用于比较两个Color32类型是不是同种颜色 /// /// /// /// public static bool IsEqual(this Color32 origin, Color32 compare) { if (origin.g == compare.g && origin.r == compare.r) { if (origin.a == compare.a && origin.b == compare.b) { return true; } } return false; }}

下面这个脚本是挂在画笔上的:

using UnityEngine;public class Painter : MonoBehaviour{ ///

/// 画笔的颜色 /// public Color32 penColor; public Transform rayOrigin; private RaycastHit hitInfo; //这个画笔是不是正在被手柄抓着 private bool IsGrabbing; private static Board board;//设置成类型的成员,而不是类型实例的成员,因为所有画笔都是用的同一个board private void Start() { //将画笔部件设置为画笔的颜色,用于识别这个画笔的颜色 foreach (var renderer in GetComponentsInChildren()) { if (renderer.transform == transform) { continue; } renderer.material.color = penColor; } if (!board) { board = FindObjectOfType(); } } private void Update() { Ray r = new Ray(rayOrigin.position, rayOrigin.forward); if (Physics.Raycast(r, out hitInfo, 0.1f)) { if (hitInfo.collider.tag == "Board") { //设置画笔所在位置对应画板图片的UV坐标 board.SetPainterPositon(hitInfo.textureCoord.x, hitInfo.textureCoord.y); //当前笔的颜色 board.SetPainterColor(penColor); board.IsDrawing = true; IsGrabbing = true; } } else if(IsGrabbing) { board.IsDrawing = false; IsGrabbing = false; } }}

以上是"Unity怎么实现VR中在黑板上写字效果"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

画笔 图片 画板 颜色 位置 功能 就是 所在 矩形 黑板 两个 代表 坐标 物体 像素 内容 参数 效果 写字 只是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 华服互联网科技靠谱吗 科技金融是不是互联网金融 互联网最新的科技有限公司 隆华科技工业互联网 科技互联网的估值 互联网科技革命什么开始 苏州铭阳互联网科技有限公司 青海科技产业互联网发展 长沙茂晟互联网科技有限公司 互联网金融科技名词解释 伊宁互联网科技做什么的 山东子淼互联网科技有限公司 互联网风格科技公司名称 半导体行业属于互联网高科技类吗 互联网公司属于科技吗 艺电能源互联网科技有限公司招聘 中国科技和美国互联网 北京军民互联网科技公司 科技互联网公司两年变化 平安好医生打造互联网科技医疗 互联网科技工作委员会副主任毛军 北京互联网科技公司 互联网医疗科技 国外互联网科技网站 中正互联网科技招聘 玖二柒互联网科技公司待遇 赶超互联网科技 微信多开 中科明德北京互联网科技 广州富喜互联网络科技 领航科技大厦互联网公司
0