机械拆装-基于Unity-装配功能的实现

目录

1. 装配场景的相机控制

2. 鼠标拖拽和旋转功能的实现

  2.1 鼠标拖拽

  2.2 物体旋转

3. 零件与装配位置的对应关系

4. 轴向装配的准备位置

5. 装配顺序的实现

  5.1 标签提示

  5.2 定义一个变量记录步骤数值



1. 装配场景的相机控制

   开始装配功能时,需要将相机调节成适合于装配的移动方式,万一鼠标拖拽零件时镜头游移到其他地方会相当不舒服。

  在本应用中的做法是,建立一个空节点,让镜头始终跟随这个节点移动,类似于第三人称控制器,控制镜头在这个节点周围的有限位置。

  

  需要将相机设置为这个固定节点的子节点,并且调整好高度和角度。效果如下:

  

  

  相机控制代码如下:  

public class CameraControl : MonoBehaviour
{//使用鼠标左键点击画面调整角度public GameObject mainPerson;//跟随点private float distance;//相机和主角点的距离private Quaternion Cam_rotation;  //相机的旋转角度public bool isClickRotate=true;  //判断是否有旋转命令private float xAngle,yAngle;private Vector2 inputPos;private Vector3 resultPos;private Ray ray;public float rotationSpeed=80;  //旋转速度public float yAngleMin=3, yAngleMax=80;public float lerp = 5; //位置跟随的范围void Start(){distance = Vector3.Distance(mainPerson.transform.position, transform.position);Cam_rotation = transform.rotation;  //记录相机初始角度//计算相机初始与X、Y轴的角度xAngle = Vector3.Angle(Vector3.right, transform.right);yAngle = Vector3.Angle(Vector3.up, transform.up);}void Update(){//或者使用lateUpdate()if(!isClickRotate){//如果点击到了零件,就不再让相机旋转return;}else{isClickRotate = Input.GetMouseButton(0);inputPos.x = Input.GetAxis("Mouse X");inputPos.y = Input.GetAxis("Mouse Y");if (isClickRotate){xAngle += inputPos.x * rotationSpeed * Time.deltaTime;yAngle -= inputPos.y * rotationSpeed * Time.deltaTime;yAngle = Mathf.Clamp(yAngle, yAngleMin, yAngleMax);Cam_rotation = Quaternion.Euler(yAngle, xAngle, 0);transform.rotation = Quaternion.Lerp(transform.rotation, Cam_rotation, Time.deltaTime * 5);}resultPos = mainPerson.transform.position - (Cam_rotation * Vector3.forward * distance);transform.position = Vector3.Lerp(transform.position, resultPos, Time.deltaTime * lerp);}//镜头缩放if (Input.GetAxis("Mouse ScrollWheel") != 0){//鼠标滚动滑轮if (Input.GetAxis("Mouse ScrollWheel") < 0){//范围值限定if (Camera.main.fieldOfView <= 100)Camera.main.fieldOfView += 2;if (Camera.main.orthographicSize <= 20)Camera.main.orthographicSize += 0.5F;}//Zoom in  if (Input.GetAxis("Mouse ScrollWheel") > 0){//范围值限定if (Camera.main.fieldOfView > 2)Camera.main.fieldOfView -= 2;if (Camera.main.orthographicSize >= 1)Camera.main.orthographicSize -= 0.5F;}}}
}

2. 鼠标拖拽和旋转功能的实现

  2.1 鼠标拖拽

  查了一下各路大仙的做法,使用协程方法的效果比较好,由于鼠标拖动是比较耗时的工作,不可能在一帧执行时间内完成,因此使用协程方法建立一个新线程,不影响主线程的执行。代码如下:

