【问题标题】:Can not get precise positioning of Rigidbody in Unity3D在 Unity3D 中无法获得刚体的精确定位
【发布时间】:2020-11-03 01:26:43
【问题描述】:

我正在创建一个与常规略有不同的 3D 无尽跑步者。有 5 条车道宽度为 1 单位,如果玩家向左或向右移动太远,他们可能会从两侧跌落。播放器不会向前移动、跳跃或滑动。它只有左或右运动。如果被迎面而来的障碍物击中,玩家可能会被弹回。

关于玩家的左/右移动,我非常接近。但我无法准确定位播放器。

有时,当玩家移动到车道上时,位置有时会偏离 0.1,并且可能会随着时间的推移开始累积。即从0位置开始,向左移动,在0.9或1.1处停止。

这是目前为止的代码 -

{
public float speed;
public float mleft = -0.7f;
public float mright = 0.7f;

private Rigidbody rb;

// Start is called before the first frame update
void Start()
{
    rb = GetComponent<Rigidbody>();
}

// Update is called once per frame
void FixedUpdate()
{
    if (Input.GetKeyDown("a"))
    {
        rb.velocity = new Vector3(mleft, 0, 0) * speed;
        StartCoroutine(stopLaneCH());
    }

    Debug.Log(GetComponent<Transform>().position);

    if (Input.GetKeyDown("d"))
    {
        rb.velocity = new Vector3(mright, 0, 0) * speed;
        StartCoroutine(stopLaneCH());
    }
    

}

IEnumerator stopLaneCH ()
{
    yield return new WaitForSeconds(0.5f);
    GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
}

}

我不得不尝试在 speed 和 mleft/mright 变量之间找到平衡,以使玩家移动 1 个单位。

我对 Unity 和编程还很陌生,但非常感谢任何有关此问题的帮助。

我什至可以用任何帮助解决这个问题的人来命名我的第三个孩子。

【问题讨论】:

  • 运动是否必须基于物理?
  • ????由于我没有那么有经验,所以我不确定。但我猜是的。想想有人站在桥上躲避迎面而来的汽车。他们不前进,只有左右躲避汽车。但是如果他们被车撞了,他们就会被撞到后面。

标签: c# unity3d


【解决方案1】:

如果我理解正确,而不是改变速度,因为让它精确移动 1 个单位几乎是不可能的。相反,为什么不将玩家移动一个单位 确切地?使用协程,您可以使用 Vector3.Lerp 方法随着时间的推移从当前位置移动到所需位置。您想要的位置是 1 个单位,或者是您的每条车道与您当前位置之间的距离。

void Update(){

    //For Moving Left
    if (Input.GetKeyDown(KeyCode.A))
            StartCoroutine(MoveToPosition(transform, new Vector3(transform.position.x - 1, transform.position.y, transform.position.z), 0.5f));
    
    //For Moving Right
    if (Input.GetKeyDown(KeyCode.D))
            StartCoroutine(MoveToPosition(transform, new Vector3(transform.position.x - 1, transform.position.y, transform.position.z), 0.5f));
}

public IEnumerator MoveToPosition(Transform transform, Vector3 position, float timeToMove)
    {
        var currentPos = transform.position;
        var t = 0f;
        while (t < 1)
        {
            t += Time.deltaTime / timeToMove;
            transform.position = Vector3.Lerp(currentPos, position, t);
            yield return null;
        }
    }

我假设您在 X 轴上向左/向右移动,如果不是,只需将 - 1 更改为您正在移动的轴。您也可以根据自己的喜好更改 TimeToMove 浮动。

希望这会有所帮助。如果您有任何问题,请随时提出!

【讨论】:

  • 天啊卢卡斯麦卡利非常感谢你。你不知道我已经尝试为此找到正确的代码多长时间了。不过我确实有一个问题。此行中的 timeToMove:t += Time.deltaTime / timeToMove:这是做什么的?
  • 为了整洁,您可以简单地使 while 循环小于 timeToMove 并将 deltaTime 添加到 t。但我发现它更容易阅读。 Time.deltaTime 是每帧之间的时间。通过将 deltaTime 除以 timeToMove,它创建的比率相当于说 while(t
  • 啊,明白了。谢谢你的课。再一次,非常感谢你帮助我做对了。你现在在我的圣诞贺卡清单上。
【解决方案2】:

在这里,您可以使用 Time.deltaTime 属性。 而速度的值应该是“你想在 1 秒内扫描多少个单位”乘以 2,因为你的协程将在 0.5 秒内停止。

或者, 如果您的协程必须在 1.0 秒内停止。 那么速度的值就是“你想在 1 秒内渗透多少个单位”。

希望对你有帮助!

public float speed;
public float mleft = -0.7f;
public float mright = 0.7f;

private Rigidbody rb;

// Start is called before the first frame update
void Start()
{
    rb = GetComponent<Rigidbody>();
}

// Update is called once per frame
void FixedUpdate()
{
    if (Input.GetKeyDown("a"))
    {
        rb.velocity = new Vector3(mleft, 0, 0) * speed * Time.deltaTime;
        StartCoroutine(stopLaneCH());
    }

    Debug.Log(GetComponent<Transform>().position);

    if (Input.GetKeyDown("d"))
    {
        rb.velocity = new Vector3(mright, 0, 0) * speed * Time.deltaTime;
        StartCoroutine(stopLaneCH());
    }
    

}

IEnumerator stopLaneCH ()
{
    yield return new WaitForSeconds(0.5f);
    GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
}

【讨论】:

    猜你喜欢
    • 2017-05-13
    • 2019-09-19
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    相关资源
    最近更新 更多