Unity3D测量面积和角度实现方法(二)

系列文章目录

unity工具


文章目录

  • 系列文章目录
  • 👉前言
  • 👉一、unity测量面积
    • 👉1-1 视频效果
    • 👉1-2 先创建预制体
    • 👉1-3 在创建LineRenderer预制体
    • 👉1-4 代码如下
  • 👉二、测量平面和测量空间切换
    • 👉2-1 平面测量
    • 👉2-1 空间测量面积效果
  • 👉三、unity测量角度的方法
    • 👉3-1 准备工作
    • 👉3-2 字体显示
    • 👉3-3 实现代码如下
    • 👉3-4 效果展示
  • 👉壁纸分享
  • 👉总结


👉前言

有时候unity会用到测量面积的问题,所以写了一个测量的小工具,里面有测量平面的面积和测量空间面积,方便使用,简单记录一下,不喜勿喷哦
大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
欢迎点赞评论哦.
下面就让我们进入正文吧 !


提示:以下是本篇文章正文内容,下面案例可供参考

👉一、unity测量面积

👉1-1 视频效果

先来看一下效果图吧,看看是不是自己想要的,如果是就继续往下看,如果不是就跳过

测量平面面积

👉1-2 先创建预制体

生成一个小球拖成预制体用来当鼠标点击的点来使用

👉1-3 在创建LineRenderer预制体

创建一个空物体,然后添加上lineRenderer组件,制作成预制体,至此准备工作已完成,开始编写代码实现功能,开始期待吧

👉1-4 代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 测量面积
/// </summary>
public class PlanimeteringCrotroller : MonoBehaviour
{
    public bool isClbool;
    public bool isOpenArea;
    private Vector3 posOne, posTwo;
    GUIStyle text = new GUIStyle();
    private int size = 40;  //文字大小
    public GameObject objPre; //圆点的预制体
    public LineRenderer lineRender;  //线的预制体
    public Transform allCLParentTransform;
       
    private List<Vector3> lv1 = new List<Vector3>();//存坐标的点
   
    private LineRenderer lineobj;
    // Start is called before the first frame update
    void Start()
    {
        
    }
    public void OpenCLLLLLL()
    {
        isClbool = true;
        isOpenArea = true;
    }
    public void CloseCLLLLLL()
    {
        lv1.Clear();
        isClbool = false;
        isOpenArea = false;
        if (allCLParentTransform.childCount == 0) return;
        if (allCLParentTransform.childCount >0)
        {
            for (int i = 0; i < allCLParentTransform.childCount; i++)
            {
                Destroy(allCLParentTransform.GetChild(i).gameObject);
            }
        }
      
    }
    // Update is called once per frame
    void Update()
    {
        if (isClbool && !EventSystem.current.IsPointerOverGameObject())
        {
            if (Input.GetMouseButtonDown(0))
            {
                posOne = Input.mousePosition;
            }
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

           if (isOpenArea)
            {
                if (Input.GetMouseButtonUp(0))
                {
                    posTwo = Input.mousePosition;
                    if (Physics.Raycast(ray, out hit) && posOne == posTwo)
                    {
                        text = new GUIStyle();
                        text.fontSize = size;
                        //创建圆点
                        Transform go = Instantiate(objPre.transform, allCLParentTransform);
                        go.position = hit.point + new Vector3(0, 0.1f, 0);
                      
                        if (lv1.Count >= 2)
                        {
                            lv1.Add(hit.point + new Vector3(0, 0.1f, 0));
                            lv1.Add(lv1[0]);                         
                        }
                        else
                        {
                            if (lv1.Count==0)
                            {
                                lineobj = Instantiate(lineRender, allCLParentTransform);
                            }
                            
                            lv1.Add(hit.point + new Vector3(0, 0.1f, 0));  //坐标的点
                        }
                      
                        lineobj.positionCount = lv1.Count;

                        lineobj.SetPositions(lv1.ToArray());

                        if (lv1.Count >= 3)
                        {
                            lv1.RemoveAt(lv1.Count - 1);
                        }

                    }
                }
            }
        }
    }

