【Unity小技巧】unity移动物体的探究——使用8个不同方法

简介: 【Unity小技巧】unity移动物体的探究——使用8个不同方法

前言

在游戏开发中,如何移动物体?是我们需要思考的事情。

Unity 引擎也提供了众多的方法,每个开发者的使用习惯也各不相同,所以往往不是很清楚在这种场景下哪种方式最好的或者最有效的。

那么,这篇文章,我想分享一下移动物体的一些方法和优缺点。

向某个方向移动

Transform.Position

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

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

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

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

效果如下:

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;
  else
    this.position += this.TransformDirection(translation);
}

效果与 Transform.Position 一致

但是这种方法产生了一个问题。由于设备之间的差异或者动态数据的变化会导致每一帧之间的间隔是不相等的,因此,如果以帧数来控制物体移动,物体的移动距离就没办法准确把握。

效果如下

所以我们需要在原来的基础上乘以 Time.deltaTime属性的值,从而保证每秒移动的距离是一致的。

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

这样不同的帧数移动距离都会一致。

效果如下:

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

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

移动到指定位置

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

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

Vector3.MoveTowards():固定速度

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

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

效果:

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);
}

效果:

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;
}

效果如下:

以上的这些方法足以让我们准确且随心的操纵物体移动。

但有一些场景,我们并不希望如此精确或始终如一的运动轨迹,我们想物体的移动受 Unity 的物理引擎影响或者其他物体影响。

同时如果用以上方法移动,在 Unity 的物理引擎下会出现抖动,穿过刚体等奇怪的现象

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

物理引擎移动

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,这样没有持续施加外力的情况下,物体会因为摩擦力的存在而停下。

效果如下:

可以看到物体很快就停下了

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

// 赋予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);
}

效果如下:

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

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方法添加力的物体,速度时慢慢提高的。

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);
}

效果如下:

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

目录
相关文章
|
10天前
|
图形学
Unity 获取鼠标位置下的UGUI或3D物体
本文总结了两种检测方法,分别用于UGUI和3D物体的检测。第一种方法`GetOverUIobj`专门用于检测鼠标悬停的UGUI元素,通过`GraphicRaycaster`实现。第二种方法`GetOverWordGameObject`则同时适用于UI和3D物体检测,利用`PhysicsRaycaster`进行射线检测。两者均返回悬停对象或null。
|
10天前
|
图形学
unity 物体震动
在Unity中实现物体震动效果,主要通过改变物体的位置、旋转或缩放属性来模拟震动。以下是位置震动的实现原理及代码示例:通过随机生成微小偏移量并累加到物体位置上,在短时间内不断改变位置产生震动效果。生成随机偏移,并结合时间控制持续震动。
|
10天前
|
前端开发 图形学
unity UGUI跟随3D物体的坐标转换
在 Unity 中实现 UGUI 元素跟随 3D 物体,关键是将 3D 物体的世界坐标转换为屏幕或画布坐标。通过 Camera.WorldToScreenPoint 方法,可将 3D 物体位置映射到屏幕上,再更新 UGUI 元素的位置。代码示例展示了如何使用该方法,使 UGUI 图像跟随 3D 模型,并提供文字显示、图像和线条的显示/隐藏功能。
|
10天前
|
存储 图形学 索引
unity 使物体跟随路径点自动移动位置
在Unity中,物体沿路径点自动移动的核心原理是通过预设路径点,控制物体依次移动。路径点可用空对象或三维向量数组定义,并按顺序存储。移动时,计算当前位置与下一个路径点的向量差以确定方向,使用`Vector3.MoveTowards`逐步靠近目标点。代码实现包括路径点设置、移动控制及插值计算,确保物体平滑移动和旋转。
|
10天前
|
图形学
Unity 射线移动物体Ray
在Unity中,通过射线检测实现3D物体的拖拽和移动。射线由起点和方向组成,使用`Physics.Raycast`检测与物体的交点。点击物体时,记录位置偏移量,拖动过程中更新物体位置。代码包括基本拖拽和上下拖动功能,适用于正交摄像机场景。测试时为物体设置特定标签(如&quot;JQR&quot;)以便区分和操作。 示例代码展示了如何通过鼠标事件控制物体移动,并结合层级掩码优化射线检测。具体实现包括:点击选中物体、拖动更新位置、释放鼠标取消选择。此外,提供了上下拖动的额外功能,通过按键切换模式。
|
10天前
|
图形学 开发者
unity 从工具栏拖动生成物体
在 Unity 中实现从工具栏拖动生成物体的功能,基于编辑器扩展、事件系统和预制体实例化。通过自定义编辑器窗口、处理鼠标事件(按下、移动、释放)及使用 Instantiate 方法,可实现拖动并生成预制体物体。代码示例展示了如何检测鼠标事件并在指定位置实例化物体。
|
6月前
|
语音技术 开发工具 图形学
Unity与IOS⭐一、百度语音IOS版Demo调试方法
Unity与IOS⭐一、百度语音IOS版Demo调试方法
|
6月前
|
前端开发 图形学
Unity精华☀️UI和物体可见性的判断方法
Unity精华☀️UI和物体可见性的判断方法
|
6月前
|
图形学 C# 开发者
全面掌握Unity游戏开发核心技术:C#脚本编程从入门到精通——详解生命周期方法、事件处理与面向对象设计,助你打造高效稳定的互动娱乐体验
【8月更文挑战第31天】Unity 是一款强大的游戏开发平台,支持多种编程语言,其中 C# 最为常用。本文介绍 C# 在 Unity 中的应用,涵盖脚本生命周期、常用函数、事件处理及面向对象编程等核心概念。通过具体示例,展示如何编写有效的 C# 脚本,包括 Start、Update 和 LateUpdate 等生命周期方法,以及碰撞检测和类继承等高级技巧,帮助开发者掌握 Unity 脚本编程基础,提升游戏开发效率。
199 0
|
6月前
|
C# 图形学 数据安全/隐私保护
Unity数据加密☀️反射的用法:变量、属性、方法、重载,反射在DLL中的使用方法
Unity数据加密☀️反射的用法:变量、属性、方法、重载,反射在DLL中的使用方法