【发布时间】: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
}
我试过这些方法:
-
对刚体施加力以向前移动
//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);
效果不好,因为角色在跷跷板上时会继续上升,尽管跷跷板开始倾斜。并且当角色从较高的平面跌落到地面或跳跃后会有速度损失,看起来角色会在着陆点上眩晕片刻,然后开始加速。
-
使用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);
}
现在我的角色可以从跷跷板上滑下来,但它会一直向后退。并且在低坡角跷跷板时无法通过。
如何为跷跷板的跑者制作一个好的行为脚本?
【问题讨论】:
-
你试过改变速度而不是增加力量吗?