    void OnGUI()
    {
        //显示面积在中间
        if (lv1.Count > 2)
        {
            //除了第一个点和最后个点,其它点都是存了两遍
            //for (int i = 0; i < lv.Count - 1; i = i + 2)
            //{
            //    Vector3 s = new Vector3((lv[i].x + lv[i + 1].x) / 2, (lv[i].y + lv[i + 1].y) / 2, (lv[i].z + lv[i + 1].z) / 2);
            //    Vector3 aa = Camera.main.WorldToScreenPoint(s);
            //    //注意屏幕坐标系与GUI的ui坐标系y轴相反,ToString(".000")保留小数点后3位数,几个零几位数
            //    //显示线段的长度
            //    GUI.Label(new Rect(aa.x - size, Screen.height - aa.y, 50, 20), "<color=white>" + Vector3.Distance(lv[i], lv[i + 1]).ToString(".0") + "</color>" + "<color=white>" + "m" + "</color>", text);

            //}
            Vector3 vector3 = Vector3.zero;
            for (int i = 0; i < lv1.Count; i++)
            {
                vector3 += lv1[i];
            }
            Vector3 a = Camera.main.WorldToScreenPoint(vector3 / lv1.Count);
            GUI.Label(new Rect(a.x - 0, Screen.height - a.y, 100, 60), "<color=red>" + Compute_3D_polygon_area(lv1).ToString("f1") + "</color>" + "<color=red>" + "㎡" + "</color>", text);
        }
        //显示角度
        //if (lv1.Count == 3 && type == 2)
        //{
        //    Vector3 a = _camera.WorldToScreenPoint(lv1[1]);
        //    GUI.Label(new Rect(a.x, Screen.height - a.y, 50, 20), "<color=yellow>" + Angle(lv1[1], lv1[0], lv1[lv1.Count - 1]).ToString(".000") + "</color>" + "<color=blue>" + "℃" + "</color>", text);
        //}
    }
    //计算任意多边形的面积,顶点按照顺时针或者逆时针方向排列,不需要考虑y轴的坐标. 2D
    public double ComputePolygonArea(List<Vector3> points)
    {
        int point_num = points.Count;
        if (point_num < 3) return 0.0;
        float s = points[0].y * (points[point_num - 1].x - points[1].x);
        for (int i = 1; i < point_num; ++i)
            s += points[i].y * (points[i - 1].x - points[(i + 1) % point_num].x);
        return Mathf.Abs(s / 2.0f);
    }
    public double Compute_3D_polygon_area(List<Vector3> points)
    {
        //points为任意多边形的点集合 注意输入时要按环的流动输入,不能乱序输入
        //此方法是3D空间的,相较于2D更具有普适性
        if (points.Count < 3) return 0.0;

        var P1X = points[0][0];
        var P1Y = points[0][1];
        var P1Z = points[0][2];
        var P2X = points[1][0];
        var P2Y = points[1][1];
        var P2Z = points[1][2];
        var P3X = points[2][0];
        var P3Y = points[2][1];
        var P3Z = points[2][2];

        var a = Mathf.Pow(((P2Y - P1Y) * (P3Z - P1Z) - (P3Y - P1Y) * (P2Z - P1Z)), 2) + Mathf.Pow(((P3X - P1X) * (P2Z - P1Z) - (P2X - P1X) * (P3Z - P1Z)), 2) + Mathf.Pow(((P2X - P1X) * (P3Y - P1Y) - (P3X - P1X) * (P2Y - P1Y)), 2);
        var cosnx = ((P2Y - P1Y) * (P3Z - P1Z) - (P3Y - P1Y) * (P2Z - P1Z)) / (Mathf.Pow(a, 0.5f));
        var cosny = ((P3X - P1X) * (P2Z - P1Z) - (P2X - P1X) * (P3Z - P1Z)) / (Mathf.Pow(a, 0.5f));
        var cosnz = ((P2X - P1X) * (P3Y - P1Y) - (P3X - P1X) * (P2Y - P1Y)) / (Mathf.Pow(a, 0.5f));

        var s = cosnz * ((points[points.Count - 1][0]) * (P1Y) - (P1X) * (points[points.Count - 1][1])) + cosnx * ((points[points.Count - 1][1]) * (P1Z) - (P1Y) * (points[points.Count - 1][2])) + cosny * ((points[points.Count - 1][2]) * (P1X) - (P1Z) * (points[points.Count - 1][0]));

        for (int i = 0; i < points.Count - 1; i++)
        {
            var p1 = points[i];
            var p2 = points[i + 1];
            var ss = cosnz * ((p1[0]) * (p2[1]) - (p2[0]) * (p1[1])) + cosnx * ((p1[1]) * (p2[2]) - (p2[1]) * (p1[2])) + cosny * ((p1[2]) * (p2[0]) - (p2[2]) * (p1[0]));
            s += ss;
        }

        return Mathf.Abs(s / 2.0f);
    }
}

