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恢复功能、自带面部识别,声卡,显卡,网卡,蓝牙等所有驱动、出厂主题…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
