当前位置: 首页 > news >正文

Unity3D 物体圆周运动

Unity3D 实现一个 2D 物体沿着圆周进行运动。

物体圆周运动

前段时间在开发一个小游戏时,需要实现火箭沿着一个圆形轨道进行圆周运动。

以前面试的时候也被问到过这类问题(如何让一个 2D 物体做圆周运动),所以还是记录一下实现思路。

准备素材

可以在网上找两张图片素材,只要是一个物体和一个圆圈就行了,这里就先不提供素材啦。

准备素材

然后直接把每张图片素材分别拖拽到场景中。

拖到场景

数学知识

在看到这个场景时,可以联想到一个单位圆,三角函数之类的数学知识。

例如下图,圆的半径 r = 1,点 P 落在圆周上,直线 OP 与 x 轴的夹角为 α α α

因为 a,b,r 三条边构成了一个三角形,可以使用正弦、余弦和正切的概念,跟夹角联系起来,即
s i n α = 对边 / 斜边 = b / r = b sin α = 对边/斜边 = b/r = b sinα=对边/斜边=b/r=b

c o s α = 邻边 / 斜边 = a / r = a cos α = 邻边/斜边 = a/r = a cosα=邻边/斜边=a/r=a

t a n α = 对边 / 邻边 = b / a tan α = 对边/邻边 = b/a tanα=对边/邻边=b/a

数学知识

那么,当夹角发生改变时,我们可以通过正弦和余弦计算出点 P 的坐标。

过点 P 作直线 PQ 垂直于直线 OP,直线 PQ 是点 P 处的切线。

数学知识切线

实现功能

计算坐标位置

创建脚本 CircularMotion.cs,挂载到火箭上。

脚本中有三个变量:

  • radius 控制圆的半径,改变火箭移动的轨迹。
  • angle 实时变化的角度,在 Update 中不断变化。
  • speed 控制角度变化的速度。

在 Update 中,先把角度转成弧度,这是因为 Mathf.SinMathf.Cos 接收的是一个弧度值。

只需要让角度乘上 Mathf.Deg2Rad 这个常量值即可。

接着,通过弧度值,计算出正弦和余弦,乘上半径(也就是斜边),就可以得到对应半径的圆周上的坐标点,修改火箭的位置。

最后实时更新角度,通过 speed 变量控制速度快慢,乘上 Time.deltaTime 保证角度变化不受帧率影响。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CircularMotion : MonoBehaviour
{public float radius = 3f;  // 圆的半径public float angle = 0f;   // 实时变化的角度public float speed = 50f;  // 角度变化速度void Update(){// 角度转弧度float radians = Mathf.Deg2Rad * angle;// 单位圆的坐标点float a = Mathf.Cos(radians);float b = Mathf.Sin(radians);// 根据半径缩放坐标点float x = a * radius;float y = b * radius;// 设置物体位置transform.position = new Vector2(x, y);// 更新角度angle += speed * Time.deltaTime;// 确保角度在合理范围内(0 到 360 度)if (angle >= 360f){angle -= 360f;}else if (angle <= 0f){angle += 360f;}}
}

运行效果:

运行效果

计算切线方向

现在火箭虽然能进行圆周运动了,但是方向看上去不对,火箭的顶端应该朝着轨道的切线方向旋转。

由上述的数学知识可知,直线 PQ 是点 P 处的切线,把切线平移到原点处,作直线 MN。

点 M 和 N 都是圆周上的点,它们构成的三角形都是全等的,容易得出它们的坐标分别是 (-b, a) 和 (b, -a)。

数学知识方向

目前火箭是按逆时针方向移动的,火箭顶端应该朝着点 M(-b, a) 的方向。

这里使用 Mathf.Atan2 函数,注意它的参数列表是 Atan2(float y, float x),第一个参数是 y,第二个参数是 x。

它也给出了注释 Returns the angle in radians whose Tan is y/x.

所以调用时,写成 Mathf.Atan2(a, -b)

因为此函数的返回值是弧度,需要转成角度,只需要乘上 Mathf.Rad2Deg 即可。

转换后的角度是从 X 轴的正方向到射线 OM 的夹角 β β β,取值范围是 -180° 到 180°。

最后使用 Quaternion.Euler 构造一个欧拉角,赋值给 transform.rotation,修改火箭的 Z 轴旋转。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CircularMotion : MonoBehaviour
{public float radius = 3f;  // 圆的半径public float angle = 0f;   // 实时变化的角度public float speed = 50f;  // 角度变化速度void Update(){// 角度转弧度float radians = Mathf.Deg2Rad * angle;// 单位圆的坐标点float a = Mathf.Cos(radians);float b = Mathf.Sin(radians);// 根据半径缩放坐标点float x = a * radius;float y = b * radius;// 设置物体位置transform.position = new Vector2(x, y);// 计算旋转角度float rotationAngle = Mathf.Atan2(a, -b) * Mathf.Rad2Deg;// 设置物体的旋转transform.rotation = Quaternion.Euler(0f, 0f, rotationAngle);// 更新角度angle += speed * Time.deltaTime;// 确保角度在合理范围内(0 到 360 度)if (angle >= 360f){angle -= 360f;}else if (angle <= 0f){angle += 360f;}}
}

运行效果:

运行效果2

小结

数学方法:

  • 角度转弧度 radians = Mathf.Deg2Rad * angle
  • 弧度转角度 angle = Mathf.Rad2Deg * radians
  • 正弦 Mathf.Sin(radians)
  • 余弦 Mathf.Cos(radians)
  • 反正切 Mathf.Atan2(y, x)

角度和弧度是度量角的两种单位,角度旋转一周是 360°,弧度则是 2 π 2π 2π,即 360 ° = 2 π 360°=2π 360°=2π

1 弧度大约等于 57.3°。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 利用HttpServlet完成MySql数据库my_user表的登录校验
  • 算法学习day29
  • AWS生成式AI项目的全生命周期管理
  • Qt pro文件详解
  • 掌握Dism++,让你的Windows系统更加清爽、流畅!
  • MyIP:强大且简单好用!
  • Langchain-Chatchat+Xinference集成部署
  • 【线性代数】汤家凤线性代数辅导讲义整理
  • Java中基本数据类型包装类的常量池缓存的值得范围是多少?
  • Linux:账号和权限管理(二)
  • 掀起 .NET 风暴:用 Docker 快速打造并部署你的炫酷应用!
  • the request was rejected because no multipart boundary was found
  • FP8量化
  • 精益生产管理培训机构怎么选?三大维度助你精准定位
  • 从科幻到现实:AIGC助力打造个性化数字人
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【面试系列】之二:关于js原型
  • Android交互
  • conda常用的命令
  • Docker入门(二) - Dockerfile
  • Javascript Math对象和Date对象常用方法详解
  • java多线程
  • JS专题之继承
  • Python 基础起步 (十) 什么叫函数?
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • text-decoration与color属性
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 面试总结JavaScript篇
  • 前端设计模式
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 责任链模式的两种实现
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • scrapy中间件源码分析及常用中间件大全
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​你们这样子,耽误我的工作进度怎么办?
  • #php的pecl工具#
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (1)(1.9) MSP (version 4.2)
  • (3)STL算法之搜索
  • (33)STM32——485实验笔记
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .Net Core与存储过程(一)
  • .NET MVC 验证码
  • .net MVC中使用angularJs刷新页面数据列表
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?