👉二、测量平面和测量空间切换

👉2-1 平面测量

只需要把加了高度的代码取消注释,默认是不加高度的,根据需要修改添加
其实代码是一样的只需要在点击的位置上添加一个高度,要不然测量平面上的时候就会被模型遮挡线段,
在这里插入图片描述

👉2-1 空间测量面积效果

测量空间面积

👉三、unity测量角度的方法

👉3-1 准备工作

首先还是先制作预制体,上面创建的小球的预制体和lineRender预制体还能继续使用

👉3-2 字体显示

在创建一个3D字体的预制体
截图如下
在这里插入图片描述

👉3-3 实现代码如下

下面是代码

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

public class LineAngleController : MonoBehaviour
{
    public bool isClbool;
    public bool isOpenAngle;
    private Vector3 posOne, posTwo;
  
    private int distanceInt;   //计数控制
    public LineRenderer lineprefab;  //线的预制体
    public Transform xiaoqiuPrefab;  //点击点的预制体
    public TextMesh angleTextPrefab; //显示角度的预制体
    public Transform allCLParentTransform;  //所有预制体生成的父节点
    private Transform dian1, dian2, dian3;  //临时接出来的物体
    private LineRenderer lineobj;   //临时接出来的物体
    private TextMesh textobj;   //临时接出来的物体
    // Start is called before the first frame update
    void Start()
    {
        
    }
    public void OpenCLLLLLL()
    {
        isClbool = true;
        isOpenAngle = true;
    }
    public void CloseCLLLLLL()
    {
        distanceInt = 0;
        isClbool = false;
        isOpenAngle = false;
        if (allCLParentTransform.childCount == 0) return;
        if (allCLParentTransform.childCount > 0)
        {
            for (int i = 0; i < allCLParentTransform.childCount; i++)
            {
                Destroy(allCLParentTransform.GetChild(i).gameObject);
            }
        }

    }
    // Update is called once per frame
    void Update()
    {
        if (isClbool && !EventSystem.current.IsPointerOverGameObject())
        {
            if (Input.GetMouseButtonDown(0))
            {
                posOne = Input.mousePosition;
            }
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            //角度
            if (isOpenAngle)
            {
                if (Input.GetMouseButtonUp(0))
                {
                    posTwo = Input.mousePosition;
                    if (Physics.Raycast(ray, out hit) && posOne == posTwo)
                    {
                        if (distanceInt == 0)
                        {
                            distanceInt++;
                            //鼠标点击克隆物体
                            dian1 = Instantiate(xiaoqiuPrefab, allCLParentTransform);
                            lineobj = Instantiate(lineprefab, allCLParentTransform);
                            dian1.transform.position = hit.point;
                            lineobj.positionCount = 2;
                            lineobj.SetPosition(0, hit.point);
                        }
                        else if (distanceInt == 1)
                        {
                            distanceInt++;                          
                            //鼠标点击克隆物体
                            dian2 = Instantiate(xiaoqiuPrefab, allCLParentTransform);                         
                            lineobj.positionCount = 3;
                            lineobj.SetPosition(1, hit.point);
                            dian2.position = hit.point;

                            //生成3DText
                            textobj = Instantiate(angleTextPrefab, allCLParentTransform);
                            textobj.transform.position = hit.point;
                        }
                        else if (distanceInt == 2)
                        {
                            distanceInt++;
                            //鼠标点击复制物体
                            dian3 = Instantiate(xiaoqiuPrefab, allCLParentTransform);
                            lineobj.positionCount = distanceInt;
                            lineobj.SetPosition(2, hit.point);
                            dian3.position = hit.point;

                            //算角度
                            Vector3 v1 = dian1.transform.position - dian2.transform.position;
                            Vector3 v2 = dian3.transform.position - dian2.transform.position;

                            textobj.text = Mathf.Round(Vector3.Angle(v1, v2)) + "°";
                            distanceInt = 0;
                        }
                    }
                }
                if (distanceInt == 1)
                {
                    if (Physics.Raycast(ray, out hit, 1000, ~(1 << 7)))
                    {
                       
                        lineobj.SetPosition(1, hit.point);
                    }
                }
                if (distanceInt == 2)
                {
                    if (Physics.Raycast(ray, out hit, 1000, ~(1 << 7)))
                    {                     
                        lineobj.SetPosition(2, hit.point);
                        //算角度
                        Vector3 v1 = dian1.transform.position - dian2.transform.position;
                        Vector3 v2 = hit.point - dian2.transform.position;

                        textobj.text = Mathf.Round(Vector3.Angle(v1, v2)) + "°";
                    }
                }
            }
        }
    }
}

