Unity使用LineRender实现签名效果

本文为大家分享了Unity制作签名功能的具体代码,供大家参考,具体内容如下

前言:项目中需要做一个签名的功能,同时需要两个两个屏幕进行显示,但是都是在UI上,从网上查了大量资料。

找到两种方法:

1、修改图片像素点  但是是马赛克效果,不满足需求
2、使用LineRenderer 的3D签名制作出2D效果

改像素点:

先上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test : ObjBase
{

    public GameObject m_obj;
    private Texture2D m_tex;
    public Color m_color;
    public int size = 3;
    private Color[] m_textureColorsStart;

    public RawImage showImg;
    void Start()
    {
        if (Display.displays.Length > 1)
            Display.displays[1].Activate();
        if (Display.displays.Length > 2)
            Display.displays[2].Activate();
        m_tex = m_obj.GetComponent<MeshRenderer>().material.mainTexture as Texture2D;
        //从纹理中获取像素颜色
        m_textureColorsStart = m_tex.GetPixels();
        Debug.Log(m_tex.name);
    }

    void Update()
    {
        //Vector3 oldPos=Vector3.zero;
        //oldPos = Input.mousePosition;
        //Ray ray = uiCam.ScreenPointToRay(Input.mousePosition);
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Input.GetMouseButton(0))
        {
            // float m_magnitude = (Input.mousePosition - oldPos).magnitude;
            // Vector3 dir = Input.mousePosition - oldPos;
            if (Physics.Raycast(ray, out hit))
            {
                //在碰撞位置处的UV纹理坐标。
                Vector2 pixelUV = hit.textureCoord;
                //以像素为单位的纹理宽度
                pixelUV.x *= m_tex.width;
                pixelUV.y *= m_tex.height;
                //贴图UV坐标以右上角为原点
                for (float i = pixelUV.x - 1; i < pixelUV.x + size; i++)
                {
                    for (float j = pixelUV.y - 1; j < pixelUV.y + size; j++)
                    {
                        m_tex.SetPixel((int)i, (int)j, m_color);
                    }
                }
                Debug.Log(pixelUV);
                m_tex.Apply();
                showImg.texture = m_tex;
            }
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //还原
            m_tex.SetPixels(m_textureColorsStart);
            m_tex.Apply();
        }

        //在处理鼠标按下的记录下位置,抬起的时候记录下位置,取2个位置中间的位置发射射线
        //if (Input.GetMouseButtonDown(0))
        //{

        //}
        //if (Input.GetMouseButtonUp(0))
        //{

        //}
    }

    public void OnClick()
    {

        showImg.texture = m_tex;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjBase : MonoBehaviour
{

    public bool IsShow
    {
        get { return gameObject.activeSelf; }
    }

    // Use this for initialization
    void Start()
    {

    }

    /// <summary>
    /// 显示
    /// </summary>
    /// <param name="parameter"></param>
    public virtual void Show(object parameter = null)
    {

        gameObject.SetActive(true);
    }

    /// <summary>
    /// 隐藏
    /// </summary>
    /// <param name="parameter"></param>
    public virtual void Hide(object parameter = null)
    {
        gameObject.SetActive(false);
    }

}

Test脚本是用来修改像素点的,ObjBase只是一个根父类,控制显示和隐藏。

测试场景用的Quad,通过读取他的mainTexture对应的像素,进行修改,UI中的话就是将一张图片转成Texture2D形式,通过读取像素点,进行修改即可,同时还可以实现同步效果。

项目中的Hierarchy窗口设置:

项目需求:使用了两个画布,MainCamera照射Quad,两个UI相机分别照射两个画布,画布的Render Mode设置为Screen Space -Camera格式。GameObject挂载脚本,Quad用来修改其上的图片的像素点。

效果图:

使用LineRenderer   3D划线方法实现2D签名效果:

先上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Text;
using System.IO;
using UnityEngine.EventSystems;

public class Test5 : MonoBehaviour {

    public GameObject drawObj;
    private bool beginDraw;
    private GameObject obj;
    public Transform parent;
    public RawImage rawImg;
    public Camera UICam;
    public Camera main;//主相机和UI相机共同照射到的地方进行截图
    Color[] colors;
    Texture2D myTexture2D;
    public RawImage photo;

    public RawImage showImg;
    [SerializeField] private string _name;

    public RectTransform canvas1;

    public void SaveFile()
    {
        Camera mainCam;
        GameObject cam = Camera.main.gameObject;

        if (cam)
        {
            mainCam = cam.GetComponent<Camera>();
        }
        else
        {
            return;
        }

        RenderTexture renderTex;

        renderTex = new RenderTexture(Screen.width, Screen.height, 24);
        mainCam.targetTexture = renderTex;
        mainCam.Render();

         myTexture2D = new Texture2D(renderTex.width, renderTex.height);
        RenderTexture.active = renderTex;
        myTexture2D.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);

        myTexture2D.Apply();
        byte[] bytes = myTexture2D.EncodeToJPG();

        myTexture2D.Compress(true);
        myTexture2D.Apply();
        RenderTexture.active = null;

        File.WriteAllBytes(Application.dataPath + "/StreamingAssets/TextureTemp.png", bytes);
        mainCam.targetTexture = null;
        GameObject.Destroy(renderTex);
    }

    public void OnClick()
    {

        main.rect = new Rect(0, 0, 1, 1);
       CaptureCamera( main,new Rect(Screen.width * 0f, Screen.height * 0f, Screen.width * 1f, Screen.height * 1f));

    }

    /// <summary>
    /// 对相机截图。
    /// </summary>
    /// <returns>The screenshot2.</returns>
    /// <param name="camera">Camera.要被截屏的相机</param>
    /// <param name="rect">Rect.截屏的区域</param>
    Texture2D CaptureCamera(Camera camera,Rect rect)
    {
        // 创建一个RenderTexture对象
        RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);
        // 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
        camera.targetTexture = rt;
        camera.Render();
        //ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。
         //camera2.targetTexture = rt;
        // camera2.Render();
        //ps: -------------------------------------------------------------------  

        // 激活这个rt, 并从中中读取像素。
        RenderTexture.active = rt;
        Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
        screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素
        screenShot.Apply();

        // 重置相关参数,以使用camera继续在屏幕上显示
        camera.targetTexture = null;
       // camera2.targetTexture = null;
        //ps: camera2.targetTexture = null;
        RenderTexture.active = null; // JC: added to avoid errors
        GameObject.Destroy(rt);
        // 最后将这些纹理数据,成一个png图片文件
        byte[] bytes = screenShot.EncodeToPNG();
        string filename = Application.dataPath + string.Format("/Screenshot_{0}.png", _name);
        System.IO.File.WriteAllBytes(filename, bytes);
        Debug.Log(string.Format("截屏了一张照片: {0}", filename));
        showImg.texture = screenShot;
        main.rect = new Rect(0.25f, 0.35f, 0.5f, 0.5f);
        return screenShot;
    }

    void Start () {
        if (Display.displays.Length > 1)
            Display.displays[1].Activate();
        if (Display.displays.Length > 2)
            Display.displays[2].Activate();
    }

 // Update is called once per frame
 void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            beginDraw = true;
            obj = Instantiate(drawObj) as GameObject;
            obj.transform.parent = parent;
        }
        if (Input.GetMouseButtonUp(0))
        {
            beginDraw = false;
        }

        if (beginDraw)
        {
            Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10f);
            position = Camera.main.ScreenToWorldPoint(position);
            //Vector3 localPoint;
            //if(RectTransformUtility.ScreenPointToWorldPointInRectangle(canvas1, position, null, out localPoint))
            //{
            //    position = localPoint;
            //}

            DrawText dt = obj.GetComponent<DrawText>();
            dt.points.Add(position);
            dt.Draw();
            dt.line.startColor = Color.yellow;
            dt.line.endColor = Color.yellow;
            dt.line.startWidth = 0.03f;
            dt.line.endWidth = 0.03f;
        }

    }
}

