繁体   English   中英

检查 RigidBody 是否接地?

[英]Checking if RigidBody is grounded?

我有一个带有 Rigidbody、Mesh Collider、Skinned Mesh Renderer 和以下脚本的 GameObject。

我正在尝试检查它是否已接地,但控制台在接地时不断吐出“未接地”。 很明显这里出了什么问题? 有人可以帮忙吗?

public class GroundCheck : MonoBehaviour
{
    public float Height;
    bool IsGrounded;
    Ray ray;
    MeshRenderer renda;

    private void Start()
    {
        Height = renda.bounds.size.y;
    }

    void Update()
    {
        if (Physics.Raycast(transform.position, Vector3.down, Height))
        {
            IsGrounded = true;
            Debug.Log("Grounded");
        }
        else
        {
            IsGrounded = false;
            Debug.Log("Not Grounded!");
        }
    }
}

检查刚体是否接地的另一个选项是使用OnTriggerStay function。

void OnTriggerStay(Collider other)
    {
        if (other.Transform.Tag == "Ground")
        {
            IsGrounded = true;
            Debug.Log("Grounded");
        }
        else
        {
            IsGrounded = false;
            Debug.Log("Not Grounded!");
        }
    }

我已经用一个带有平面和立方体的简单场景检查了你的代码,它可以工作。

只有当它明显是“浮动”环绕或 object 的一半身体在飞机之外时,它才会生成 NotGrounded。

检查那些绘制射线的东西,这应该可以为您提供有关网格出了什么问题的更多信息。

此外,如果问题是游戏如何感知蒙皮网格的高度,您还可以使用SkinnedMeshRenderer.localBounds ,它返回 object 的 AABB。

有比碰撞检查和射线更好的方法来检查刚体是否接地。 但是首先,为什么碰撞检查不是一个好主意:如果您的关卡是单个 model,那么墙壁也将被标记为“Ground”标签并且撞到墙壁将返回 true,这是您不想要的。 可以使用光线,但你不需要浪费时间来处理太多的数学问题。

无需使用新的对象和方法,只需检查 position 是否发生变化:

private float lastYposition;
private bool grounded;

void Start() {
    lastYposition = transform.position.y;
}

void Update() {
    grounded = (lastYposition == transform.position.y); // Checks if Y has changed since last frame
    lastYposition = transform.position.y;
}

从这里开始,您要添加什么逻辑取决于您。

private void Jump()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        if (transform.position.y == 0f)
        {
            rb.AddRelativeForce(Vector3.up * jumpForce);
        }
    }
}

只有当 y 的 position 为 0 时,我才使用这种方法使用刚体的 addrelativeforce 进行跳跃。

获取最接近底部的接触点。 检查接触法线是否在范围内。

void OnCollisionStay(Collision collision)
{
    var bottom = renderer.bounds.center;
    bottom.y -= renderer.bounds.extents.y;
    float minDist = float.PositiveInfinity;
    float angle = 180f;
    // Find closest point to bottom.
    for (int i = 0; i < collision.contactCount; i++)
    {
        var contact = collision.GetContact(i);
        var tempDist = Vector3.Distance(contact.point, bottom);
        if(tempDist < minDist)
        {
            minDist = tempDist;
            // Check how close the contact normal is to our up vector.
            angle = Vector3.Angle(transform.up, contact.normal);
        }
    }
    // Check if the angle is too steep.
    if (angle <= 45f) IsGrounded = true;
    else IsGrounded = false;
}

void OnCollisionExit(Collision collision)
{
    IsGrounded = false;
}

阅读amitklein的回答后,我想出了这个答案。

暂无
暂无

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

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