代码挂载截图
在这里插入图片描述

👉3-4 效果展示

最后放上录屏效果

测量角度

欢迎留言评论,指正不足

👉壁纸分享

请添加图片描述
请添加图片描述

上一篇关于测量距离的实现链接

👉总结

本次总结的就是测量面积和角度的实现,有需要会继续添加新的
如能帮助到你,就帮忙点个赞吧,三连更好哦,谢谢
你的点赞就是对博主的支持,有问题记得留言评论哦!
不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/698574.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java---程序逻辑控制(详解)

目录 一、概述二、顺序结构三、分支结构3.1 if语句3.1.1 语法格式13.1.2 语法格式23.1.3 语法格式3 3.2 练习3.2.1 判断一个数字是奇数还是偶数3.2.2 判断一个数字是正数&#xff0c;负数&#xff0c;还是零3.2.3 判断一个年份是否为闰年 3.3.switch语句 四、循环结构4.1 while…

远程工作岗位机会

电鸭&#xff1a;​​​​​​https://eleduck.com/?sortnew电鸭社区是具有8年历史的远程工作招聘社区&#xff0c;也是远程办公互联网工作者们的聚集地。在社区&#xff0c;我们进行有价值的话题讨论&#xff0c;也分享远程、外包、零活、兼职、驻场等非主流工作机会。「只工…

最好用的搜题软件大学?8个公众号和软件推荐清单! #知识分享#知识分享#经验分享

今天&#xff0c;我将分享一些受欢迎的、被大学生广泛使用的日常学习工具&#xff0c;希望能给你的学习生活带来一些便利和启发。 1.彩虹搜题 这个是公众号 一款专供大学生使用的搜题神器专注于大学生校内学习和考研/公考等能力提升 下方附上一些测试的试题及答案 1、行大量…

【C++】B树

概念 实现 二叉搜索树的插入&#xff08;非递归&#xff09; 二叉搜索树的中序遍历 二叉搜索树的查找&#xff08;非递归&#xff09; 二叉搜索树的删除&#xff08;非递归&#xff09; 二叉搜索树的查找&#xff08;递归&#xff09; 拷贝构造函数 赋值运算符重载 三、…

三星系统因何而成?或许是因为吞噬了第四颗恒星

相比于其他的类似星体&#xff0c;这个特殊的三星系统拥有更大更紧密的星体。 三星 天文学家发现了前所未见的三星系统。相比于其他典型的三星系统&#xff0c;这一三星系统拥有更大的体积&#xff0c;并且排列也更加紧密&#xff0c;这也使得这一系统更加特别。科学家推测&am…

好用的Web数据库管理工具推荐(ChatGPT 4o的推荐是什么样?)

在现代数据管理和开发中&#xff0c;Web数据库管理工具变得越来越重要。这些工具不仅提供了直观的用户界面&#xff0c;还支持跨平台操作&#xff0c;方便用户在任何地方进行数据库管理。 目录 1. SQLynx 2. phpMyAdmin 3. Adminer 4. DBeaver 5 结论 以下是几款推荐的Web…

操作系统安全:Windows系统安全配置,Windows安全基线检查加固

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

数据结构与算法笔记:基础篇 - 红黑树(上):为什么工程中都用红黑树这种二叉树?

概述 上两篇文章&#xff0c;我们依次讲解了树、二叉树、二叉查找树。二叉查找树是最常用的一种二叉树&#xff0c;它支持快速插入、删除、查找操作&#xff0c;各个操作的时间复杂度跟树的高度成正比&#xff0c;理想情况下&#xff0c;时间复杂度是 O ( l o g n ) O(logn) …

如何用R语言ggplot2画折线图

文章目录 前言一、数据集二、ggplot2画图1、全部代码2、细节拆分1&#xff09;导包2&#xff09;创建图形对象3&#xff09;主题设置4&#xff09;轴设置5&#xff09;图例设置6&#xff09;颜色7&#xff09;保存图片 前言 一、数据集 数据下载链接见文章顶部 数据&#xff1a…

