Unity怎么實(shí)現(xiàn)VR中在黑板上寫字效果

這篇文章主要為大家展示了“Unity怎么實(shí)現(xiàn)VR中在黑板上寫字效果”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Unity怎么實(shí)現(xiàn)VR中在黑板上寫字效果”這篇文章吧。

專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)臨漳免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了近千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

具體內(nèi)容如下

一、工具

1.開發(fā)用的是Unity 5.6.2版本

2.VR中的物理交互用的是VRTK插件,這個(gè)插件集成了比較好的物理交互功能;

3.HTC Vive

二、概述

實(shí)現(xiàn)的功能: 在一個(gè)白板上,用不同顏色的筆,在白板畫出任何想要的圖形;

因?yàn)橹皇且粋€(gè)初級(jí)篇所以只是用兩個(gè)腳本簡(jiǎn)單的實(shí)現(xiàn),而且并沒有黑板擦等功能 ,也不能兩個(gè)筆同時(shí)畫畫,這些功能將會(huì)在未來的升級(jí)篇中寫出;

三、知識(shí)點(diǎn)

其實(shí)這個(gè)功能很簡(jiǎn)單,只是簡(jiǎn)單的運(yùn)用Unity Texure2D類中的兩個(gè)函數(shù):

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

前面4個(gè)參數(shù)相當(dāng)于一個(gè)矩形,x和y就是矩形的左下角的那個(gè)點(diǎn),blockWidth和blockHeight分別是矩形的寬和高,這個(gè)矩形所代表的范圍就是blockWidth*blockHeight個(gè)像素所在的位置,不妨稱這個(gè)矩形范圍為一個(gè)色塊;

colors這個(gè)參數(shù)的大小必須等于blockWidth*blockHeight,因?yàn)檫@個(gè)方法就是給坐標(biāo)(x,y)開始,從左到右,從下到上,一行一行的對(duì)矩形范圍內(nèi)的每個(gè)像素賦值;

也就是把colors[0]~colors[blockWidth - 1]分別賦值到坐標(biāo)為(x,y)~(x + blockWidth,y)的像素,以此類推;

最后一個(gè)參數(shù),因?yàn)槲覀冇玫膱D片把Generate Min Maps這個(gè)選項(xiàng)關(guān)閉了,所以用默認(rèn)的可選參數(shù)0;

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

當(dāng)對(duì)圖片改動(dòng)完成以后,需要調(diào)用這個(gè)方法,才能讓改動(dòng)真正的應(yīng)用在圖片上;

四、場(chǎng)景搭建

1.畫板

在場(chǎng)景中建一個(gè)Quad,把它的x和y方向的Scale分別設(shè)置為1.92和1.08(或者其它尺寸);注意這個(gè)Quad一定要用Mesh Collider作為碰撞體,不然到時(shí)候射線獲取的紋理坐標(biāo)有誤,并為它設(shè)置一個(gè)Tag為Board;

2.筆

建一個(gè)尺寸合適的筆,創(chuàng)建一個(gè)空的子物體,命名為SnapPoint,并設(shè)置SnapPoint的Z方向指向筆尖方向,這個(gè)子物體就是,手柄拿筆的位置就是,并且保證筆的姿態(tài)是相當(dāng)于人正常拿筆的樣子;

3.其它

創(chuàng)建一個(gè)放筆的物體,讓筆處于比較好拿的位置;

我的場(chǎng)景中代表畫板的是WhiteBoard下的Board物體;

五、代碼實(shí)現(xiàn)功能

這個(gè)腳本是掛在代表畫板的物體上的:

