【问题标题】:Unity3D - Make character moving forward nicely on a seesaw in a 2.5D runner gameUnity3D - 让角色在 2.5D 跑步游戏中很好地在跷跷板上向前移动
【发布时间】:2017-02-25 08:14:58
【问题描述】:

我想做的是在Unity中制作一种2.5D的跑步游戏,角色的三个旋转轴都被冻结,Z轴上的位置也被冻结。我不知道如何让角色在跷跷板上顺利前行。 (我使用 HingeJoint 创建跷跷板。)

我创建了一个结构来使用 Physics.Raycast() 函数检测 CapsuleCollider 状态,并且效果很好。

 private struct ColliderStatus
    {
        public bool headed;  //colliding up
        public bool footed;  //colliding down
        public bool onPlane; //colliding down && the obstacle colliding does not have slope angle
        public bool lefted;  //colliding left
        public bool righted; //colliding right
        public bool inAir;   //not colliding anything
    }

我试过这些方法:

  1. 对刚体施加力以向前移动

    //To move character rigidbody move forward automatically in runner game 
    //when the speed is lower than the minimum speed and it's on plane or in air.
    if (rigidbody.velocity.x < minForwardSpeed && (colliderStatus.onPlane || colliderStatus.inAir))
    {
        rigidbody.AddForce(20f * Vector3.right);
    }
    
    //Add gravity to player
    Vector3 gravityForce = new Vector3(0f, -gravityOnPlayer, 0f);
    rigidbody.AddForce(gravityForce);
    

效果不好,因为角色在跷跷板上时会继续上升,尽管跷跷板开始倾斜。并且当角色从较高的平面跌落到地面或跳跃后会有速度损失,看起来角色会在着陆点上眩晕片刻,然后开始加速。

  1. 使用transform.Translate()向前移动&&改变添加重力的方式

    //Use transform.Translate() to move forward
    //I recognize that by this way, there will be no velocity loss
    //when the character falling down to the ground at the landing point
    //If I don't use this condition, my character will stuck on the
    //right vertical wall
    if (!colliderStatus.righted)
    {
         transform.Translate(new Vector2(minForwardSpeed, 0f) * Time.deltaTime);
    }
    

我不知道为什么我不能这样写,因为它会导致速度反应不正确:

    //Use transform.Translate() to move forward
    if (!colliderStatus.righted && rigidbody.velocity.x < minForwardSpeed)
    {
         transform.Translate(new Vector2(minForwardSpeed, 0f) * Time.deltaTime);
    }

为了改变添加重力的方式,我使用了一个函数 SlopeAngleVector() 来计算角色运行时的斜率向量。

    private Vector3 SlopeAngleVector()
    {
    Vector3 nextStepPositon = new Vector3(transform.position.x + 0.01f, transform.position.y, 0f);
    Ray nextPosRay = new Ray(nextStepPositon, Vector3.down);
    Ray nowPosRay = new Ray(transform.position, Vector3.down);
    RaycastHit nextPosHit;
    RaycastHit nowPosHit;
    Vector3 slopeAngle = Vector3.zero;

    Physics.Raycast(nowPosRay, out nowPosHit, 5f, obstaclesLayerMask);
    if (Physics.Raycast(nextPosRay, out nextPosHit, 5f, obstaclesLayerMask))
    {
        slopeAngle = new Vector3(nextPosHit.point.x - nowPosHit.point.x, nextPosHit.point.y - nowPosHit.point.y, 0f).normalized;
    }
    return slopeAngle;
    }

然后我通过计算斜率向量上的重力投影来添加重力:

    private void AddGravity()
    {
    Vector3 gravityForce = new Vector3(0f, -gravityOnPlayer, 0f);
    //my character could be collided by the long vertical wall(colliderStatus.righted)
    //so I set the condition as "!colliderStatus.footed"
    //otherwise, I would use "colliderStatus.inAir"
    if (!colliderStatus.footed)
    {
        gravityForce = new Vector3(0f, -gravityOnPlayer, 0f);
    }
    else
    {
        gravityForce = Vector3.Project(Vector3.down * gravityOnPlayer, SlopeAngleVector());
    }
    rigidbody.AddForce(gravityForce);
    }

现在我的角色可以从跷跷板上滑下来,但它会一直向后退。并且在低坡角跷跷板时无法通过。

如何为跷跷板的跑者制作一个好的行为脚本?

【问题讨论】:

  • 你试过改变速度而不是增加力量吗?

标签: c# unity3d


【解决方案1】:

我建议查看一些 Unity 标准资产角色控制器,我相信他们会在角色移动时考虑坡度。它可能会给你一些想法。

我还建议修改代码计算坡度角度的方式。光线投射命中会给你一个表面法线,然后你应该能够使用 Vector3.Cross 来计算斜坡的角度。

它将类似于:Vector3.Cross(normal, (vector that point away from screen))。

您可能需要对其进行调整以使其正常工作,但这可以在一次光线投射中为您提供倾斜角度。它还可以消除您移动到刚好低于跷跷板的位置的潜在问题。

作为一般提示,尽量不要将变换和刚体混合在一起,如果要移动刚体,请直接移动刚体,而不是通过变换间接移动。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多