using UnityEngine;
using UnityEngine.InputSystem;
public class CharacterMovement : MonoBehaviour
{
[SerializeField]
Rigidbody rb;
[SerializeField]
InputActionAsset controls;
[SerializeField]
InputAction move;
[Header("Debug")]
[SerializeField]
float currentVelocity;
[SerializeField]
float horizontalVelocity;
float deltaTimeOffset = 100f;
[Header("Movement")]
[SerializeField]
Vector2 movementDirection;
[SerializeField]
float speed;
[SerializeField]
float acceleration;
Vector3 counterDir;
[SerializeField]
bool grounded;
[SerializeField]
bool onSlope;
[SerializeField]
float maxSlopeAngle;
[SerializeField]
float slopeAngle;
[SerializeField]
Vector3 slopePlane;
[SerializeField]
float touchSlopeAngle;
float slopeSlideMultiplier = 0;
void Awake()
{
rb = gameObject.GetComponent<Rigidbody>();
move = controls.FindActionMap("Player").FindAction("Move");
}
void Update()
{
currentVelocity = rb.linearVelocity.magnitude;
horizontalVelocity = Vector3.Magnitude(new Vector3(rb.linearVelocity.x, 0, rb.linearVelocity.z));
InputReader();
}
void FixedUpdate()
{
if (!onSlope)
{
rb.AddForce(Vector3.down * Time.deltaTime * 800f, ForceMode.Acceleration);
}
if (touchSlopeAngle > maxSlopeAngle)
{
rb.AddForce(Vector3.down * 4000f * Time.deltaTime, ForceMode.Acceleration);
}
if (touchSlopeAngle > maxSlopeAngle && touchSlopeAngle < 87f)
{
slopeSlideMultiplier = 0.25f;
}
else
{
slopeSlideMultiplier = 1f;
}
HorizontalMovement();
CounterMovement();
SlopeMovement();
}
void InputReader()
{
movementDirection = move.ReadValue<Vector2>();
}
void HorizontalMovement()
{
Vector3 moveDir = SlopeMovement();
rb.AddForce(moveDir.normalized * speed * acceleration * Time.deltaTime * deltaTimeOffset * slopeSlideMultiplier, ForceMode.Acceleration);
if (horizontalVelocity <= 0.001f)
{
rb.linearVelocity = new Vector3(0, rb.linearVelocity.y, 0);
}
}
void CounterMovement()
{
if (movementDirection.magnitude <= 0.001f && horizontalVelocity <= 0.001f)
{
return;
}
if (onSlope || grounded)
{
counterDir = rb.linearVelocity;
}
else
{
counterDir = new Vector3(rb.linearVelocity.x, 0, rb.linearVelocity.z);
}
rb.AddForce(counterDir * -acceleration * Time.deltaTime * deltaTimeOffset, ForceMode.Acceleration);
}
Vector3 SlopeMovement()
{
Vector3 wishDir = transform.forward * movementDirection.y + transform.right * movementDirection.x;
bool slopeCheck = Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, 1.5f);
slopeAngle = Vector3.Angle(Vector3.up, slopePlane);
slopePlane = hit.normal;
if (slopeAngle > maxSlopeAngle || slopeAngle <= 0.001f)
{
onSlope = false;
}
else
{
onSlope = slopeCheck;
}
if (!onSlope)
{
rb.useGravity = true;
return wishDir;
}
if (rb.linearVelocity.y > 0)
{
rb.AddForce(Vector3.down * 800f * Time.deltaTime, ForceMode.Acceleration);
}
rb.useGravity = false;
return Vector3.ProjectOnPlane(wishDir, slopePlane).normalized;
}
void OnCollisionStay(Collision collision)
{
for (int contactpoint = 0; contactpoint < collision.contactCount; contactpoint++)
{
Vector3 touchSlope = collision.GetContact(contactpoint).normal;
touchSlopeAngle = Vector3.Angle(Vector3.up, touchSlope);
if (Vector3.Dot(touchSlope.normalized, Vector3.up) >= 0.975f)
{
grounded = true;
}
else
{
grounded = false;
}
}
}
void OnCollisionExit(Collision collision)
{
touchSlopeAngle = 0;
grounded = false;
onSlope = false;
}
}
评论 (0)