【Unity】如何优雅地移动物体-8个方法

news/2024/4/30 0:53:13/文章来源:https://blog.csdn.net/GG_and_DD/article/details/126917358

在游戏开发中,如何移动物体?是我们需要思考的事情。
Unity 引擎也提供了众多的方法,每个开发者的使用习惯也各不相同,所以往往不是很清楚在这种场景下哪种方式最好的或者最有效的。
那么,这篇文章,我想分享一下移动物体的一些方法和优缺点。

全部效果.gif

image.png

项目地址

仓库地址

向某个方向移动

Transform.Position

众所周知,我们可以给对象的Transform组件赋予一个坐标来决定其位置。

transform.position = new Vector3(2, 1, 0);

当我们每一帧给对象赋予一个新的坐标,那么看起来,这个物体就是在运动的。

    void Update(){var dir = new Vector3(0.02f, 0, 0);transform.position += dir;}

效果如下:
Transform.Position 移动.gif

Transform.Translate()

由于直接改变 Position 属性看起来不太优雅。所以 Transform 组件提供了一个更友好的方法:Transform.Translate()

      void Update(){var dir = new Vector3(0.02f, 0, 0);transform.Translate(dir);}

其实,他的内部与 Transform.Position无异。

 public void Translate(Vector3 translation, [DefaultValue("Space.Self")] Space relativeTo){if (relativeTo == Space.World)this.position += translation;elsethis.position += this.TransformDirection(translation);}

效果与 Transform.Position 一致
Transform.Translate() 移动.gif

但是这种方法产生了一个问题。由于设备之间的差异或者动态数据的变化会导致每一帧之间的间隔是不相等的,因此,如果以帧数来控制物体移动,物体的移动距离就没办法准确把握。
效果如下
帧数不同.gif
所以我们需要在原来的基础上乘以 Time.deltaTime属性的值,从而保证每秒移动的距离是一致的。

void Update() 
{var dir = new Vector3(2f, 0, 0)*time;transform.Translate(dir);
}

这样不同的帧数移动距离都会一致。
效果如下:
帧数不同,但距离相同.gif

但这还不够优雅。在游戏中,我们经常需要改变物体的速度。为了方便实现,我们通常会使用单位向量来确定方向,增加一个浮点值来控制速度。

public float speed = 2;
void Update()
{var dir = new Vector3(2,0,0)transform.Translate(dir.normalized * speed * Time.deltaTime);
}

移动到指定位置

移动到指定位置,大概有两种方式。

  1. 速度:物体通过特定速度向目标移动。
  2. 时间:物体在时间内到达目标。

Vector3.MoveTowards():固定速度

以固定的速度移动到目标位置

public Vector3 targetPosition;
public float speed=10;
void Update()
{transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
}

效果:
MoveTowards.gif

Vector3.SmoothDamp():平滑移动

又或者,我们可以用平滑的方式到达目标位置。(平滑:到达位置前提前减速)

public Vector3 targetPosition;
public float smoothTime = 0.5f; 
public float speed = 10;
Vector3 velocity ;
void Update()
{transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime, speed);
}

效果:
SmoothDamp.gif

Vector3.Lerp():线性时间移动

该方法的意思是在调用方法期间,已经过的时间除以总持续时间,得到当前的位移目标。

 // 终点public Vector3 targetPosition;// 开始位置public Vector3 startPosition;// 持续时间public float lerpDuration = 4;// 记录运行时间private float _timeElapsed = 0;void Start(){startPosition = transform.position;}void Update(){// 记录下一个位置Vector3 valueToLerp;_timeElapsed += Time.deltaTime;if (_timeElapsed < lerpDuration){valueToLerp  = Vector3.Lerp(startPosition, targetPosition, _timeElapsed / lerpDuration);}else{valueToLerp = targetPosition;}transform.position = valueToLerp;}

效果如下:
Lerp.gif

以上的这些方法足以让我们准确且随心的操纵物体移动。
但有一些场景,我们并不希望如此精确或始终如一的运动轨迹,我们想物体的移动受 Unity 的物理引擎影响或者其他物体影响。
同时如果用以上方法移动,在 Unity 的物理引擎下会出现抖动,穿过刚体等奇怪的现象。
改变 position 移动.gif

那么接下来,我们就需要用到一些涉及到物理引擎的移动方式。

物理引擎移动

Rigidbody.AddForce()

使用这个方法给物体添加一个方向力。在力的作用下,物体将会移动。那么移动速度和位移就会与物理特效有关,比如物体质量,阻力,甚至还有重力。

一般会有两种使用方式。
在初始时给物体一个力,让其顺着物理规律下运动。使用场景一般时跳跃或者碰撞。

    // 赋予200的力public float force = 200;private Rigidbody2D _rigidbody2D;// 移动方向private Vector3 dir = Vector3.right;void Start(){_rigidbody2D = GetComponent<Rigidbody2D>();_rigidbody2D.AddForce(Vector2.right * force);}

