AR涂涂乐⭐三、 C#实现识别图进入扫描框显示绿色,未进入为红色功能

2024-08-14 15:44:32 浏览数 (4)

代码语言:javascript复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;   //因为屏幕自适度原因,使用了Canvas的Canvas Scaler组件(Canvas来自Unity的UI)

public class Area : MonoBehaviour {

    public Material Red_Mate;
    public Material Green_Mate;
    public Material Tran_Mate;

    private CanvasScaler Cans;  //申请变量储存UI屏幕自适度(长&宽)的缩放组件
    private float X_Sc;   //申请浮点型变量储存实际的缩放比例(实际的/Unity使用的)

    //记录扫描框坐标  二维!
    private Vector2 TopLeft_UI, BottomLeft_UI, TopRight_UI, BottomRight_UI;   //我们可以看到Vector2是淡蓝色,代表一个类,所以需要实例化。
    //记录面片的世界坐标  三维!
    private Vector3 TopLeft_pl_w, BottomLeft_pl_w, TopRight_pl_w, BottomRight_pl_w;

    //获取面片二维方向上高和宽的长度!
    private Vector2 PlaneWH;

    //记录面片的屏幕坐标
    Vector2 TopLeft_pl_sc, BottomLeft_pl_sc, TopRight_pl_sc, BottomRight_pl_sc;

    // Use this for initialization
    void Start () {
        Cans = GameObject.Find("Canvas").gameObject.GetComponent<CanvasScaler>();  //获取屏幕自适度,GameObject指GameObject.Find("Canvas")这个物体,gameObject指GameObject这个物体。待测试去掉gameOgject是否可运行。
        X_Sc = Screen.width / Cans.referenceResolution.x;
        //为什么是除以x呢?因为在unity中,UI Scale Mode选的是Scale with Screen Scale,根据屏幕比例自动缩放,并且下方的
        //Screen Match Mode——Match Width or Height滑动条中,我们将滑动条拖到了最左侧的Width,所以是用屏幕宽度/自定义的宽度。
    }
	
	// Update is called once per frame
	void Update () {

        //计算扫描框四个点位置
        TopLeft_UI = new Vector2(Screen.width - 400*X_Sc, Screen.height   300 * X_Sc) * 0.5f;  //因为不确定屏幕分辨率大小,所以需先获取;记得f!
        BottomLeft_UI = new Vector2(Screen.width - 400 * X_Sc, Screen.height - 300 * X_Sc) * 0.5f;  //屏幕左下角(0,0),向右x轴,向上y轴
        TopRight_UI = new Vector2(Screen.width   400 * X_Sc, Screen.height   300 * X_Sc) * 0.5f;
        BottomRight_UI = new Vector2(Screen.width   400 * X_Sc, Screen.height - 300 * X_Sc) * 0.5f;

        //我们需要的是面片在空间中的大小,但我们获取到的是面片的实际大小,它本身缩放了0.1倍,它父集缩放50倍,所以他在空间实际是扩大了5倍,所以要*5。
        PlaneWH = new Vector2(gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x, gameObject.GetComponent<MeshFilter>().mesh.bounds.size.z)*5*0.5f;   //空间中x、z是长宽,y是空间中的高度!

        //获得图片的四个点世界坐标(gameobject指的是面片,它的父集是图片)(position是图片中心的位置,所以需要加上面片x,y向长度)
        TopLeft_pl_w = gameObject.transform.parent.position   new Vector3(-PlaneWH.x, 0, PlaneWH.y);
        BottomLeft_pl_w = gameObject.transform.parent.position   new Vector3(-PlaneWH.x, 0, -PlaneWH.y);
        TopRight_pl_w = gameObject.transform.parent.position   new Vector3(PlaneWH.x, 0, PlaneWH.y);
        BottomRight_pl_w = gameObject.transform.parent.position   new Vector3(PlaneWH.x, 0, -PlaneWH.y);

        //获取面片的屏幕坐标
        TopLeft_pl_sc = Camera.main.WorldToScreenPoint(TopLeft_pl_w);   //Camera.main.WorldToScreenPoint()是封装好的函数,将三维向量转化为屏幕的二维向量。
        BottomLeft_pl_sc = Camera.main.WorldToScreenPoint(BottomLeft_pl_w);
        TopRight_pl_sc = Camera.main.WorldToScreenPoint(TopRight_pl_w);
        BottomRight_pl_sc = Camera.main.WorldToScreenPoint(BottomRight_pl_w);

        if (TopLeft_pl_sc.x>TopLeft_UI.x && TopLeft_pl_sc.y < TopLeft_UI.y && BottomLeft_pl_sc.x > BottomLeft_UI.x && BottomLeft_pl_sc.y > BottomLeft_UI.y&&TopRight_pl_sc.x<TopRight_UI.x&&TopRight_pl_sc.y<TopRight_UI.y&&BottomRight_pl_sc.x<BottomRight_UI.x&&BottomRight_pl_sc.y>BottomRight_UI.y)
        {
            gameObject.GetComponent<Renderer>().material = Green_Mate;   //当面片完全处于扫描框中时执行代码赋予材质
        }
        else
        {
            gameObject.GetComponent<Renderer>().material = Red_Mate;
        }
    }
}

测试过程发现几个待改进地点: 1、未考虑手机屏幕可旋转问题,导致旋转后手机UV的二维向量就互换了,即X、y变成了y、x(或其他方式),此时不该除以x(宽) 2、若识别图转动了一定角度(90°、180°、270°),即识别图不和屏幕同一方向了(面片和识别图同方向,面片四个点的 数值根据识别图位置确定,我们获取的是面片数值,转换后与屏幕数值相比较,很明显转动角度后比较的数值是错的),会出现不正确显示问题

大家还有什么问题,欢迎在下方留言!

0 人点赞