当前位置:网站首页>How to gracefully moving objects - Unity 】 【 8 method

How to gracefully moving objects - Unity 】 【 8 method

2022-09-23 08:50:29give me encouragement

在游戏开发中,如何移动物体?is something we need to think about.
Unity The engine also provides numerous methods,The usage habits of each developer are also different,So it's often not clear which approach is best or most effective in this scenario.
那么,这篇文章,I would like to share some methods and pros and cons of moving objects.

全部效果.gif

image.png

项目地址

仓库地址

How to move objects gracefully?8个方法

move in a certain direction

Transform.Position

众所周知,We can give objectsTransformA component is assigned a coordinate to determine its position.

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

When we assign a new coordinate to the object every frame,那么看起来,This object is in motion.

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

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

Transform.Translate()

due to direct change Position Properties don't look very elegant.所以 Transform Components provide a friendlier approach:Transform.Translate() .

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

其实,his internal and 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 一致
Transform.Translate() 移动.gif

But this approach created a problem.Due to differences between devices or changes in dynamic data, the interval between each frame will be unequal,因此,If the object movement is controlled by the number of frames,There is no way to accurately grasp the moving distance of an object.
效果如下
The number of frames is different.gif
So we need to multiply by the original Time.deltaTime属性的值,This ensures that the distance moved per second is consistent.

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

In this way, the moving distance of different frame numbers will be the same.
效果如下:
The number of frames is different,But the distance is the same.gif

But that's not elegant enough.在游戏中,We often need to change the speed of an object.为了方便实现,We usually use the unit vector to determine the direction,Add a float value to control the speed.

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

移动到指定位置

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

  1. 速度:The object moves towards the target with a certain speed.
  2. 时间:The object reaches the target in time.

Vector3.MoveTowards():固定速度

Move to the target position at a fixed speed

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

效果:
MoveTowards.gif

Vector3.SmoothDamp():平滑移动

又或者,We can reach the target position in a smooth way.(平滑:Decelerate early before reaching the position)

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():Linear time movement

The method is meant to be during the invocation of the method,Elapsed time divided by total duration,Get the current displacement target.

 // 终点
    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

The above methods are enough to allow us to accurately and freely manipulate the movement of objects.
But there are some scenarios,我们并Such precise or consistent motion trajectories are not desired,We want the movement of objects to be affected Unity The physics engine influence or other object influence.
At the same time, if you use the above method to move,在 Unity Jitter occurs under the physics engine,Strange phenomena like going through rigid bodies.
改变 position 移动.gif

那么接下来,We need to use some movement methods that involve the physics engine.

Physics engine moves

Rigidbody.AddForce()

Use this method to add a directional force to an object.在力的作用下,The object will move.Then the movement speed and displacement will be related to the physical effects,such as the mass of an object,阻力,There's even gravity.

一般会有两种使用方式.
Gives a force to the object initially,Let it move according to the laws of physics.Use the scene to jump or collide normally.

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

In order to better demonstrate the motion of the rigid body,I also gave the Rigidbody Linear Resistance instead1,In this way, there is no continuous external force applied,Objects stop because of friction.
image.png
效果如下:
The object can be seen to stop very quickly
AddForce Start powerful.gif

第二种,A force is continuously applied to the object every frame,Allows objects to move continuously.

 // 赋予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 Sustained power.gif
You can see from the effect,under continuous external force,Objects move faster and faster,But it will stop before the block.

Rigidbody.Velocity

直接赋予 Velocity A vector of attributes,The speed of an object can be changed instantly.一般情况下,We don't need to modify the speed directly,Unless you are very clear that you need to change the speed of the object immediately.

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

    void FixedUpdate()
    {
    
        _rigidbody2D.velocity = dir * speed;
    }

效果如下:
Seeing that objects already have speed from the start,而通过AddForcemethod to add a force to the object,The speed is gradually increased.
Velocity.gif

Rigidbody.MovePosition()

This method has relatively limited usage scenarios,When the rigid body type of the object is Kinematic 时,使用Rigidbody.MovePosition() 方法进行移动.
因为 Kinematic 类型下,Not subject to gravity andAddForce、AddTorqueThe effect of isodynamically related functions!!!

	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 时 ,for rigid body types Dynamic 施加力,而无视 static 类型.

在文末,Welcome to express your opinions in the comment area.如果觉得写的不错,可以给我点赞,鼓励一下,谢谢.

原网站

版权声明
本文为[give me encouragement]所创,转载请带上原文链接,感谢
https://chowdera.com/2022/266/202209230836030591.html

随机推荐