网络数据包抓取与分析工具wireshark的安及使用

WireShark安装和使用 WireShark是非常流行的网络封包分析工具&#xff0c;可以截取各种网络数据包&#xff0c;并显示数据包详细信息。常用于开发测试过程中各种问题定位。 1 任务目标 1.1 知识目标 了解WireShark的过滤器使用,通过过滤器可以筛选出想要分析的内容 掌握Wir…

企业微信hook接口协议,ipad协议http,确认群发消息

确认群发消息 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid": "d85c7605-ae91-41db-aad5-888762493bac","vids":[],//如果是客户群群发需要填群id"msgid":1097787129…

前端三剑客之JavaScript基础入门

目录 ▐ 快速认识JavaScript ▐ 基本语法 &#x1f511;JS脚本写在哪? &#x1f511;注释 &#x1f511;变量如何声明? &#x1f511;数据类型 &#x1f511;运算符 &#x1f511;流程控制 ▐ 函数 ▐ 事件 ▐ 计时 ▐ HTML_DOM对象 * 建议学习完HTML和CSS后再…

手把手带你做一个自己的网络调试助手(4) - 优化完善

了解全部信息&#xff0c;请关注专栏: QT网络调试助手_mx_jun的博客-CSDN博客 优化服务器 1.不能设置随拖动变大: this->setLayout(ui->verticalLayout); 2. 未连接就能发送消息: //在处理新连接槽函数中加入 if(!ui->btnSend->isEnabled()){//只有客户端连接…

【CC精品教程】osbg格式三维实景模型全解

数据格式同样都是osgb,不同软件生产的,建模是参数不一样,还是有很大区别的,本讲进行一一讲解。 文章目录 一、CC生产的osbg1. osgb的文件结构2. metadata.xml是什么?​(1)EPSG模式metadata.xml​(2)EPSG带+模式metadata.xml​(3)ENU模式metadata.xml​(4)LOCAl模式…

《大道平渊》· 拾贰 —— 天下大事必作于细:做好每一件小事,必然大有所成!

《平渊》 拾贰 "天下难事必作于易&#xff0c;天下大事必作于细。" 社群一位大佬最近在研究新项目, 他做事的 "方法论" 令我深受启发。 他在测试项目时, 每一步都做的非常细致&#xff1a; 整个项目的测试都被划分为一件件小事, 然后有条不紊地推进…… …

postgresql之翻页优化

列表和翻页是所有应用系统里面必不可少的需求&#xff0c;但是当深度翻页的时候&#xff0c;越深越慢。下面是几种常用方式 准备工作 CREATE UNLOGGED TABLE data (id bigint GENERATED ALWAYS AS IDENTITY,value double precision NOT NULL,created timestamp with time zon…

matlab 异常值检测与处理——Z-score法

目录 一、算法原理1、算法概述2、主要函数3、参考文献二、代码实现三、结果展示四、相关链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、算法概述 使用Z分数法,可以找出距离平均值有多少个标准差值…

Java面试八股之静态变量和实例变量的区别有哪些

Java静态变量和实例变量的区别有哪些 存储位置和生命周期&#xff1a; 静态变量&#xff1a;静态变量属于类级别&#xff0c;存储在Java的方法区&#xff08;或称为类区&#xff0c;随JVM实现而异&#xff0c;现代JVM中通常在元数据区内&#xff09;&#xff0c;并且在类首次…

天锐绿盾,怎么防止公司内部核心文件、文档、设计图纸、源代码、音视频等数据资料外泄

天锐绿盾通过多种技术和管理手段&#xff0c;全面保护公司内部的核心文件、文档、设计图纸、源代码、音视频等数据资料&#xff0c;防止外泄。以下是具体的防泄密措施&#xff1a; PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5d…

【技术干货】Linux命令“du-sh和df”执行结果存在差异,问题分析及处理过程

1.du-sh和df的差异 du和df是两个不同的Linux命令&#xff0c;它们⽤于查看磁盘空间的使⽤情况。但是它们有⼀些区别&#xff1a; • du&#xff08;diskusage&#xff09;会扫描每个⽂件和⽬录&#xff0c;并计算它们的总⼤⼩。[1]du-sh*会显⽰当前⽬录下每个⽂件或⽬录的⼤⼩…