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

article/2025/11/10 21:57:55

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

全部效果.gif

image.png

项目地址

仓库地址

如何优雅地移动物体?8个方法

向某个方向移动

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://chatgpt.dhexx.cn/article/EmMdvU0B.shtml

相关文章

详解Unity的几种移动方式实现

前言 最近在学习如何制作 FPS 游戏&#xff0c;学习了如何使用角色控制器来控制角色的移动跳跃等等&#xff0c;结合之前学到的使用 transform&#xff0c;刚体等使物体移动&#xff0c;不同的移动方式适用于不同的场景&#xff0c;今天就来简要盘点一下各种移动方式以及其优劣…

unity物体四种移动方法总结

目录 一.通过修改位置来实现移动 二.通过物理系统实现位移 三.通过输入控制物体移动 一.通过修改位置来实现移动 利用修改Transform组件的position的两种常用方法。 1.使用Translate&#xff08;&#xff09;函数。 2.&#xff0c;直接指定新的位置 将上述两种方法在void …

详解Unity的移动控制实现

前言 上一篇写了数种Unity中的移动方式&#xff0c;有物理移动&#xff0c;有非物理移动等&#xff0c;这篇我们来谈谈Unity中的移动控制方式&#xff0c;来结合上一篇所说的方法&#xff0c;用起来。一般控制是通过获取用户输入来处理角色移动逻辑的&#xff0c;而用户输入的…

JSON数据和解析

JSON> JavaScript Object Notation JSON是一个字符串 常常用于网络传输数据的一种字符 json数据是一种轻量级的数据交换格式&#xff0c;它基于一个子集&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语…

Android开发之JSON数据解析详解(一)

&#xfeff;&#xfeff; 今天很高兴和大家一起学习Android的JSON数据解析,可能对于学习安卓的朋友都知道JSON在数据解析方面已经很普遍了.所以也是我们必定要了解的知识 ,下面让我们了解一下JSON的发展历程. XML——这种用于表示客户端与服务器间数据交换有效负载的格式&am…

Android开发json数据解析

在Android开发过程中&#xff0c;或更新数据&#xff0c;或为减轻手机负担将大部分复杂运算交由服务器来进行&#xff0c;都需要与服务器之间进行数据交互&#xff0c;数据交互中&#xff0c;使用的较为频繁的格式变为json数据&#xff0c;书写便捷&#xff0c;操作方便&#x…

JSON解析data数据

之前 是用JSONObject去解析data后来就报错 com.alibaba.fastjson.JSONException: expect : at 0, actual

JSON数据解析 之JSONPath

一&#xff1a;JSONPath说明&#xff1a; JSONPath是一种通过配置正则表达式语法&#xff0c;抽取json中的指定数据的一种类库&#xff1b; 二&#xff1a;需要的jar依赖&#xff08;依赖阿里巴巴的fastjson.jar&#xff09; maven用户可通过maven远程仓库获取配置地址 <…

一文搞懂JSON及JSON数据解析

文章目录 前言一、XML1、简介2、XML解析方式2.1、SAX解析方式2.2、DOM解析方式2.3、JDOM解析方式2.4、DOM4J解析方式 二、JSON1. 简介及其语法格式2. 解析方式2.1 GSON解析2.1.1 对象转换为JSON字符串2.1.2 JSON字符串转换为对象 2.2 fastjson2.2.1 对象转换为JSON字符串2.2.2 …

c语言解析json数据

我使用的是cJSON: http://sourceforge.net/projects/cjson/ 先看json的数据结构 c中没有对象&#xff0c;所以json数据是采用链表存储的 C代码 typedef struct cJSON { struct cJSON *next,*prev; // 数组 对象数据中用到 struct cJSON *child; // 数…

JSON数据解析(GSON方式)

Android技术学习&#xff0c;更多知识请访问https://www.itkc8.com     JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;采用完全独立于语言的文本格式&#xff0c;为Web应用开发提供了一种理想的数据交换格式。 在上一篇…

android studio json数据解析汇总(备忘)

之前写过一个&#xff0c;但是写不太全&#xff0c;结果自己都看不懂&#xff0c;希望这个以后能看懂吧。 以两个例子说明json数据解析&#xff0c;一个是最简单的&#xff0c;一个是比较难的。 必须知道的&#xff1a;JSONObject和JSONArray JSONObject是在{ }内的。如{&qu…

json解析数据详解

对于服务器端来说&#xff0c;返回给客户端的数据格式一般分为html、xml和json这三种格式&#xff0c;那么本篇随笔将讲解一下json这个知识点&#xff0c;包括如何通过json-lib和gson这两个json解析库来对解析我们的json数据&#xff0c;以及如何在我们的Android客户端解析来自…

Python3 JSON数据解析

JSON是一种比轻量级的数据交换格式。比XML更小、更快、更容易解析。 JSON语法时JavaScript对象表示语法的子集。书写格式为&#xff1a;键:值。用英文逗号为分隔符&#xff0c;{}大括号报错对象&#xff0c;[]中括号报错数组。 python3中使用json模块对JSON进行编码和解码&am…

json数据解析 jsonpath

json是一种文本数据交换格式&#xff0c;不是一种语言 jsonpath是一种语法&#xff0c;用于json数据&#xff0c;类似xpath用于html 1.json.dumps json.loads 需要import json json.dumps——将python数据转化为json数据 实际上就是将python里面的字典转化成json格式的数…

Android开发--Json数据的解析

在执行解析数据之前&#xff0c;需要将一个类库应用到你的程序中&#xff0c;下载的地址是&#xff1a; http://code.google.com/p/google-gson/ 下载解压之后你需要将蓝色标记的文件放入到你的程序之中应用 首先&#xff0c;我们需要知道什么是Json数据: JSON的定义&…

Python3 JSON 数据解析

Python3 中可以使用 json 模块来对 JSON 数据进行编解码&#xff0c;它包含了两个函数&#xff1a; json.dumps(): 对数据进行编码。json.loads(): 对数据进行解码。 示例&#xff1a; # -*- coding:utf-8 -*-import json # 加载json模块data { # 定义一个字典类型a: 1,b:…

json数据解析(json数据解析 前端)

JAVA为什么要返回JSON数据&#xff1f;JAVA为什么要返回JSON数? print( String()); 这样在前台页面就可以通过eval(data。List)获取到。 输出 String()就可以看到讲一个java对象转换成json对象的结果。其他java对象也可以这么来处理。 另外还有就是 List list new ArrayL…

JSON 数据解析的方法

JSON 数据解析 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式&#xff0c;但是也使用了类似于C语言家族的习惯&#xff08;包括C、C、C#、Java、JavaScript、Perl、Python等&#xff09;。这…

手动JSON数据解析

1.将json格式的字符串{}转化为JAVA对象 //第一步&#xff1a;获取或创建Json数据String json "{\n" " \"id\":2,\"name\":\"小龙虾\",\n" " \"price\":12.3,\n" " …