Unity如何平滑运动-移动及运动方式(附通用实现代码)

基础知识引入

移动物体方式分2种

  • 非物理移动(没有力/速度等因素),只需要改变物体的位置Position即可  
  • 物理运动,这个时候就需要使用Unity中的物理系统

运动方式有3种

1. 朝一个方向运动

非物理运动

在Update中对Transform.position中的 (x, y, z) 值自加,例如Transform.position.x+=0.1f,0.1f被称为步长

物理运动(Rigidbody组件中的方法

  • Rigidbody.AddForce() 方法在某一个方向上施加力的效果    
  • Rigidbody.velocity 给物体一个移动速度    
  • CharacterController 中的方法,由于 CharacterController 中继承部分的 Rigidbody 属性,也可以控制物体移动,主要用于制作第一,三人称射击运动  

2. 向着目标点移动(一般是鼠标点击点)

非物理运动

  1. Transform.Translate:举个例子,Transform.Translate(Vector3.zero*Time.deltaTime) 以一米每秒的速度向 (0,0,0) 点运动    
  2. Vector3.lerp:Vector.Slerp,Vector3.MoveTowards插值。Vector3.lerp(transform.position, targetposition, Time.deltaTime),Slerp主要用于角度弧度的插值运算,MoveTowards在Lerp基础上增加了限制最大速度    
  3. Vector3.SmoothDamp:该方法是可以平滑的从A逐渐移动到B点,并且可以控制速度,最常见的用法是相机跟随目标。

物理运动

  • Righdbody 中的 Rigidbody.MovePosition 方法用于实现向目标点移动   

3. 由A点到B点(运动方式2的特殊化)


运用

一个物体在运动状态下,会有一个速度变量,也就是我们期望的速度。而从静止到运动状态的过程,会有一个加速度。而游戏开发中,要做到一个物体平滑的运动,也就是模拟出这个从静止,通过加速度,达到期望速度的过程。游戏是按帧运行的,在初始的时候,目标运动速度为 0,随着每一帧的流逝,目标速度会不断累加一帧中的加速度,当累加到期望速度时,则会以期望速度来运动。

Unity 中实现的代码如下(原理对于所有游戏引擎通用)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MovingSphere : MonoBehaviour
{
    // 用户设定最大期望速度
    [SerializeField, Range(0f, 100f)] private float maxSpeed = 10f;
    // 用户设定最大加速度
    [SerializeField, Range(0f, 100f)] private float maxAcceleration = 10f;

    // 当前的运动速度
    private Vector3 velocity;

    // Update is called once per frame
    void Update()
    {
        // 通过读取用户输入,来确定期望速度向量(向量包含了大小和方向)
        Vector2 playerInput;
        playerInput.x = Input.GetAxis("Horizontal");
        playerInput.y = Input.GetAxis("Vertical");
        Vector3 desiredVelocity = new Vector3(playerInput.x, playerInput.y, 0.0f) * maxSpeed;

        // 计算这一帧中的最大加速度(现实中是以秒为单位,而游戏运行是以帧为单位)
        float maxSpeedChanged = maxAcceleration * Time.deltaTime;

        // 下面的代码是将当前速度限制为最大期望速度
        if (velocity.x < desiredVelocity.x)
        {
            velocity.x = Mathf.Min(velocity.x + maxSpeedChanged, desiredVelocity.x);
        }
        else if (velocity.x > desiredVelocity.x)
        {
            velocity.x = Mathf.Max(velocity.x - maxSpeedChanged, desiredVelocity.x);
        }

        if (velocity.y < desiredVelocity.y)
        {
            velocity.y = Mathf.Min(velocity.y + maxSpeedChanged, desiredVelocity.y);
        }
        else if (velocity.y > desiredVelocity.y)
        {
            velocity.y = Mathf.Max(velocity.y - maxSpeedChanged, desiredVelocity.y);
        }

        // 得到了当前速度,就可以计算当前这一帧的位移
        Vector3 displacement = velocity * Time.deltaTime;

        // 将物体的当前位置,累加上这一帧的位移,就是最终的移动
        transform.localPosition += displacement;
    }
}

猜你喜欢

转载自blog.csdn.net/Luoxiaobaia/article/details/123864221