using System; using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Scripting.APIUpdating; /// /// 角色控制器 /// public class PlayerController : MonoBehaviour { #region 序列化 public Rigidbody[] m_RigsToLift; public ConstantForce m_LeftKneeForce; public ConstantForce m_RightKneeForce; [Header("Gravity")] public Vector3 m_ExtraGravity; [Header("TurnBody")] public float m_TorqueForce; [Header("Stand")] public float m_StandHeight; public float m_StandUpForceMultiplier; public AnimationCurve m_StandUpForceCurve; [Header("Move")] public float m_HorizontalMoveForce; public float m_JumpForce; public float m_SwitchLegInterval; public float m_LegAngle; public float m_TorsoForce; [Header("动画")] public JointAnimation m_MoveAnimation; #endregion #region 公有字段 [NonSerialized] public CharacterInformation info; public Vector3 forward { get { return -transform.forward; } } #endregion #region 私有字段 private Rigidbody[] m_AllRigidBodies; private Rigidbody m_HipRigidBody; private Rigidbody m_HeadRigidBody; private Rigidbody m_TorsoRigidBody; private Rigidbody m_LegLeftRigidBody; private Rigidbody m_LegRightRigidBody; private Quaternion m_TowardDirection; // 朝向角度 private bool m_LastMove; private bool m_DoJump; private bool m_DoMoveLeft; private bool m_DoMoveRight; private float m_StepSwitchTimer; private bool m_IsLeftForward; private float m_FallenGravityFactor; #endregion private void Awake() { InitRigidBodies(); m_HipRigidBody = transform.Find("Rigidbodies/Hip").GetComponent(); m_HeadRigidBody = transform.Find("Rigidbodies/Head").GetComponent(); m_TorsoRigidBody = transform.Find("Rigidbodies/Torso").GetComponent(); m_LegLeftRigidBody = transform.Find("Rigidbodies/Leg_Left").GetComponent(); m_LegRightRigidBody = transform.Find("Rigidbodies/Leg_Right").GetComponent(); info = GetComponent(); m_TowardDirection = Quaternion.Euler(0, -90, 0); m_DoJump = false; m_LastMove = false; } private void Update() { m_DoMoveLeft = false; m_DoMoveRight = false; if (Input.GetKey(KeyCode.A)) { m_TowardDirection = Quaternion.Euler(0, -90, 0); } if (Input.GetKey(KeyCode.D)) { m_TowardDirection = Quaternion.Euler(0, 90, 0); } if (Input.GetKeyDown(KeyCode.W)) { m_DoJump = true; } if (Input.GetKey(KeyCode.A)) { m_DoMoveLeft = true; } if (Input.GetKey(KeyCode.D)) { m_DoMoveRight = true; } m_StepSwitchTimer += Time.deltaTime; if(m_StepSwitchTimer > m_SwitchLegInterval && Vector3.Angle(m_LegLeftRigidBody.transform.up, m_LegRightRigidBody.transform.up) > m_LegAngle) { m_IsLeftForward = !m_IsLeftForward; m_StepSwitchTimer = m_StepSwitchTimer - m_SwitchLegInterval; } } private void FixedUpdate() { StandUp(); TurnBody(); OnMove(); } private void OnMove() { if (!(m_DoMoveLeft || m_DoMoveRight || m_DoJump)) { m_LastMove = false; return; } //if (info.sinceTurn != 0) //{ // return; //} if (!m_LastMove) // enter move { m_StepSwitchTimer = 0; m_LastMove = true; } m_MoveAnimation.Animate(); if(m_DoMoveLeft) { MoveLeft(); } if (m_DoMoveRight) { MoveRight(); } if (m_DoJump) { Jump(); m_DoJump = false; } } void MoveLeft() { DoActionToAllRigidbodies((rig, i) => { rig.AddForce(Vector3.left * m_HorizontalMoveForce * Time.fixedDeltaTime, ForceMode.Acceleration); }); m_TorsoRigidBody.AddForce(Vector3.left * m_TorsoForce, ForceMode.Force); } void MoveRight() { DoActionToAllRigidbodies((rig, i) => { rig.AddForce(Vector3.right * m_HorizontalMoveForce * Time.fixedDeltaTime, ForceMode.Acceleration); }); m_TorsoRigidBody.AddForce(Vector3.right * m_TorsoForce, ForceMode.Force); } void Jump() { if(info.isGrounded || info.sinceGrounded < 0.2f) { Debug.Log("Jump"); DoActionToAllRigidbodies((rig) => { rig.AddForce(Vector3.up * m_JumpForce * Time.fixedDeltaTime, ForceMode.VelocityChange); }); } } private void StandUp() { if (!info.isGrounded) // air { m_FallenGravityFactor += Time.fixedDeltaTime; //m_FallenGravityFactor = Mathf.Clamp(m_FallenGravityFactor, 0, 1); ApplyExtraGravity(); } else // grounded { m_FallenGravityFactor = 0; //Vector3 standUpForce = m_StandUpForce * Vector3.up * (m_StandHeight - info.shortestDistanceFromHeadToGround); float headHeight = info.HeadRayCast(); if(headHeight < m_StandHeight) { float t = 1 - (m_StandHeight - headHeight) / m_StandHeight; t = Mathf.Clamp(t, 0, 1); //Debug.Log(t); Vector3 standUpForce = m_StandUpForceMultiplier * m_StandUpForceCurve.Evaluate(t) * Vector3.up; for (int i = 0; i < m_RigsToLift.Length; i++) { m_RigsToLift[i].AddForce(info.GetTotalMass() * standUpForce + info.GetTotalMass() * -Physics.gravity, ForceMode.Force); } } } if(info.sinceGrounded < 0.3f) { m_LeftKneeForce.enabled = true; m_RightKneeForce.enabled = true; } else { m_LeftKneeForce.enabled = false; m_RightKneeForce.enabled = false; } } private void TurnBody() { Vector3 properForward = m_TowardDirection * -Vector3.forward; float angel = Vector3.Angle(m_HipRigidBody.transform.forward, properForward); Vector3 dir = Vector3.Cross(m_HipRigidBody.transform.forward, properForward); if(Mathf.Abs(angel) < 5f) { info.sinceTurn = 0; } if(dir.y > 0) { m_HipRigidBody.AddTorque(Vector3.up * angel * m_TorqueForce, ForceMode.Acceleration) ; } else if(dir.y < 0) { m_HipRigidBody.AddTorque(-Vector3.up * angel * m_TorqueForce, ForceMode.Acceleration); } } /// /// 初始化rigidbody /// private void InitRigidBodies() //初始化刚体,编号 { this.m_AllRigidBodies = base.GetComponentsInChildren(); DoActionToAllRigidbodies((rig, i) => { }); IgnoreCollision(); } /// /// 屏蔽身体各部件之间的碰撞 /// public void IgnoreCollision() { for (int i = 0; i < m_AllRigidBodies.Length - 1; i++) { for (int j = i + 1; j < m_AllRigidBodies.Length; j++) { Collider collider1 = m_AllRigidBodies[i].GetComponent(); Collider collider2 = m_AllRigidBodies[j].GetComponent(); Physics.IgnoreCollision(collider1, collider2, true); } } } private void ApplyExtraGravity() { DoActionToAllRigidbodies((rig) => { rig.AddForce(m_ExtraGravity * m_FallenGravityFactor, ForceMode.Acceleration); }); } private void DoActionToAllRigidbodies(Action action) { DoActionToAllRigidbodies((rig, i) => { action(rig); }); } private void DoActionToAllRigidbodies(Action action) { for (int i = 0; i < m_AllRigidBodies.Length; ++i) { if (action != null) { action(m_AllRigidBodies[i], i); } } } public bool StepLeft() { return m_IsLeftForward; } public bool StepRight() { return !m_IsLeftForward; } }