为了更好演示刚体的运动,我还给刚体的线性阻力改为1,这样没有持续施加外力的情况下,物体会因为摩擦力的存在而停下。
image.png
效果如下:
可以看到物体很快就停下了
AddForce 开始给力.gif

第二种,会在每一帧持续给物体施加力,使物体可以持续运动。

 // 赋予2的力public float force = 2;private Rigidbody2D _rigidbody2D;// 移动方向private Vector3 dir = Vector3.right;void Start(){_rigidbody2D = GetComponent<Rigidbody2D>();}void FixedUpdate(){_rigidbody2D.AddForce(Vector2.right * force);}

效果如下:
AddForce 持续给力.gif
从效果可以看到,在持续给外力的作用下,物体移送越来越快,但在阻挡物前会停下。

Rigidbody.Velocity

直接赋予 Velocity 属性一个向量,可以立即改变物体的速度。一般情况下,我们不需要直接修改速度,除非你非常明确需要立即改变物体的速度。

    public float speed = 10;private Rigidbody2D _rigidbody2D;// 移动方向private Vector3 dir = Vector3.right;void Start(){_rigidbody2D = GetComponent<Rigidbody2D>();}void FixedUpdate(){_rigidbody2D.velocity = dir * speed;}

效果如下:
看到物体一开始就已经有速度,而通过AddForce方法添加力的物体,速度时慢慢提高的。
Velocity.gif

Rigidbody.MovePosition()

该方法有比较局限的使用场景,当物体的刚体类型是 Kinematic 时,使用Rigidbody.MovePosition() 方法进行移动。
因为 Kinematic 类型下,不会受到重力和AddForce、AddTorque等力相关的函数的影响!!!

	public float speed = 10;private Rigidbody2D _rigidbody2D;// 移动方向private Vector3 dir = Vector3.right;void Start(){_rigidbody2D = GetComponent<Rigidbody2D>();}private void FixedUpdate(){var positon = dir * (speed * Time.deltaTime);_rigidbody2D.MovePosition(transform.position + positon);}

效果如下:
MovePosition.gif

刚体类型是 Kinematic 时 ,会对刚体类型为 Dynamic 施加力,而无视 static 类型。

在文末,欢迎在评论区发表你的见解。如果觉得写的不错,可以给我点赞,鼓励一下,谢谢。

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

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

相关文章

【牛客刷题日记】— Javascript 通关秘籍

CSDN话题挑战赛第2期 参赛话题&#xff1a;面试宝典 *众人拾柴火焰高&#xff0c;我们一起携手共筑面试宝典&#xff0c;大家可以将各语言各技术各类面试真题或者你刷过的面试题汇聚于此&#xff0c;金九银十之际&#xff0c;让我们助应聘同学一臂之力~ 前进之路 题一&#x…

在TX2平台编译安装飞桨Paddlepaddle

安装nccl: git clone https://github.com/NVIDIA/nccl.git cd nccl make -j4 sudo make install 配置CUDA: (Bashrc配置:) export PATH/usr/local/cuda-10.2/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH 下载Paddle-2.1.0源码并解压…

Prometheus系列第九篇一核心之micrometer架构

文章目录架构图系统模块总结架构图 MeterRegistry有两大类[SimpleMeterRegistry,CompositeMeterRegistry]单注册源和多注册源MeterRegistry针对不同数据源实现包含 HealthMeterRegistry PrometheusMeterRegistry AtlasMeterRegistry etc… PrometheusMeterRegistry负责创建m…

ElasticSearch(六)【分词器】

六、分词器 6.1 分词器介绍 Analysis 和 Analyzer Analysis&#xff1a;文本分析是把全文本转换一系列单词&#xff08;term/token&#xff09;的过程&#xff0c;也叫分词&#xff08;Analyzer&#xff09;。Analysis是通过Analyzer来实现的。分词就是将文档通过Analyzer分成一…

k8s创建并发布WordPress

WordPress 简介 WordPress 是使⽤ PHP 语⾔开发的内容管理系统软件&#xff0c;⽤户可以在⽀持 PHP 和 MySQL 数据库的服务器上使⽤⾃⼰的博客&#xff0c;⼀个完整的 WordPress 应⽤程序包括以下 Kubernetes 对象。 ⽬的 演示如何在 KubeSphere 中创建应⽤程序&#xff08;以…

Springboot毕设项目基于Java的比亚迪汽车大数据评分系统c34pk(java+VUE+Mybatis+Maven+Mysql)

Springboot毕设项目基于Java的比亚迪汽车大数据评分系统c34pk&#xff08;javaVUEMybatisMavenMysql&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEc…

公众号查题方法-授权即可使用

公众号查题方法-授权即可使用 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#x…

SpringSecurity系列 - 13 SpringSecurity 密码加密认证 PasswordEncoder

