[Unity 2D Platform] 让人物移动拥有精确加速度和减速度的代码

Celeste_speed_curve
GMTK总结的Celeste速度曲线(黄线)

在寻找和探索了许久之后我终于发现了接近完美的代码。在改进了这里的代码之后,以下的代码便可以指定人物的加速度和减速度以及最高速度,从而实现对速度曲线的控制。"It just works!"

public class PlayerController: MonoBehaviour
{
    Rigidbody2D myRigidBody;
	[Header("Run")]
    //最高速度
    [SerializeField] [Range(0f, 10f)] float MaxSpeed = 7f;
    //当前速度(不要强行改动)
    [SerializeField] float Speed = 0f;
    //加速度unit/s^2:在一秒结束时人物可以从0加速到多少。
    [SerializeField] float Acceleration = 30f;
    //减速度unit/s^2:在一秒结束时人物可以从某个速度减速到0。
    [SerializeField] float Deceleration = 50f;
    
	void Start()
	{
		myRigidBody = GetComponent<Rigidbody2D>();
	}
	
    void Update()
	{
		Run();
	}
	
	void Run()
	{
		//在速度不到极限速度时且速度和方向键同向时提供加速度
		if ((Input.GetKey("left") || Input.GetKey(KeyCode.A)) 
&amp;&amp; (Speed >- MaxSpeed) &amp;&amp; (Mathf.Approximately(Speed,0f)|| Speed<0f)) 
			Speed = Speed - Acceleration * Time.deltaTime;
        else if ((Input.GetKey("right") || Input.GetKey(KeyCode.D)) 
&amp;&amp; (Speed <MaxSpeed) &amp;&amp; (Mathf.Approximately(Speed,0f)|| Speed>0f)) 
			Speed = Speed + Acceleration * Time.deltaTime;
        else
        {
			//在松开按键或者速度和方向键反向时提供减速度
            if (Speed > Deceleration * Time.deltaTime) 
Speed = Speed - Deceleration * Time.deltaTime;
            else if (Speed < -Deceleration * Time.deltaTime) 
Speed = Speed + Deceleration * Time.deltaTime;
            else
                Speed = 0;
        }
		
		//不可以强行改变人物位置,会导致穿模
        //Vector2 position = transform.position;
        //position.x += Speed * Time.deltaTime;
        //transform.position = position;
		
		//正确做法是改变人物速度,相当于AddForce
        Vector2 tarVelocity = myRigidBody.velocity;
        tarVelocity.x = Speed;
        myRigidBody.velocity = tarVelocity;
	}
}

另外要实现更精确的控制可以锁帧,然后根据算出从0加速到最高的时间MaxSpeed/Acceleration,即可估摸出加速过程有几帧。

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注