using System.Linq;using UnityEngine;/// <summary>/// 畫板/// </summary>public class Board : MonoBehaviour{ //當(dāng)畫筆移動(dòng)速度很快時(shí),為了不出現(xiàn)斷斷續(xù)續(xù)的點(diǎn),所以需要對(duì)兩個(gè)點(diǎn)之間進(jìn)行插值,lerp就是插值系數(shù) [Range(0, 1)] public float lerp = 0.05f; //初始化背景的圖片 public Texture2D initailizeTexture; //當(dāng)前背景的圖片 private Texture2D currentTexture; //畫筆所在位置映射到畫板圖片的UV坐標(biāo) private Vector2 paintPos; private bool isDrawing = false;//當(dāng)前畫筆是不是正在畫板上 //離開時(shí)畫筆所在的位置  private int lastPaintX; private int lastPaintY; //畫筆所代表的色塊的大小 private int painterTipsWidth = 30; private int painterTipsHeight = 15; //當(dāng)前畫板的背景圖片的尺寸 private int textureWidth; private int textureHeight; //畫筆的顏色 private Color32[] painterColor; private Color32[] currentColor; private Color32[] originColor; private void Start() { //獲取原始圖片的大小  Texture2D originTexture = GetComponent<MeshRenderer>().material.mainTexture as Texture2D; textureWidth = originTexture.width;//1920  textureHeight = originTexture.height;//1080 //設(shè)置當(dāng)前圖片 currentTexture = new Texture2D(textureWidth, textureHeight, TextureFormat.RGBA32, false, true); currentTexture.SetPixels32(originTexture.GetPixels32()); currentTexture.Apply(); //賦值給黑板 GetComponent<MeshRenderer>().material.mainTexture = currentTexture; //初始化畫筆的顏色 painterColor = Enumerable.Repeat<Color32>(new Color32(255, 0, 0, 255), painterTipsWidth * painterTipsHeight).ToArray<Color32>(); } private void LateUpdate() { //計(jì)算當(dāng)前畫筆,所代表的色塊的一個(gè)起始點(diǎn) 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);  //如果快速移動(dòng)畫筆的話,會(huì)出現(xiàn)斷續(xù)的現(xiàn)象,所以要插值  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; } } /// <summary> /// 設(shè)置當(dāng)前畫筆所在的UV位置 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void SetPainterPositon(float x, float y) { paintPos.Set(x, y); } /// <summary> /// 畫筆當(dāng)前是不是在畫畫 /// </summary> public bool IsDrawing { get {  return isDrawing; } set {  isDrawing = value; } } /// <summary> /// 使用當(dāng)前正在畫板上的畫筆的顏色 /// </summary> /// <param name="color"></param> 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{ /// <summary> /// 用于比較兩個(gè)Color32類型是不是同種顏色 /// </summary> /// <param name="origin"></param> /// <param name="compare"></param> /// <returns></returns> 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; }}

下面這個(gè)腳本是掛在畫筆上的:

using UnityEngine;public class Painter : MonoBehaviour{ /// <summary> /// 畫筆的顏色 /// </summary> public Color32 penColor; public Transform rayOrigin; private RaycastHit hitInfo; //這個(gè)畫筆是不是正在被手柄抓著 private bool IsGrabbing; private static Board board;//設(shè)置成類型的成員,而不是類型實(shí)例的成員,因?yàn)樗挟嫻P都是用的同一個(gè)board private void Start() { //將畫筆部件設(shè)置為畫筆的顏色,用于識(shí)別這個(gè)畫筆的顏色 foreach (var renderer in GetComponentsInChildren<MeshRenderer>()) {  if (renderer.transform == transform)  {  continue;  }  renderer.material.color = penColor; } if (!board) {  board = FindObjectOfType<Board>(); }  } private void Update() { Ray r = new Ray(rayOrigin.position, rayOrigin.forward); if (Physics.Raycast(r, out hitInfo, 0.1f)) {  if (hitInfo.collider.tag == "Board")  {  //設(shè)置畫筆所在位置對(duì)應(yīng)畫板圖片的UV坐標(biāo)   board.SetPainterPositon(hitInfo.textureCoord.x, hitInfo.textureCoord.y);  //當(dāng)前筆的顏色  board.SetPainterColor(penColor);  board.IsDrawing = true;  IsGrabbing = true;  } } else if(IsGrabbing) {  board.IsDrawing = false;  IsGrabbing = false; } }}

以上是“Unity怎么實(shí)現(xiàn)VR中在黑板上寫字效果”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

文章名稱:Unity怎么實(shí)現(xiàn)VR中在黑板上寫字效果
分享URL:http://muchs.cn/article30/ihghso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營(yíng)銷型網(wǎng)站建設(shè)網(wǎng)站維護(hù)、關(guān)鍵詞優(yōu)化網(wǎng)站營(yíng)銷、小程序開發(fā)、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化