Unity实现3D书写功能
程序员文章站
2024-03-25 23:55:46
...
Unity实现3D书写功能
利用LineRender实现书写功能
利用LineRender的点位功能实现画线功能
画板的预制排版
画板的脚本放置与Board上并添加BoxCollider
UICanvasTemp为临时画板层
UICanvasSave为最终画板层
UICanvasTemp与UICanvasSave中的Comtent采用RawImage
UICamera与UICanvasTemp中的Comtent使用RenderTexture进行关联,使UICanvasTemp中的Comtent的图片始终为UICamera的图片
UICanvasSave中的Comtent的图片为LineRender的保存图片
画板的缺陷
- 需要保证UICanvasTemp和UICanvasSave的大小全部占满UICamera的区间,否则会出现BUG
- UICanvasTemp的Layer层需要为Default
- UICanvasTemp的Layer层需要为DrawUI
- UICamera为画板的专用相机,只看画板层DrawUI
- 场景中的主相机不可场景DrawUI层
- 画布Canvas的RenderMode的类型必须为WorldSpace否则主相机无法查看
画板的优化
- UICanvasSave的作用为避免LineRender中的点位过多导致程序卡死,所有每一笔画完都需要对LineRender的内容进行保存.或当LineRender的点位达到一定的数量进行临时保存.或当相邻点位的距离较小时忽略点位的写入
- 画布Canvas的RenderMode的类型可以用ScreenSpace-Camera来确保画布的大小占满UICamera的区间
画板功能代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.UI;
public class DrawBoard : MonoBehaviour
{
public Transform mRoot;
public Camera mUICamera;
public Canvas mUICanvasSave;
public Canvas mUICanvasTemp;
public RawImage mSaveDrawCanvas;
public RawImage mTempDrawCanvas;
Dictionary<uint, LineRenderer> mAllLine = new Dictionary<uint, LineRenderer>();
List<LineRenderer> mLastLine = new List<LineRenderer>();
/// <summary>
/// 开始绘画参数准备
/// </summary>
/// <param name="varPenID">笔的ID,方便与多笔同时进行作画</param>
/// <param name="size">笔的粗细</param>
/// <param name="color">笔的颜色</param>
public void StartDraw(uint varPenID, float size, Color color, Vector3 pos)
{
if (mAllLine.ContainsKey(varPenID))
{
return;
}
LineRenderer Line;
if (mLastLine.Count != 0)
{
Line = mLastLine[0];
mLastLine.RemoveAt(0);
}
else
{
Line = NewGameobject<LineRenderer>("Line", mRoot);
Line.gameObject.layer = LayerMask.NameToLayer("DrawUI");
Line.material = new Material(Shader.Find("Unlit/Color"));
Line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
}
Line.material.SetColor("_Color", color);
Line.widthMultiplier = size;
Line.positionCount = 2;
Line.SetPosition(0, pos);
Line.SetPosition(1, pos);
Line.gameObject.SetActive(true);
mAllLine.Add(varPenID, Line);
}
/// <summary>
/// 进行绘画
/// </summary>
/// <param name="varPen">笔的ID,方便与多笔同时进行作画</param>
/// <param name="pos">绘画的点位</param>
public void Drawing(uint varPenID, Vector3 pos)
{
if (!mAllLine.ContainsKey(varPenID))
{
return;
}
LineRenderer Line = mAllLine[varPenID];
Line.positionCount += 1;
Line.SetPosition(Line.positionCount - 1, pos);
}
/// <summary>
/// 结束绘画
/// </summary>
/// <param name="varPen">笔的ID,方便与多笔同时进行作画</param>
public void EndDraw(uint varPenID)
{
if (!mAllLine.ContainsKey(varPenID))
{
return;
}
LineRenderer varLine = mAllLine[varPenID];
mAllLine.Remove(varPenID);
//进行图画保存
SaveDraw();
varLine.gameObject.SetActive(false);
mLastLine.Add(varLine);
}
/// <summary>
/// 对相机渲染的图片进行存储进指定的图片中
/// </summary>
private void SaveDraw()
{
if (mSaveDrawCanvas == null || mTempDrawCanvas == null)
return;
foreach (var item in mAllLine)
{
item.Value.gameObject.SetActive(false);
}
Texture2D screenShot = CaptureScreen(mUICamera);
mSaveDrawCanvas.texture = screenShot;
mSaveDrawCanvas.color = Color.white;
foreach (var item in mAllLine)
{
item.Value.gameObject.SetActive(true);
}
}
/// <summary>
/// 将相机看到的画面转换成Texture2D
/// </summary>
/// <param name="came"></param>
/// <param name="r"></param>
/// <returns></returns>
public Texture2D CaptureScreen(Camera camera)
{
camera.Render();
RenderTexture.active = camera.targetTexture;
Rect r = new Rect(Vector2.zero, new Vector2(camera.activeTexture.width, camera.targetTexture.height));
#if UNITY_2017
Texture2D screenShot = new Texture2D((int)r.width, (int)r.height, TextureFormat.RGBA32, false);
#elif UNITY_2019
Texture2D screenShot = new Texture2D((int)r.width, (int)r.height, GraphicsFormat.R32G32B32A32_SFloat, TextureCreationFlags.None);
#endif
screenShot.ReadPixels(r, 0, 0);
screenShot.Apply();
RenderTexture.active = null;
return screenShot;
}
private T NewGameobject<T>(string varContent,Transform varParent) where T:Component
{
GameObject TempGame = new GameObject(varContent);
TempGame.transform.SetParent(varParent);
TempGame.transform.localPosition = Vector3.zero;
TempGame.transform.localEulerAngles = Vector3.zero;
TempGame.transform.localScale = Vector3.one;
T TempT = TempGame.AddComponent<T>();
return TempT;
}
}
画笔的功能实现
using UnityEngine;
public class DrawPen : MonoBehaviour
{
/// <summary>
/// 笔的ID
/// </summary>
public uint mID;
/// <summary>
/// 笔的输入大小
/// </summary>
public float mSize = 0.01f;
/// <summary>
/// 笔的输入颜色
/// </summary>
public Color mPenColor = Color.white;
/// <summary>
/// 笔的输入类型
/// </summary>
public PenType mPenType = PenType.Collider;
private void Awake()
{
ColliderDrawInit();
}
#region ColliderDraw//使用碰撞实现画笔的输入功能
private void ColliderDrawInit()
{
if (mPenType != PenType.Collider)
return;
BoxCollider box = this.GetComponent<BoxCollider>();
if (box == null)
{
box = this.gameObject.AddComponent<BoxCollider>();
}
box.isTrigger = true;
Rigidbody Rig = this.GetComponent<Rigidbody>();
if (Rig == null)
{
Rig = this.gameObject.AddComponent<Rigidbody>();
}
Rig.isKinematic = true;
Rig.useGravity = false;
}
private void OnTriggerEnter(Collider other)
{
if (mPenType != PenType.Collider)
return;
DrawBoard board = other.GetComponent<DrawBoard>();
if (board == null)
return;
Vector3 pos = other.ClosestPoint(this.transform.position);
board.StartDraw(mID, mSize, mPenColor, pos);
}
private void OnTriggerStay(Collider other)
{
if (mPenType != PenType.Collider)
return;
DrawBoard board = other.GetComponent<DrawBoard>();
if (board == null)
return;
Vector3 pos = other.ClosestPoint(this.transform.position);
board.Drawing(mID, pos);
}
private void OnTriggerExit(Collider other)
{
if (mPenType != PenType.Collider)
return;
DrawBoard board = other.GetComponent<DrawBoard>();
if (board == null)
return;
board.EndDraw(mID);
}
#endregion
#region RayDraw//使用射线实现画笔的输入功能
#endregion
public enum PenType
{
Collider,
Ray,
}
}
上一篇: 方法的定义、调用、重载
推荐阅读
-
Unity实现3D书写功能
-
Unity 基础 之 在 UGUI 上简单实现VideoPlayer视频播放的功能,简单暂停播放/显示视频名称/显示时长/拖拽播放等
-
unity Physics.Raycast 射线进入离开collider、开始结束碰撞检测功能的实现
-
Unity3D实现批量下载图片功能
-
jQuery实现经典的网页3D轮播图封装功能【附源码下载】
-
Unity实现扇形Slider进度条加载功能
-
Unity实现类似于苹果视频播放器视频播放进度条及声音进度条拖拽功能
-
Unity通过脚本添加组件实现鼠标滑过3D物体高亮(附Demo)
-
Unity使用Vuforia实现AR脱卡功能
-
Unity3D实现批量下载图片功能