角色坡度行为
Character Slope Behaviour
我正在开发一款主要专注于户外运动的游戏,因此我希望角色控制感觉尽可能好。
我目前正在解决的问题是斜坡行为:角色站在不太陡的斜坡上不应该滑下,而在太陡的斜坡上滑下。
我通过根据玩家下方地面的当前角度激活和停用刚体约束来实现这一点。
private const RigidbodyConstraints DefaultConstraints = RigidbodyConstraints.FreezeRotation;
private const RigidbodyConstraints StayOnSlope = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ | DefaultConstraints;
private const RigidbodyConstraints SlideDownSlope = DefaultConstraints;
地面的角度以单独的方法计算,返回 up 矢量与地面法线之间的角度(以度为单位)。
private float GetGroundAngle()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, Vector3.down, out hit, 0.5f))
{
return Vector3.Angle(Vector3.up, hit.normal);
}
return 0;
}
约束的实际激活和停用是在 FixedUpdate
方法内部实现的。此外,斜坡越陡,玩家的移动速度就越慢。
private void FixedUpdate()
{
const float MAX_SLOPE_ANGLE = 45;
// If the player is grounded, check the ground angle and prevent slope sliding
float angle = GetGroundAngle();
// Apply the constraints
m_rigidbody.constraints = (m_movementVector.magnitude < Vector3.kEpsilon) && angle <= MAX_SLOPE_ANGLE ? StayOnSlope : SlideDownSlope;
// Calculate the movement coefficient to ensure the player cannot run up slopes
float slopeCoefficient = Mathf.Cos(angle * Mathf.Deg2Rad);
// Calculate and apply the movement vector
Vector3 movement = m_movementVector * slopeCoefficient * Time.fixedDeltaTime;
m_rigidbody.MovePosition(m_rigidbody.position + movement);
// ...
}
此功能的问题如下:
- 玩家在斜坡上站立不动时正确停止,但当向太陡的斜坡移动时,玩家会向下滑动,但会继续向下滑动,直到移动矢量改变或未给出输入完全没有。
预期的结果是,玩家一到可以行走的平坦斜坡上,就会停止下滑,目前情况并非如此。
- 激活和停用约束似乎有点……太老套了,无法在控制器内部使用。
是否有更好的方法来制作坡度移动行为?
The character should not slide down when standing on a slope that is not very steep, and slide down on slopes that are too steep.
我相信 CharacterController 组件可能对您有用。
请注意它有一个可调整的斜率限制变量。
https://docs.unity3d.com/Manual/class-CharacterController.html
在 Unity 标准资产中有一个第一人称控制器实现了这一点,它可以在 Unity 中的资产 -> 导入包 -> 角色下找到。
我正在开发一款主要专注于户外运动的游戏,因此我希望角色控制感觉尽可能好。
我目前正在解决的问题是斜坡行为:角色站在不太陡的斜坡上不应该滑下,而在太陡的斜坡上滑下。
我通过根据玩家下方地面的当前角度激活和停用刚体约束来实现这一点。
private const RigidbodyConstraints DefaultConstraints = RigidbodyConstraints.FreezeRotation;
private const RigidbodyConstraints StayOnSlope = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ | DefaultConstraints;
private const RigidbodyConstraints SlideDownSlope = DefaultConstraints;
地面的角度以单独的方法计算,返回 up 矢量与地面法线之间的角度(以度为单位)。
private float GetGroundAngle()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, Vector3.down, out hit, 0.5f))
{
return Vector3.Angle(Vector3.up, hit.normal);
}
return 0;
}
约束的实际激活和停用是在 FixedUpdate
方法内部实现的。此外,斜坡越陡,玩家的移动速度就越慢。
private void FixedUpdate()
{
const float MAX_SLOPE_ANGLE = 45;
// If the player is grounded, check the ground angle and prevent slope sliding
float angle = GetGroundAngle();
// Apply the constraints
m_rigidbody.constraints = (m_movementVector.magnitude < Vector3.kEpsilon) && angle <= MAX_SLOPE_ANGLE ? StayOnSlope : SlideDownSlope;
// Calculate the movement coefficient to ensure the player cannot run up slopes
float slopeCoefficient = Mathf.Cos(angle * Mathf.Deg2Rad);
// Calculate and apply the movement vector
Vector3 movement = m_movementVector * slopeCoefficient * Time.fixedDeltaTime;
m_rigidbody.MovePosition(m_rigidbody.position + movement);
// ...
}
此功能的问题如下:
- 玩家在斜坡上站立不动时正确停止,但当向太陡的斜坡移动时,玩家会向下滑动,但会继续向下滑动,直到移动矢量改变或未给出输入完全没有。
预期的结果是,玩家一到可以行走的平坦斜坡上,就会停止下滑,目前情况并非如此。 - 激活和停用约束似乎有点……太老套了,无法在控制器内部使用。
是否有更好的方法来制作坡度移动行为?
The character should not slide down when standing on a slope that is not very steep, and slide down on slopes that are too steep.
我相信 CharacterController 组件可能对您有用。
请注意它有一个可调整的斜率限制变量。
https://docs.unity3d.com/Manual/class-CharacterController.html
在 Unity 标准资产中有一个第一人称控制器实现了这一点,它可以在 Unity 中的资产 -> 导入包 -> 角色下找到。