Net_Ease_Dome/Assets/Scripts/Input/PlayerMover.cs

256 lines
8.7 KiB
C#

using Invector.vCharacterController;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
using System;
public class PlayerMover : MonoBehaviour
{
public float speed = 3f;
[HideInInspector]
public Vector3 move;
public VariableJoystick variableJoystick;
[HideInInspector] public vThirdPersonController cc;
public UnityEngine.UI.Button JumpButton;
public bool Freeze;
private bool isGrounded;
void Start()
{
isGrounded = true;
Init();
JumpButton.onClick.AddListener(() =>
{
if (JumpConditions())
Jump();
});
}
void Update()
{
if (Freeze) return;
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
move = new Vector3(x, 0, z);
x = x == 0 ? variableJoystick.Horizontal : x;
z = z == 0 ? variableJoystick.Vertical : z;
move = new Vector3(x, 0, z);
if (move != Vector3.zero)
{
move = Quaternion.Euler(0, Camera.main.transform.eulerAngles.y, 0) * move;
transform.position += move * speed * Time.deltaTime;
RotatePlayer();
}
UpdateAnim();
}
void FixedUpdate()
{
CheckGround();
ControlJumpBehaviour();
}
void UpdateAnim()
{
animator.SetFloat("InputMagnitude", move.magnitude);
}
private void RotatePlayer()
{
//向量v围绕y轴旋转cameraAngle.y度
Vector3 vec = Quaternion.Euler(0, 0, 0) * move;
Quaternion qua = Quaternion.LookRotation(vec);
transform.rotation = Quaternion.Lerp(transform.rotation, qua, Time.deltaTime * 100);
}
private void Jump()
{
// trigger jump behaviour
jumpCounter = jumpTimer;
isJumping = true;
// trigger jump animations
if (move.sqrMagnitude < 0.1f)
animator.CrossFadeInFixedTime("Jump", 0.1f);
else
animator.CrossFadeInFixedTime("JumpMove", .2f);
}
protected virtual void ControlJumpBehaviour()
{
if (!isJumping) return;
jumpCounter -= Time.deltaTime;
if (jumpCounter <= 0)
{
jumpCounter = 0;
isJumping = false;
}
// apply extra force to the jump height
var vel = _rigidbody.velocity;
vel.y = jumpHeight;
_rigidbody.velocity = vel;
}
protected bool JumpConditions()
{
return isGrounded && GroundAngle() < slopeLimit && !isJumping ;
}
public float GroundAngle()
{
var groundAngle = Vector3.Angle(groundHit.normal, Vector3.up);
return groundAngle;
}
public float jumpTimer = 0.3f;
public float jumpHeight = 4;
internal float jumpCounter;
private bool isJumping;
private Vector3 input;
[Tooltip("Layers that the character can walk on")]
public LayerMask groundLayer = 1 << 0;
[Tooltip("Distance to became not grounded")]
public float groundMinDistance = 0.25f;
public float groundMaxDistance = 0.5f;
[Tooltip("Max angle to walk")]
[Range(30, 80)] public float slopeLimit = 75f;
[Tooltip("Apply extra gravity when the character is not grounded")]
public float extraGravity = -10f;
internal float groundDistance; // used to know the distance from the ground
internal RaycastHit groundHit; // raycast to hit the ground
internal float heightReached; // max height that character reached in air;
internal float verticalVelocity; // set the vertical velocity of the rigidbody
internal Vector3 colliderCenter; // storage the center of the capsule collider info
internal float colliderRadius, colliderHeight; // storage capsule collider extra information
protected virtual void CheckGround()
{
CheckGroundDistance();
ControlMaterialPhysics();
if (groundDistance <= groundMinDistance)
{
isGrounded = true;
if (!isJumping && groundDistance > 0.05f)
_rigidbody.AddForce(transform.up * (extraGravity * 2 * Time.deltaTime), ForceMode.VelocityChange);
heightReached = transform.position.y;
}
else
{
if (groundDistance >= groundMaxDistance)
{
// set IsGrounded to false
isGrounded = false;
// check vertical velocity
verticalVelocity = _rigidbody.velocity.y;
// apply extra gravity when falling
if (!isJumping)
{
_rigidbody.AddForce(transform.up * extraGravity * Time.deltaTime, ForceMode.VelocityChange);
}
}
else if (!isJumping)
{
_rigidbody.AddForce(transform.up * (extraGravity * 2 * Time.deltaTime), ForceMode.VelocityChange);
}
}
}
protected virtual void ControlMaterialPhysics()
{
return;
//change the physics material to very slip when not grounded
_capsuleCollider.material = (isGrounded && GroundAngle() <= slopeLimit + 1) ? frictionPhysics : slippyPhysics;
if (isGrounded && move == Vector3.zero)
_capsuleCollider.material = maxFrictionPhysics;
else if (isGrounded && move != Vector3.zero)
_capsuleCollider.material = frictionPhysics;
else
_capsuleCollider.material = slippyPhysics;
}
protected virtual void CheckGroundDistance()
{
if (_capsuleCollider != null)
{
// radius of the SphereCast
float radius = _capsuleCollider.radius * 0.9f;
var dist = 10f;
// ray for RayCast
Ray ray2 = new Ray(transform.position + new Vector3(0, colliderHeight / 2, 0), Vector3.down);
// raycast for check the ground distance
if (Physics.Raycast(ray2, out groundHit, (colliderHeight / 2) + dist, groundLayer) && !groundHit.collider.isTrigger)
dist = transform.position.y - groundHit.point.y;
// sphere cast around the base of the capsule to check the ground distance
if (dist >= groundMinDistance)
{
Vector3 pos = transform.position + Vector3.up * (_capsuleCollider.radius);
Ray ray = new Ray(pos, -Vector3.up);
if (Physics.SphereCast(ray, radius, out groundHit, _capsuleCollider.radius + groundMaxDistance, groundLayer) && !groundHit.collider.isTrigger)
{
Physics.Linecast(groundHit.point + (Vector3.up * 0.1f), groundHit.point + Vector3.down * 0.15f, out groundHit, groundLayer);
float newDist = transform.position.y - groundHit.point.y;
if (dist > newDist) dist = newDist;
}
}
groundDistance = (float)System.Math.Round(dist, 2);
}
}
#region Components
internal Animator animator;
internal Rigidbody _rigidbody; // access the Rigidbody component
internal PhysicMaterial frictionPhysics, maxFrictionPhysics, slippyPhysics; // create PhysicMaterial for the Rigidbody
internal CapsuleCollider _capsuleCollider; // access CapsuleCollider information
#endregion
void Init()
{
animator = GetComponent<Animator>();
frictionPhysics = new PhysicMaterial();
frictionPhysics.name = "frictionPhysics";
frictionPhysics.staticFriction = .25f;
frictionPhysics.dynamicFriction = .25f;
frictionPhysics.frictionCombine = PhysicMaterialCombine.Multiply;
// prevents the collider from slipping on ramps
maxFrictionPhysics = new PhysicMaterial();
maxFrictionPhysics.name = "maxFrictionPhysics";
maxFrictionPhysics.staticFriction = 1f;
maxFrictionPhysics.dynamicFriction = 1f;
maxFrictionPhysics.frictionCombine = PhysicMaterialCombine.Maximum;
// air physics
slippyPhysics = new PhysicMaterial();
slippyPhysics.name = "slippyPhysics";
slippyPhysics.staticFriction = 0f;
slippyPhysics.dynamicFriction = 0f;
slippyPhysics.frictionCombine = PhysicMaterialCombine.Minimum;
// rigidbody info
_rigidbody = GetComponent<Rigidbody>();
// capsule collider info
_capsuleCollider = GetComponent<CapsuleCollider>();
// save your collider preferences
colliderCenter = GetComponent<CapsuleCollider>().center;
colliderRadius = GetComponent<CapsuleCollider>().radius;
colliderHeight = GetComponent<CapsuleCollider>().height;
isGrounded = true;
}
}