public class onMouseDrag3d : MonoBehaviour
{//偏移值private Vector3 _Offset;//当前物体对应的屏幕坐标private Vector3 _ScreenPos;private void Start(){StartCoroutine(OnMouseDrag());}private IEnumerator OnMouseDrag(){//当前物体对应的屏幕坐标_ScreenPos = Camera.main.WorldToScreenPoint(transform.position);//偏移值=物体的世界坐标,减去转化之后的鼠标世界坐标(z轴的值为物体屏幕坐标的z值)_Offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, _ScreenPos.z));//当鼠标左键点击while (Input.GetMouseButton(0)){//物体当前坐标transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y, _ScreenPos.z)) + _Offset;//等待固定更新,且循环执行yield return new WaitForFixedUpdate();}}
}

  将这个代码挂在需要移动的物体上,能够实现移动的效果。

  2.2 物体旋转

    将下面的旋转脚本挂在物体上,并且需要将物体的层设置为“WorkPiece"层。

public class onMouseRotate : MonoBehaviour
{    //旋转所需的参数//上下旋转最大角度限制public int yMinLimit = -20;public int yMaxLimit = 80;//旋转速度public float xSpeed = 250.0f;//左右旋转速度public float ySpeed = 120.0f;//上下旋转速度//旋转角度private float x = 0.0f;private float y = 0.0f;private void Update(){RaycastHit hit;//射线检测需要旋转的物体Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);Physics.Raycast(ray, out hit, 100, LayerMask.GetMask("WorkPiece")); //零件需要加入WorkPiece层if (Input.GetMouseButton(1)&&hit.collider!=null){//旋转的判断条件为射线接触到物体,且按下了鼠标右键x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;y = ClampAngle(y, yMinLimit, yMaxLimit);//欧拉角转化为四元数target.transform.rotation = Quaternion.Euler(y, x, 0);} }//角度范围值限定static float ClampAngle(float angle, float min, float max){if (angle < -360)angle += 360;if (angle > 360)angle -= 360;return Mathf.Clamp(angle, min, max);}
}

