简体   繁体   English

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

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

Yes I know this question was asked before by SuperSonyk: That post is here: Set rigidbody.velocity to direction of mouse in Unity2d是的,我知道 SuperSonyk 之前曾问过这个问题:该帖子在这里: 在 Unity2d 中将刚体.速度设置为鼠标方向

However- the link referenced in the answer to that post is now legacy material, and I can't bring myself to understand it in Unity's current version.但是 - 该帖子的答案中引用的链接现在是遗留材料,我无法让自己在 Unity 的当前版本中理解它。

My Problem: In short, I want to make my player accelerate in the direction of my cursor.我的问题:简而言之,我想让我的播放器朝着我的 cursor 的方向加速。 My game is currently a TOP-DOWN Space Shooter in 2D.我的游戏目前是 2D 中的 TOP-DOWN 太空射击游戏。 My player already looks at my mouse correctly, using cam.ScreenToWorldPoint.我的播放器已经使用 cam.ScreenToWorldPoint 正确地看着我的鼠标。 But relentlessly trying to add force seems futile for me, since I am fairly new to coding.但是无情地试图增加力量对我来说似乎是徒劳的,因为我对编码还很陌生。

If I have any other issues in my code, It would be great if anyone could point them out: Here's my code:如果我的代码中有任何其他问题,如果有人能指出它们会很棒:这是我的代码:

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

Please summarize the edits clearly, thank you!请把修改总结清楚,谢谢!

In general since this is a 2D rigidbody also the velocity is a Vector2 and you should probably rather use Vector2.ClampMagnitude一般来说,因为这是一个 2D 刚体,所以速度也是Vector2 ,您可能应该使用Vector2.ClampMagnitude

and then in然后在

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

do you only want to move in global Y direction?你只想在全局 Y 方向移动吗? Also a velocity is already a "per second" value -> it makes no sense to multiply by Time.deltaTime if you reassign a new velocity.此外,速度已经是“每秒”值 -> 如果重新分配新速度,乘以Time.deltaTime是没有意义的。 Since it says thrust I guess you rather wanted to add to the existing velocity.既然它说thrust ,我猜你宁愿想增加现有的速度。


What you would rather do is save your mouse direction you already have and do你宁愿做的是保存你已经拥有的鼠标方向并做

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

You already have half of the work by having your player looking at the mouse.通过让玩家看着鼠标,您已经完成了一半的工作。 We will be using the vector lookDirection as the direction of the movement for the player, normalize it so its length is 1 and multiply it by thrust .我们将使用向量lookDirection作为玩家的移动方向,对其进行归一化,使其长度为 1 并乘以推力 This way, we have a vector in the direction of the mouse and of length thrust as intended.这样,我们就有了一个指向鼠标方向的向量和预期的长度推力

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

Note that we work here with Vector2 since you are using a Rigidbody2D.请注意,我们在这里使用 Vector2,因为您使用的是 Rigidbody2D。

Also, I don't think that using Time.DeltaTime is relevant here.另外,我不认为使用Time.DeltaTime在这里是相关的。 When you apply force to a physic object, you don't need to use it, by definition, the function FixedUpdate() has a fixed frequency.当您对物理 object 施加力时,您不需要使用它,根据定义,function FixedUpdate()具有固定频率。 If you look at one of Unity's tutorial , you can see that they don't multiply it by Time.DeltaTime如果您查看 Unity 的教程之一,您会发现它们不会将其乘以Time.DeltaTime

Last tip: you may want to be playing around with the drag property of your Rigidbody2D to have your player slow down over time when not accelerating, otherwise, it will be sliding out of control and the player won't be able to stop it.最后提示:您可能希望使用 Rigidbody2D 的drag属性来让您的玩家在不加速时随着时间的推移减速,否则,它将滑出失控并且玩家将无法停止它。

Don't hesitate to tell me if my answer is not clear for you or does not entirely satisfy you, it's my first answer here!如果我的答案对您来说不清楚或不能完全满足您,请随时告诉我,这是我在这里的第一个答案!

EDIT: I forgot to tell you but as derHugo mentioned, since you are using Rigidbody2D , you must use Vector2.ClampMagnitude to limit your speed in your speedLimiter function.编辑:我忘了告诉你,但正如 derHugo 提到的,由于你使用的是Rigidbody2D ,你必须使用Vector2.ClampMagnitude来限制你的speedLimiter function 中的速度。 Also, I don't think that you need your if since the function Vector2.ClampMagnitude will only change the value of the velocity if it exceeds the maximum.另外,我认为你不需要你的if因为 function Vector2.ClampMagnitude只会在速度值超过最大值时改变它。

Thanks to everyone who responded, With the help of Brackeys community: I managed to solve this by using this method:感谢所有回复的人,在 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