文章目录01. 密码加密算法简介02. 环境准备03. 认证流程源码分析步骤1&#xff1a; AbstractAuthenticationProcessingFilter#doFilter 认证请求入口方法步骤2&#xff1a;UsernamePasswordAuthenticationFilter#attemptAuthentication 尝试认证方法步骤3&#xff1a;ProviderM…

MySQL-锁

MySQL-锁 锁分类 MySQL中锁按照粒度分&#xff0c;分为以下三类 全局锁&#xff1a;锁定数据库中的所有表表级锁&#xff1a;每次操作锁住整张表行级锁&#xff1a;每次操作锁住对应的行数据 全局锁 全局锁就是对整个数据库实例加锁&#xff0c;加锁后整个实例就处于只读状…

Koltin协程:异步热数据流的设计与使用

一.异步冷数据流 在Kotlin协程&#xff1a;协程的基础与使用中&#xff0c;通过使用协程中提供的flow方法可以创建一个Flow对象。这种方法得到的Flow对象实际上是一个异步冷数据流&#xff0c;代码如下&#xff1a; private suspend fun test() {val flow flow {emit(1)emit(…

ESP8266升級SDK到V3.0版本編譯報錯

編譯報錯信息 bin/libmain2.a(app_main.o): In function `user_uart_wait_tx_fifo_empty: (.irom0.text+0x678): undefined reference to `user_pre_init bin/libmain2.a(app_main.o): In function `system_phy_freq_trace_enable: (.irom0.text+0x6e4): undefined reference t…

SpringCloud基础7——Redis分布式缓存

用于复习快速回顾。 目录 1.Redis持久化 1.1.数据备份文件RDB持久化方案 1.1.1.执行时机 1.1.2.RDB原理 1.1.3.小结&#xff0c;bgsave流程、执行时间、缺点 1.2.追加文件AOF持久化方案 1.2.1.AOF原理 1.2.2.AOF配置 1.2.3.AOF文件重写 1.3.RDB与AOF对比 2.Redis主…

getBean方法源码

一、 三个API // 根据name获取bean Override public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false); }// 根据name获取bean&#xff0c;如果获取到的bean和指定类型不匹配&#xff0c;则抛出异常 Override public <T>…

C++11 - 8 -智能指针

C11 - 智能指针前言&#xff1a;普通指针&#xff1a;安全隐患&#xff1a;其他函数异常&#xff1a;new函数异常&#xff1a;智能指针&#xff1a;RAII原理&#xff1a;smart_ptr&#xff1a;auto_ptr&#xff1a;管理权转移&#xff1a;优点&#xff1a;缺点&#xff1a;uniq…

报告分享|2022汽车生态营销白皮书

报告链接&#xff1a;http://tecdat.cn/?p28679 不确定性增加&#xff0c;消费意愿在压力下等待释放 今年3月以来&#xff0c;受国际冲突和国内环境双重影响&#xff0c;能源价格大幅上涨&#xff0c;导致全球供应不稳定趋势加深&#xff0c;宏观经济下行压力明显&#xff0…

程序设计竞赛-过了这个村没这个店

文章目录个人经验竞赛简介蓝桥杯天梯赛CCPCICPC其他个人经验 初闻不知曲中意&#xff0c;再闻已是曲中人。 标题无意夸张&#xff0c;但是竞赛生涯的时间真的不长&#xff0c;机会真的错过了就没有了。一般来说&#xff0c;大一打基础&#xff0c;学习编程语言、数据结构和算法…

Moment.js的常用函数、借助vue和Moment.js实现一个简单的时钟

前言 项目中关于时间的处理是挺常见的&#xff0c;虽然之前就知道有Moment.js这个库&#xff0c;但是一直没有接触过。只不过最近同事在项目中使用了&#xff0c;那也只能简单学习一下&#xff0c;不然遇到了完全看不懂。 本文只介绍一下常用的函数&#xff0c;其他内容可以在…

想换工作?那还不赶紧来看看这份面试题

引言 “寒冬”之下&#xff0c;诸如 “Android 凉了”之类的话我已经屡见不鲜了&#xff0c;现在互联网行业的热潮已经褪去&#xff0c;开始恢复冷静&#xff1b;这样一来&#xff0c;互联网公司就会面向大量的开发者们&#xff0c;因此对应的要求只会越来越高&#xff1b;据反…

用纯css实现一个图片拼接九宫格

<style> body{ margin: 0; padding: 0; // 设定居中 display: flex; justify-content: center; align-items: center; height: 100vh; } .container{ width: 300px; height: 300px; display: flex; // 子盒子布局&#xff0c;要让子盒子之间有间隙就把宽高设大一些。 jus…

报告分享|2022年中国机器人产业图谱及云上发展研究报告

报告链接&#xff1a;http://tecdat.cn/?p28681 报告在分析当前我国机器人市场现状与产业图谱的基础上&#xff0c;对人工智能、5G、云计算、边缘计算等新兴技术赋能机器人智能化、轻量化、柔性化发展进行了理性探讨&#xff0c;结合阿里云加速器企业案例探讨了机器人企业的上…