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(); 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(); // capsule collider info _capsuleCollider = GetComponent(); // save your collider preferences colliderCenter = GetComponent().center; colliderRadius = GetComponent().radius; colliderHeight = GetComponent().height; isGrounded = true; } }