【问题标题】:Mathf.clamp() function in UnityUnity 中的 Mathf.clamp() 函数
【发布时间】:2017-05-02 22:33:29
【问题描述】:

我的游戏场景中有一个 Cube(Player)。我编写了一个 C# 脚本来约束 Cube 的移动(使用 Mathf.Clamp()),使其不会离开屏幕。

下面是我在脚本中的FixedUpdate() 方法

private void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
        rb.velocity = movement * speed;

        rb.position = new Vector3(
            Mathf.Clamp (rb.position.x, x_min, x_max),
            0.5f,
            Mathf.Clamp(rb.position.z, z_min, z_max)
            );

    }

x_minx_maxz_minz_max的值分别是通过unity inspector输入的-3、3、-2、8。

问题

脚本运行良好,但我的播放器(立方体)可以在负数X-AXIS(如果我一直按向左箭头按钮)最多移动 -3.1 个单位,在负数X-AXIS(这种行为是其他轴也是如此)。当我停止按下按钮时,它显然会夹住 -3.1 到 -3。

  • 为什么会这样?为什么它 (Mathf.Clamp()) 首先不将 Cube 限制为 -3 个单位?
  • 为什么我会得到额外的 0.1 个单位?
  • 为什么这个值只有 0.1 个单位?为什么不增加或减少?

【问题讨论】:

  • 我可能是错的,但我认为这是因为您正在设置速度然后设置位置,但是在下一帧之前,我再次猜测,统一使用对象的速度计算下一个位置.最终将其绘制在这样的位置。我认为如果它的位置超出你的边界,你需要将速度重置为零。
  • @Alox 你应该把它作为答案。我认为这也可能是问题所在。除了完全删除刚体组件或使用Rigidbody.MovePosition 函数之外,我什至认为这是不可能解决的。
  • 那为什么总是只有0.1个单位呢?
  • 就像 Alox 说的......因为物理学仍在运行,施加于它的旧力仍然存在。当达到极限时,尝试将速度设置为Vector.Zero。那应该消除这种力量。我建议你为此使用 if 语句。

标签: c# unity3d clamp


【解决方案1】:

您的问题可能是因为您正在设置速度然后位置,但在下一帧统一之前将速度添加到您的对象位置。这就是为什么它最终会减少 0.1 个单位。

要解决此问题,如果对象即将离开您的边界,请尝试将其速度重置为零。

【讨论】:

    【解决方案2】:
    • 发生这种情况是因为内部物理更新移动了立方体after,您已将其置于夹紧位置。 Mathf.Clamp() 确实首先将立方体限制在预期位置,因为您可以通过在分配位置后直接放置 Debug.Log 来验证
    • 您获得了额外的 0.1 单位,因为您为对象提供了在夹紧后应用的速度
    • 由于速度和固定时间步的设置(在项目设置 > 时间中),它是 0.1 个单位。如果您设置更高的速度,它会更多。如果你降低固定时间步长,它也会多一点。

    【讨论】:

    • 那么,在内部物理更新中调用FixedUpdate()之后添加0.1个单位是否正确,这个值取决于(立方体的)速度和时间步长?
    • 我说的对吗?是的 Debug.Log 从未显示值 -3.1
    • 是的,你是对的,0.1个单位是在FixedUpdate()完成后添加的,这取决于立方体的速度和时间步长。因此,一个可能的解决方法是按照 Alox 的建议将速度设置为 0,然后再跨过边界。
    【解决方案3】:

    你已经知道为什么会这样了。

    为了解决问题,您可以使用此代码来防止立方体超出您的边界:

    private void FixedUpdate() {
        Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
    
        // Get new position in advance
        float xPos = rb.position.x + movement.x * speed * Time.fixedDeltaTime;
        float zPos = rb.position.z + movement.z * speed * Time.fixedDeltaTime;
    
        // Check if new position goes over boundaries and if true clamp it
        if (xPos > x_max || xPos < x_min) {
            if (xPos > x_max)
                rb.position = new Vector3(x_max, 0, rb.position.z);
            else
                rb.position = new Vector3(x_min, 0, rb.position.z);
            movement.x = 0;
        }
        if (zPos > z_max || zPos < z_min) {
            if (zPos > z_max)
                rb.position = new Vector3(rb.position.x, 0, z_max);
            else
                rb.position = new Vector3(rb.position.x, 0, z_min);
            movement.z = 0;
        }
    
        rb.velocity = movement * speed;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多