【发布时间】:2020-01-13 17:59:01
【问题描述】:
我正在使用 Unity 开发一个 2D 项目。
角色控制器是基于物理的,所以我使用刚体来移动玩家。一切正常,除非我尝试对角色应用高速运动,如破折号。
这就是代码的样子。
我只是检查玩家是否在冲刺,所以我将Vector2的运动量增加了一定量。
private void DashMovement() {
if (isDashing) {
movement.x *= dashFactor;
}
}
我也在计算地面角度,所以我将运动矢量设置为跟随地面倾斜度。
private void OnSlopeMovement() {
if (isGrounded && !isJumping) {
float moveDistance = Mathf.Abs(movement.x);
float horizontalOnSlope = Mathf.Cos(groundAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign(movement.x);
float verticalOnSlope = Mathf.Sin(groundAngle * Mathf.Deg2Rad) * moveDistance;
if (horizontalOnSlope != 0)
movement.x = horizontalOnSlope;
if (isGrounded && verticalOnSlope != 0)
movement.y = verticalOnSlope;
}
SetMaxFallVelocity();
}
所以我设置了刚体速度以使其移动。
private void Move() {
movement.x *= Time.fixedDeltaTime;
if(isGrounded && !isJumping) movement.y *= Time.fixedDeltaTime;
Vector3 targetVelocity = new Vector2(movement.x, movement.y);
PlayerController.rb2d.velocity = Vector3.SmoothDamp(PlayerController.rb2d.velocity, targetVelocity, ref velocity, movementSmoothing);
}
当我应用足够高的速度时会出现问题。我知道这个问题是因为物理学。 我认为检查地面并用于计算 groundAngle 的光线工作速度不够快,无法跟踪该运动,因此我无法将玩家固定在地面上。
我想在不使玩家运动或在斜坡上停止冲刺的情况下找到解决方案。
And this is how the rigidbody movement remain right over the ground, following the slopes angle.
编辑:
这就是我获得地面角度的方式:
private void GroundAngle() {
Vector2 rayOrigin = feetCollider.bounds.center;
rayOrigin.y += 0.1f;
Vector2 rayDirection = (Input.GetAxisRaw("Horizontal") == 0) ? Vector2.right : new Vector2(Input.GetAxisRaw("Horizontal"), 0);
int groundCollisions = Physics2D.RaycastNonAlloc(rayOrigin, Vector2.down, groundResults, Mathf.Infinity, groundMask);
if (groundCollisions > 0) {
groundAngle = Vector2.Angle(groundResults[0].normal, rayDirection) - 90f;
//Debug.DrawRay(rayOrigin, Vector2.down, Color.green);
if (groundAngle > 0 && !isDashing) {
rayOrigin.x += Input.GetAxisRaw("Horizontal") * .125f;
Physics2D.RaycastNonAlloc(rayOrigin, Vector2.down, groundResults, Mathf.Infinity, groundMask);
groundAngle = Vector2.Angle(groundResults[0].normal, rayDirection) - 90f;
//Debug.DrawRay(rayOrigin, Vector2.down, Color.blue);
}
}
}
感谢@Ruzhim 的帮助。我只是为这个问题发布了第一个“解决方案”。 根据 Ruzhim 的建议,我是这样使用他的代码的。
private void SetPositionAfterTick() {
if (isDashMovement) {
Vector2 currentPosition = new Vector2(transform.position.x, transform.position.y);
currentPosition.y = feetCollider.bounds.min.y;
Vector2 feetPosAfterTick = currentPosition + PlayerController.rb2d.velocity * Time.deltaTime;
float maxFloorCheckDist = .1f;
RaycastHit2D groundCheckAfterTick = Physics2D.Raycast(feetPosAfterTick + Vector2.up * maxFloorCheckDist, Vector2.down, maxFloorCheckDist * 5f);
if (groundCheckAfterTick) {
Vector2 wantedFeetPosAfterTick = groundCheckAfterTick.point;
if (wantedFeetPosAfterTick != feetPosAfterTick) {
//PlayerController.rb2d.transform.position = (wantedFeetPosAfterTick + new Vector2(0f, feetCollider.bounds.min.y - PlayerController.rb2d.position.y));
PlayerController.rb2d.velocity = Vector2.zero;
}
}
}
}
这足以继续完善该机制。我仍然需要以某种方式设置位置。刚体的位置计算不起作用 现在被提升,因为条件 (wantedFeetPosAfterTick != feetPosAfterTick) 始终为真,所以角色会摔倒地板并摔倒。
如你所见,我还需要控制下坡运动,因为它有时会使用斜坡运动,而其他人则向前冲刺。
【问题讨论】:
-
我个人认为 dash-into-a-ramp-to-fly 看起来很有趣的游戏机制,但我是一个老部落玩家 ;)
-
这种交互对于那个速度来说是正常的,当使用基于物理的交互时,你可以真正操纵结果的唯一方法是在你的斜率中添加可能的某种物理材料,但这可能会减慢你的家伙下来,或调整他的质量?我倾向于从我的玩家运动中删除物理并进行自己的计算以“伪造”物理,所以像这样的技能我只会投射他正在移动的位置,创建一个效果来越过该区域并在效果之后将他移动到那里结束...
-
但正如@Ruzihm 所说,这看起来可能是一个有趣的功能。
-
是的,我第一次看到它时就想到了它,但我认为并不是每个斜坡都可能发生这种情况。在某些方面会是一个不错的机制,并且有意识地实现某些目标。关于您的回答@AresCaelum,我只想在更改控制器之前花费我的可能性。
-
如果你冲下斜坡会发生什么?