Test5是划线和截取签名的操作,绑定在空物体上,OnClick函数绑定在按钮上

Line:制作签名预制体

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DrawText : MonoBehaviour {

    public List<Vector3> points = new List<Vector3>();
    public  LineRenderer line;
    private void Awake()
    {
        line = GetComponent<LineRenderer>();
    }
    public  void Draw()
    {
        line.positionCount = points.Count;
        for (int i = 0; i < points.Count; i++)
        {
            line.SetPosition(i, points[i]);
            line.startWidth =2f;
            line.endWidth =2f;
        }
    }
    // Use this for initialization
    void Start () {

 }

 // Update is called once per frame
 void Update () {

 }
}

Draw Text脚本挂在预制体Line上,Line 添加LineRenderer组件,同时Material中加入自己创建的材质球

项目需求:Hierarchy窗口设置

和上面一种方法一样,也是两个画布,两个UI相机,同时需要一个MainCamera

parent为空物体,用来作为根节点,将签名时实时生成的预制体放在其下面,作为子节点,方便后面进行销毁,重新签名。

重点:

第二种方法使用的是特定相机照射画面进行截图,Test5中的CaptureCamera方法就是截取主相机照射到的画面。由于签名不能进行全屏进行截图,只能部分截图,类似相面的画面

下面会有一些常规的功能按钮,重新签名,保存签名等等操作,这些操作就是在UI上进行签名。