3. 零件与装配位置的对应关系

  在一个装配场景中,零件数量从几个到上百个不等,因此,需要根据零件数量定义数据表,如数据表、数组或二维数组、字典等数据形式,必要时需要用数据库存储零件信息。这里使用相对容易理解的数组,设置三个数组,分别存储零件、零件位置和提示标签,让这三者的下标一致作为对应标记。

  

  并且可以在初始化时Start() ,使用for循环给每个零件挂上拖拽和旋转的脚本

        for (int i = 0; i < 14; i++){   //将所有零件挂上onMouseDrag3d脚本workPiece[i].AddComponent<onMouseDrag3d>();if (i == 0)workPiece[i].GetComponent<pieceToPlace>().ifBase = true;//第一个零件为基准零件(主轴),其他为轴向装配零件}

4. 轴向装配的准备位置

  在主轴一端设置一个轴向准备位置,以便于轴向装配的零件,自由移动到这个位置后,锁定其他两轴,仅沿着轴向装配。(拆卸场景相反)

  

  实现思想是:当零件被自由拖拽,移动到的位置和这个准备位置的距离,小于一定数值时,将这个准备位置的角度和位置赋值给零件。(装配到最终位置也是这么实现的)

  var offset = Vector3.Distance(transform.position, piecePlace.transform.position);if (offset <= 0.75f){//在两者距离较接近时让两者重叠transform.position = piecePlace.transform.position;  //位置一致transform.rotation = piecePlace.transform.rotation;  //方向一致}

  之后仅仅让零件在x方向上被拖动,将上面的协程方法修改为如下,其中正负方向和坐标轴需要根据实际情况而定。

  private IEnumerator OnMouseDragX(){//X方向拖拽//当前物体对应的屏幕坐标_ScreenPos = Camera.main.WorldToScreenPoint(transform.position);//偏移值_Offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, _ScreenPos.z));//当鼠标左键点击while (Input.GetMouseButton(0)){//修改:y、z方向不变transform.position = Camera.main.ScreenToWorldPoint(new Vector3(-Input.mousePosition.x,transform.position.y, transform.position.z)) + Offset;//等待固定更新,且循环执行yield return new WaitForFixedUpdate();}}

5. 装配顺序的实现

  5.1 标签提示

  使用UI制作标签,包含Canvas和Text,其中画布Canvas设置为WorldSpace,相机设置为主相机。

    

  这些标签起到在场景中提示拆装顺序的作用:

  5.2 定义一个变量记录步骤数值

   比如,可以定义一个记录步骤的整型变量,初始值为0,用这个整型变量与零件的数组下标进行比较,如果选取一个零件的下标与步骤变量相符时,可以顺利实现装配,并且变量值+1;当两者不符合时,则提示装配顺序有误。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vector与list的简单介绍

1. 标准库中的vector类的介绍&#xff1a; vector是表示大小可以变化的数组的序列容器。 就像数组一样&#xff0c;vector对其元素使用连续的存储位置&#xff0c;这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素&#xff0c;并且与数组中的元素一样高效。但与数…

1975react社区问答管理系统开发mysql数据库web结构node.js编程计算机网页源码

一、源码特点 react 社区问答管理系统是一套完善的完整信息管理类型系统&#xff0c;结合react.js框架和node.js后端完成本系统&#xff0c;对理解react node编程开发语言有帮助系统采用node框架&#xff08;前后端分离&#xff09;&#xff09;&#xff0c;系统具有完整的源…

6种ETL计算引擎介绍

目录 一、ETL计算引擎定义 二、ETL计算引擎的功能和特性 三、6种ETL计算引擎 1、MapReduce 2、Tez 3、Spark 4、Flink 5、ClickHouse 6、Doris 一、ETL计算引擎定义 ETL&#xff08;Extract, Transform, Load&#xff09;计算引擎是用于执行ETL过程中数据转换阶段的关键组件之一…

mac如何压缩视频大小不改变画质,mac怎么压缩视频软件

在数字时代&#xff0c;视频已成为信息传递和娱乐消遣的重要媒介。然而&#xff0c;视频带来的愉悦体验背后&#xff0c;是日益增长的存储和分享压力。大视频文件不仅占用大量存储空间&#xff0c;上传和下载也变得异常缓慢。那么&#xff0c;如何才能有效压缩视频&#xff0c;…

ERROR: No matching distribution found for numpy

1.原因&#xff1a; 出现这两行英文是因为原先输入pip install numpy的方式不安全&#xff0c;不被信任所以无法下载。 2.解决方法&#xff1a; 改成以下命令执行&#xff1a; pip install numpy -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun…

2025年中国国际新能源汽车技术零部件及服务展览会

中国国际新能源汽车技术零部件及服务展览会&#xff0c;从设计到制造、从使用到服务&#xff0c;精准“链”接新能源汽车全产业链的技术供应商和汽车制造商&#xff0c;专业面向新能源造车供应链的行业盛会。2024展会回顾&#xff1a;在展会的3天里&#xff0c;有62家车企核心供…

共享拼购:创新商业模式引领小用户基数下的销售奇迹“

在瞬息万变的商业蓝海中&#xff0c;一个新颖且深具潜力的策略正悄然改变着游戏规则&#xff0c;它巧妙地避开了传统路径的束缚&#xff0c;以微妙却深远的调整&#xff0c;开辟出了一条通往成功的独特航道。我的一位合作伙伴&#xff0c;正是这一策略的实践者&#xff0c;他在…

数字媒体技术基础之:DNG 文件

DNG&#xff08;Digital Negative&#xff09;文件是一种用于存储原始图像数据的文件格式&#xff0c;由 Adobe Systems 于2004年开发并推广。DNG 是一种开放的、非专利的原始图像格式&#xff0c;旨在为不同相机制造商提供一个统一的存储格式。DNG 文件保存了原始的、未处理的…

C++时区转换

#include <iostream> #include "cctz/civil_time.h" #include "cctz/time_zone.h"// 时区转换库 // https://github.com/google/cctzint test() {for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); d) {std::cout << &…

【设计模式】设计模式学习线路与总结

文章目录 一. 设计原则与思想二. 设计模式与范式三. 设计模式进阶四. 项目实战 设计模式主要是为了改善代码质量&#xff0c;对代码的重用、解耦以及重构给了最佳实践&#xff0c;如下图是我们在掌握设计模式过程中需要掌握和思考的内容概览。 一. 设计原则与思想 面向对象编…

qt6 获取百度地图(一)

需求分析&#xff1a; 要获取一个地图&#xff0c; 需要ip 需要根据ip查询经纬度 根据经纬度查询地图 另外一条线是根据输入的地址 查询ip 根据查询到的ip查地图‘ 最后&#xff0c;要渲染地图 上面这这些动作&#xff0c;要进行http查询&#xff1a; 为此要有三个QNet…

机器学习与AI大数据的融合:开启智能新时代

在当今这个信息爆炸的时代&#xff0c;大数据和人工智能&#xff08;AI&#xff09;已经成为推动社会进步的强大引擎。作为AI核心技术之一的机器学习&#xff08;Machine Learning, ML&#xff09;&#xff0c;与大数据的深度融合正引领着一场前所未有的科技革命&#xff0c;不…

电子画册制作的小秘密都在这篇文章了

电子画册作为现代营销和展示的重要工具&#xff0c;已经成为各类企业和个人宣传品的首选。相比传统印刷画册&#xff0c;电子画册不仅节省成本&#xff0c;还能通过多媒体元素增强视觉冲击力&#xff0c;提升用户互动体验。本文将介绍电子画册制作的基础步骤和关键要点&#xf…

电气-伺服(4)CANopen

一、CAN Controller Area Network ,控制器局域网&#xff0c;80年的德国Bosch的一家公司研发可以测量仪器直接的实时数据交换而开发的一款串行通信协议。 CAN发展历史 二、CAN 的osi 模型 CAN特性&#xff1a; CAN 的数据帧 三、CANopen 什么是CANopen CANopen 的网络模型 …

Unity In App Purchasing内购校验

1&#xff0c;利用收据验证混淆器 把后台的key填进去&#xff0c;点击自动生成一些文件 2&#xff0c;代码过滤 using UnityEngine.Purchasing.Security;在IAPManager.cs的 public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)增加 #if !UNITY_EDITOR…

香橙派AIpro如何赋能AI+边缘流媒体设备

文章目录 &#xff08;一&#xff09;前言&#xff08;二&#xff09;AI边缘流媒体设备展示&#xff08;三&#xff09;赋能AI边缘流媒体设备1、准备开发环境2、在板子中下载编译安装SRS3、基本推拉流测试4、多路推流性能测试 &#xff08;四&#xff09;一些注意事项1、开发板…

springboot 篮球馆管理系统-计算机毕业设计源码21945

目 录 摘要 1 绪论 1.1选题背景 1.2研究意义 1.3论文结构与章节安排 2 篮球馆管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 2.4 …

ctfshow sql注入

开启其他注入 web221 limit注入 给出查询语句 以及过滤逻辑为空 获取数据库名即可 limit 用于控制返回结果行数 limit后面似乎只能跟PROCEDURE ANALYSE( ) 函数了 PROCEDURE ANALYSE( ) 函数用于分析查询结果的函数 参数是用来控制函数的 这个参数的位置 可以放入报错函数 原…

MySQL—创建查看删除备份恢复数据库

创建数据库 创建数据库 LLF_DB01CREATE DATABASE LLF_DB01删除数据库DROP DATABASE LLF_DB01创建一个使用utf8字符集的数据库并带校对规则的数据库CREATE DATABASE hsp_db03 CHARACTER SET utf8 COLLATE utf8_bin 查看、删除数据库 显示所有的数据库SHOW DATABASES显示数据库…

AI PC(智能电脑)技术分析

一文看懂AI PC&#xff08;智能电脑&#xff09; 2024年&#xff0c;英特尔、英伟达等芯片巨头革新CPU技术&#xff0c;融入AI算力&#xff0c;为传统PC带来质的飞跃&#xff0c;引领智能计算新时代。 2024年&#xff0c;因此被叫作人工智能电脑&#xff08;AI PC&#xff09;…