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 updatevoid 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 framevoid 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轴的坐标. 2Dpublic 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 updatevoid 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 framevoid 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;//生成3DTexttextobj = 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开发技巧,觉得有用记得一键三连哦。么么哒
相关文章:

Unity3D测量面积和角度实现方法(二)
系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、unity测量面积👉1-1 视频效果👉1-2 先创建预制体👉1-3 在创建LineRenderer预制体👉1-4 代码如下 👉二、测量平面和测量空间切换&…...
vite 配置 typescript 环境
要在 Vite 项目中配置 TypeScript 环境,你需要遵循几个步骤来确保 TypeScript 被正确设置并可以与 Vite 一起工作。以下是一个基本的指南: 初始化项目 如果你还没有初始化项目,可以使用 npm 或 yarn 初始化一个新的项目: npm i…...

ThreadCache线程缓存
一.ThreadCache整体结构 1.基本结构 定长内存池利用一个自由链表管理释放回来的固定大小的内存obj。 ThreadCache需要支持申请和释放不同大小的内存块,因此需要多个自由链表来管理释放回来的内存块.即ThreadCache实际上一个哈希桶结构,每个桶中存放的都…...
UE5_加载本地图片(jpg, png) 转 UTexture
UE5_加载图片到UTexture __Desc使用方式源码 __Desc __Time__: 2024-06-05 16:30 __Author__: Yblackd __Desc__: UE5.2 加载本地图片 转 UTexture2D, 给材质 和 UMG 使用使用方式 新建继承BlueprintFunctionLibrary c 类复制下面源码,修改类名实测加载 jpg,jpeg,…...

Linux操作系统:Spark在虚拟环境下的安装及部署
将Spark安装到指定目录 // 通过wget下载Spark安装包 $ wget https://d3kbcqa49mib13.cloudfront.net/spark-2.1.1-bin-hadoop2.7.tgz // 将spark解压到安装目录 $ tar –zxvf spark-2.1.1-bin-hadoop2.7.tgz –C /usr/local/ // 重命名 $ mv /usr/local/spark-2.1.1-bin-hado…...

内网安全--隧道技术代理技术
注:本文仅做技术交流,请勿非法破坏... 目录 项目: 1-Ngrok 用法 2-Frp 用法 3-Nps 用法 4-Spp 用法 工具: windows下: Proxifier(推荐~) Sockscap ccproxy Linux下: Proxychains 用法 http://t.csdnimg.cn/88Ew7 隧道技术:解决不出网协议上线的问…...

彩虹易支付最新版源码
源码简介 彩虹易支付最新版源码,更新时间为5.1号 2024/05/01: 1.更换全新的手机版支付页面风格 2.聚合收款码支持填写备注 3.后台支付统计新增利润、代付统计 4.删除结算记录支持直接退回商户金额 安装环境 1.PHP版本>7.4 2.Mysql数据库 安装教…...

python生成excel数据并实现隔行变色
代码 from openpyxl import Workbook from datetime import date from openpyxl.styles import PatternFilldef create_excel():wb Workbook()sh wb.activerows [[Date, Batch 1, Batch 2, Batch 3],[date(2024, 2, 1), 40, 30, 25],[date(2024, 2, 2), 40, 25, 30],[date(…...
IEEE754 十进制数转32位浮点数格式
为了将十进制数37.25转换为IEEE 754短浮点数格式(32位),我们需要按照以下步骤进行: IEEE 754标准结构 IEEE 754标准的单精度浮点数(32位)格式如下: 1位符号位(S)8位指…...
JVM内存分析之JVM分区与介绍
JVM(Java Virtual Machine)作为Java平台的核心组件,为Java应用程序的运行提供了一个虚拟的计算机环境。为了更好地理解和优化Java应用程序的性能,对JVM的内存管理进行深入分析是至关重要的。本文将详细介绍JVM的内存分区及其功能。…...

多目标检测模型加权框集成
优秀项目推荐:https://gitcode.com/ZFTurbo/Weighted-Boxes-Fusion/overview 参考链接: 目标检测加权框融合 WBF原理讲解 https://blog.csdn.net/YXD0514/article/details/132574588 目标检测加权框融合 WBF原理讲解(Weighted Boxes Fusion&…...

转型AI产品经理(6):“ 序列位置效应”如何应用在Chatbot产品中
序列位置效应是心理学中的一个记忆现象,指的是人们对一系列信息的记忆效果受到信息在序列中位置的影响。具体来说,人们通常更容易记住列表的开头和结尾部分的项目,而对中间部分的项目记忆较差。这个效应可以进一步分为“首因效应”和“近因效…...

ESP32:往MicroPython集成PCNT以支持硬件正交编码器
背景 官方发布的1.23依然没有在ESP32中集成PCNT功能。考虑到硬件的PCNT模块可以提供4倍的编码精度(对比使用PIn IRQ),还能提供硬件去毛刺。 还是自己集成一下吧。 实际上Github上早在2022年1月的时候就已经有人建议了将PCNT加入正式版本的功…...

Unity基础实践小项目
项目流程: 需求分析 开始界面 选择角色面板 排行榜面板 设置面板 游戏面板 确定退出面板 死亡面板 UML类图 准备工作 1.导入资源 2.创建需要的文件夹 3.创建好面板基类 开始场景 开始界面 1.拼面板 2.写脚本 注意事项:注意先设置NGUI的分辨率大小&…...
Set up a WordPress blog with Nginx
CentOS7 配置Nginx域名HTTPS Here is the revised guideline for setting up a WordPress blog with Nginx: Step 1: Install Nginx, MySQL, and PHP (LEMP Stack) Install Nginx: sudo yum install nginx sudo systemctl start nginx sudo systemctl enable nginxInstall MyS…...

Facebook开户|Facebook广告设计与测试优化
早上好家人们~今天Zoey给大家伙带来的是Facebook广告设计与测试优化,需要的家人们看过来啦! 一、避免复杂用图和过多的文字 根据Facebook的数据显示,用户平均浏览一个贴文的时间在手机上仅花1.7秒、在电脑上则为2.5秒。因此,广告…...
vite获取所有环境变量(env)
0.环境变量文件 API_URL8888888 VITE_API_URL99999991.定义环境变量 默认情况下,vite只获取以VITE_为前缀的环境变量。 为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码 但如果你觉得你是进击的巨人…...

【算法】常用排序算法(插入排序、希尔排序、堆排序、选择排序、冒泡排序、快速排序、归并排序、计数排序)超详细
排序算法是数据结构相关知识中非常重要的一节,相信很多小伙伴对这部分知识一知半解。那么接下来,小编就要带领大家一起来进行对排序算法的深入剖析学习,希望本篇文章能够使你有所收获! 一.常见的排序算法 排序算法有很多种&#…...

力扣 240.搜素矩阵II
题目描述: 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1: 输入:matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9…...

ASUS华硕ROG幻14Air笔记本GA403UI(UI UV UU UJ)工厂模式原厂Windows11系统安装包,带MyASUS in WinRE重置还原
适用型号:GA403UI、GA403UV、GA403UU、GA403UJ 链接:https://pan.baidu.com/s/1tz8PZbYKakfvUoXafQPLIg?pwd1mtc 提取码:1mtc 华硕原装WIN11系统工厂包带有ASUS RECOVERY恢复功能、自带面部识别,声卡,显卡,网卡,蓝牙等所有驱动、出厂主题…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...

数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...