所以,通过修改MainCamera的Viewport Rect窗口来进行截图,同时能够实现正常的签名操作。

MainCamera的Viewport Rect设置:

运行刚开始:

通过设置这个属性,可以使签名界面呈现上一个图的效果,前面是UI层,后面是3D层。

然而在截屏图的时候如果始终保持Viewport Rect是上面的设置,则截图的时候仍把周围的黑色部分也截取出来,刚开始以为特定相机照射截图只截取Viewport Rect中的图像,后来测试是周围的所有黑色部分也截取了,这样就不满足要求。

所以,在代码中签字 的时候保持上面的设置,截图之前main.rect = new Rect(0, 0, 1, 1);设置成全屏,截好之后重新回复成原来的设置  main.rect = new Rect(0.25f, 0.35f, 0.5f, 0.5f);,截图完成之后将签名图片赋值给第二个屏幕画布中的RawImage进行展示。

达到效果。结合UI实际签名过程中

中间的白色部分,通过设置MainCamera中的Camera组件中的Background(设置为白色)以及天空盒(Windows->Lighting->Settings->Scene->Skybox Material设置为空),设置为需要的颜色。UI制作的时候需要签名的部分制作成透明的即可。

效果图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Unity使用LineRender断笔写字

    做多媒体项目时,经常会最后来个客户签名并保存之类的,签名保存之前的博客Unity3d截图方法合集有介绍过了,今天闲着把断笔写字的也贴出来吧,以前用leap motion时尝试用 leap motion演示中的食指写字,当时的写字其实只能一笔画,说白了其实就是个寿命无限长的拖尾,虽然效果不太好,但是很流畅,尝试过用leap motion断笔写字,但是效果不好,很容易误写,然后就产生了此方法,就是鼠标或者触摸屏写字了. 讲一下思路,就是不断的将鼠标的屏幕坐标转换成世界坐标,然后用LineRender

  • C#自定义签名章实现方法

    本文实例讲述了C#自定义签名章实现方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; namespace WfpApp { public class DrawCac

  • C#创建自签名认证文件的方法

    本文实例讲述了C#创建自签名认证文件的方法.分享给大家供大家参考.具体如下: using System; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using SecureString = System.Security.SecureString; using RuntimeHelpers = System.Runtime.CompilerServices.

  • c# 给pdf添加数字签名的步骤

    数字签名广泛用于保护PDF文档,可见数字签名在日常生活中是相当重要的.在这篇文章中我将与大家分享如何给PDF文件添加可见的数字签名. 首先我下载了一个由E-iceblue公司开发的免费版的PDF组件-Free Spire.PDF,控件安装好后,再通过下面所提及的路径把Bin文件夹里的Spire.PDF.dll添加为引用. 路径:"...\Spire.pdf-fe\Bin\NET4.0\ Spire.PDF.dll" 接下来我将提供一些代码片段来向大家展示如何添加可见的数字签名: 步骤1

  • Unity使用LineRender实现签名效果

    本文为大家分享了Unity制作签名功能的具体代码,供大家参考,具体内容如下 前言:项目中需要做一个签名的功能,同时需要两个两个屏幕进行显示,但是都是在UI上,从网上查了大量资料. 找到两种方法: 1.修改图片像素点  但是是马赛克效果,不满足需求 2.使用LineRenderer 的3D签名制作出2D效果 改像素点: 先上代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using

  • unity实现屏幕上写字效果

    本文实例为大家分享了unity实现屏幕上写字效果的具体代码,供大家参考,具体内容如下 先建立一个RawImage,然后再在这个图片上加个LineRenderer组件,再建个材质球,把材质球的Shader改成Particles/Additive,把材质球拖给LineRenderer组件的Materials/Element 0(不拖也可以),最后再把代码拖给空物体即可,代码的Target是RawImage,下面的代码 using System.Collections; using System.Co

  • Unity实现物体左右移动效果

    本文实例为大家分享了Unity实现物体左右移动效果的具体代码,供大家参考,具体内容如下 效果如下 代码: using UnityEngine; using System.Collections; //Add this script to the platform you want to move. //左右移动的平台 public class MovingPlatform : MonoBehaviour { //Platform movement speed.平台移动速度 public floa

  • vue+element加入签名效果(移动端可用)

    下面介绍为了方便就把项目的文件叫作父组件,然后签名的那个组件叫作子组件 ! 如有不太明白的地方,多看看代码注释.为细节地方 1. 首先根据element ui 在父组件中设置好diglog弹框,并且在全局样式下,自定义样式 <div class="canva" @click="centerDialogVisible = true"> // click绑定的方法是element提供的 centerDialogVisibe=true 是点击时弹框出现 <

  • Unity实现3D循环滚动效果

    本文实例为大家分享了Unity实现3D循环滚动效果展示的具体代码,供大家参考,具体内容如下 然后通过SetDepthAndPosition这个方法,实现图片的空间空间展开 Z轴和Y轴,系数是一样的 经过上面设置,空间就摆开了 using UnityEngine; using System.Collections; using System.Collections.Generic; public class SelectRole : MonoBehaviour { public GameObjec

  • Unity实现卡牌翻动效果

    本文实例为大家分享了Unity实现卡牌翻动效果展示的具体代码,供大家参考,具体内容如下 事实上这是项目需要,我改的一个代码,实际上就是利用unity的一些基础属性实现其效果.啥也不多说了,先上原代码: /// Credit Mrs. YakaYocha /// Sourced from - https://www.youtube.com/channel/UCHp8LZ_0-iCvl-5pjHATsgw /// Please donate: https://www.paypal.com/cgi-b

  • Unity使用摄像机实现望远镜效果

    本文实例为大家分享了Unity使用摄像机实现望远镜效果的具体代码,供大家参考,具体内容如下 听起来挺酷炫,其实超简单,就是控制摄像机的fieldOfView: using UnityEngine; using System.Collections; public class TelesopicView : MonoBehaviour { public float zoomLevel = 2.0f; public float zoomInSpeed = 100.0f; public float z

  • Unity Shader实现描边OutLine效果

    本文实例为大家分享了Unity Shader实现描边OutLine效果的具体代码,供大家参考,具体内容如下 Shader实现描边流程大致为:对模型进行2遍(2个pass)绘制,第一遍(描边pass)在vertex shader中对模型沿顶点法线方向放大,fragment shader设置输出颜色为描边颜色:第二遍正常绘制模型,除被放大的部分外,其余被覆盖,这样就有了描边的效果. 实现代码如下: Shader "Custom/OutlineShader" { Properties { _

  • unity实现车方向盘转动效果

    本文实例为大家分享了unity实现车方向盘转动效果的具体代码,供大家参考,具体内容如下 效果: C#脚本如下: using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class NewBehaviourScript : MonoBehaviour, IDragHandler,IBeginD

  • Unity实现老虎机滚动抽奖效果的示例代码

    直接看下效果图吧: 制作思路: 设计四张图片,五个点,每个图片同时向下一个点移动,到最后一个就回到0号点,以此循环. 场景搭建: 创建Image命名为Bg作为电视框背景: 创建Image命名Mask并添加Mask组件作为电视框内容显示遮罩框: 创建四个Image作为滚动图片: 创建开始抽奖按钮: PS:实际项目中可以根据需求来动态修改图片显示,以达到的控制每次抽奖奖品内容. 源码分享: using System.Collections; using UnityEngine; using Unit

随机推荐