繁体   English   中英

在 Unity2d 中将rigidbody.velocity 设置为鼠标方向:更新版本

[英]Set rigidbody.velocity to direction of mouse in Unity2d: Updated Version

是的,我知道 SuperSonyk 之前曾问过这个问题:该帖子在这里: 在 Unity2d 中将刚体.速度设置为鼠标方向

但是 - 该帖子的答案中引用的链接现在是遗留材料,我无法让自己在 Unity 的当前版本中理解它。

我的问题:简而言之,我想让我的播放器朝着我的 cursor 的方向加速。 我的游戏目前是 2D 中的 TOP-DOWN 太空射击游戏。 我的播放器已经使用 cam.ScreenToWorldPoint 正确地看着我的鼠标。 但是无情地试图增加力量对我来说似乎是徒劳的,因为我对编码还很陌生。

如果我的代码中有任何其他问题,如果有人能指出它们会很棒:这是我的代码:

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

public class PlayerController : MonoBehaviour
{
    //================= MOVEMENT =====================
    private float thrust = 0.5f;
    private float maxSpeed = 10f;
    public Rigidbody2D rb;

    //================= AIMING =======================
    public Camera cam;
    Vector2 mousePos;

    // Update is called once per frame: Good for INPUTS
    void Update()
    {
        //aiming
        mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
    }
    // Called Set amount of times. Good for PHYSICS CALCULATIONS
    void FixedUpdate()
    {
        Move();
        speedLimiter();

        //aim
        Vector2 lookDirection = mousePos - rb.position;
        float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg - 90f;
        rb.rotation = angle;
    }
    //======= MY MOVE FUNCTION DOES NOT WORK. HELP? ======
    void Move()
    {
        if (Input.GetButtonDown("Accelerate"))
        {
            rb.velocity = new Vector3(0, thrust, 0) * Time.deltaTime;
        }
    }
    void speedLimiter()
    {
        if (rb.velocity.magnitude > maxSpeed)
        {
            rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
        }
    }
}

请把修改总结清楚,谢谢!

一般来说,因为这是一个 2D 刚体,所以速度也是Vector2 ,您可能应该使用Vector2.ClampMagnitude

然后在

rb.velocity = new Vector3(0, thrust, 0) * Time.deltaTime; 

你只想在全局 Y 方向移动吗? 此外,速度已经是“每秒”值 -> 如果重新分配新速度,乘以Time.deltaTime是没有意义的。 既然它说thrust ,我猜你宁愿想增加现有的速度。


你宁愿做的是保存你已经拥有的鼠标方向并做

public class PlayerController : MonoBehaviour
{
    ...

    void FixedUpdate()
    {
        // I would update the aim BEFORE moving
        // Use a NORMALIZED direction! Makes things easier later
        Vector2 moveDirection = (mousePos - rb.position).normalized;
        float angle = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg - 90f;
        rb.rotation = angle;

        // OPTIONAL: Redirect the existing velocity into the new up direction 
        // without this after rotating you would still continue to move into the same global direction    
        rb.velocity = rb.velocity.magnitude * moveDirection;

        Move(moveDirection);
        speedLimiter();
    }
    
    void Move(Vector2 moveDirection)
    {
        if (Input.GetButtonDown("Accelerate"))
        {
            // Instead of re-assigning you would probably add to the existing velocity
            // otherwise remove the "+" again
            rb.velocity += moveDirection * thrust * Time.deltaTime;
        }
    }

    void speedLimiter()
    {
        if (rb.velocity.magnitude > maxSpeed)
        {
            // You are working with Vector2 so use the correct method right away
            rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);
        }
    }
}

通过让玩家看着鼠标,您已经完成了一半的工作。 我们将使用向量lookDirection作为玩家的移动方向,对其进行归一化,使其长度为 1 并乘以推力 这样,我们就有了一个指向鼠标方向的向量和预期的长度推力

void Move()
{
  if (Input.GetButtonDown("Accelerate"))
  {
    Vector2 lookDirection = (mousePos - rb.position);
    rb.AddForce(lookDirection.normalized  * thrust);
  }
}

请注意,我们在这里使用 Vector2,因为您使用的是 Rigidbody2D。

另外,我不认为使用Time.DeltaTime在这里是相关的。 当您对物理 object 施加力时,您不需要使用它,根据定义,function FixedUpdate()具有固定频率。 如果您查看 Unity 的教程之一,您会发现它们不会将其乘以Time.DeltaTime

最后提示:您可能希望使用 Rigidbody2D 的drag属性来让您的玩家在不加速时随着时间的推移减速,否则,它将滑出失控并且玩家将无法停止它。

如果我的答案对您来说不清楚或不能完全满足您,请随时告诉我,这是我在这里的第一个答案!

编辑:我忘了告诉你,但正如 derHugo 提到的,由于你使用的是Rigidbody2D ,你必须使用Vector2.ClampMagnitude来限制你的speedLimiter function 中的速度。 另外,我认为你不需要你的if因为 function Vector2.ClampMagnitude只会在速度值超过最大值时改变它。

感谢所有回复的人,在 Brackeys 社区的帮助下:我设法通过使用这种方法解决了这个问题:

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

public class PlayerController : MonoBehaviour
{
    //================= MOVEMENT =====================
    private float thrust = 10f;
    private float maxSpeed = 100f;
    public Rigidbody2D rb;

    //================= AIMING =======================
    public Camera cam;
    Vector2 mousePos;

    // Update is called once per frame: Good for INPUTS
    void Update()
    {
        //aiming
        mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
    }
    // Called Set amount of times. Good for PHYSICS CALCULATIONS
    void FixedUpdate()
    {
        Move();
        speedLimiter();

        //aim
        Vector2 lookDirection = mousePos - rb.position;
        float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg - 90f;
        rb.rotation = angle;
    }
    void Move()
    {
        if (Input.GetKey("up"))
        {
            rb.AddRelativeForce(Vector2.up*thrust);
        }
    }
    void speedLimiter()
    {
        if (rb.velocity.magnitude > maxSpeed)
        {
            rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
        }
    }
    //rb.AddForce(new Vector3(0, thrust, 0));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM