簡體   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