Slopes - Done!

This commit is contained in:
2021-02-02 22:49:43 +08:00
parent 676700ecfa
commit 3904d75eea
21 changed files with 14097 additions and 168 deletions

View File

@@ -9,23 +9,35 @@ public class MovingSphere : MonoBehaviour
private float maxAcceleration = 10f, maxAirAcceleration = 1f;
[SerializeField, Range(0f, 10f)]
float jumpHeight = 2f;
private float jumpHeight = 2f;
[SerializeField, Range(0, 5)]
int maxAirJumps = 0;
private int maxAirJumps = 0;
[SerializeField, Range(0f, 90f)]
private float maxGroundAngle = 25f;
private Rigidbody body;
private Vector3 desiredVelocity = new Vector3(0f, 0f, 0f);
private bool desiredJump = false;
private bool onGround;
private int groundContactCount;
private bool onGround => groundContactCount > 0;
private int jumpPhase;
private Vector3 velocity;
private Vector3 contactNormal;
private float minGroundDotProduct;
private void OnValidate()
{
minGroundDotProduct = Mathf.Cos(maxGroundAngle * Mathf.Deg2Rad);
}
private void Awake()
{
body = GetComponent<Rigidbody>();
OnValidate();
}
private void Update()
@@ -43,10 +55,7 @@ public class MovingSphere : MonoBehaviour
{
UpdateState();
float acceleration = onGround ? maxAcceleration : maxAirAcceleration;
float maxSpeedChange = acceleration * Time.deltaTime;
velocity.x = Mathf.MoveTowards(velocity.x, desiredVelocity.x, maxSpeedChange);
velocity.z = Mathf.MoveTowards(velocity.z, desiredVelocity.z, maxSpeedChange);
AdjustVelocity();
if (desiredJump)
{
@@ -56,7 +65,7 @@ public class MovingSphere : MonoBehaviour
body.velocity = velocity;
onGround = false;
ClearState();
}
private void UpdateState()
@@ -65,6 +74,14 @@ public class MovingSphere : MonoBehaviour
if (onGround)
{
jumpPhase = 0;
if (groundContactCount > 1)
{
contactNormal.Normalize();
}
}
else
{
contactNormal = Vector3.up;
}
}
@@ -83,7 +100,11 @@ public class MovingSphere : MonoBehaviour
for (int i = 0; i < collision.contactCount; i++)
{
var normal = collision.GetContact(i).normal;
onGround |= normal.y >= 0.9f;
if (normal.y >= minGroundDotProduct)
{
groundContactCount += 1;
contactNormal += normal;
}
}
}
@@ -93,12 +114,42 @@ public class MovingSphere : MonoBehaviour
{
jumpPhase++;
float jumpSpeed = Mathf.Sqrt(-2f * Physics.gravity.y * jumpHeight);
if (velocity.y > 0f)
float alignedSpeed = Vector3.Dot(velocity, contactNormal);
if (alignedSpeed > 0f)
{
jumpSpeed = Mathf.Max(jumpSpeed - velocity.y, 0f);
jumpSpeed = Mathf.Max(jumpSpeed - alignedSpeed, 0f);
}
velocity.y += jumpSpeed;
velocity += contactNormal * jumpSpeed;
}
}
private void AdjustVelocity()
{
Vector3 xAxis = ProjectOnContactPlane(Vector3.right).normalized;
Vector3 zAxis = ProjectOnContactPlane(Vector3.forward).normalized;
float currentX = Vector3.Dot(velocity, xAxis);
float currentZ = Vector3.Dot(velocity, zAxis);
float acceleration = onGround ? maxAcceleration : maxAirAcceleration;
float maxSpeedChange = acceleration * Time.deltaTime;
float newX =
Mathf.MoveTowards(currentX, desiredVelocity.x, maxSpeedChange);
float newZ =
Mathf.MoveTowards(currentZ, desiredVelocity.z, maxSpeedChange);
velocity += xAxis * (newX - currentX) + zAxis * (newZ - currentZ);
}
private Vector3 ProjectOnContactPlane(Vector3 vector)
{
return vector - contactNormal * Vector3.Dot(vector, contactNormal);
}
void ClearState()
{
groundContactCount = 0;
contactNormal = Vector3.zero;
}
}