diff options
Diffstat (limited to 'ActiveRagdoll/Assets/Scripts/PlayerController.cs')
-rw-r--r-- | ActiveRagdoll/Assets/Scripts/PlayerController.cs | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/ActiveRagdoll/Assets/Scripts/PlayerController.cs b/ActiveRagdoll/Assets/Scripts/PlayerController.cs new file mode 100644 index 0000000..21eaa01 --- /dev/null +++ b/ActiveRagdoll/Assets/Scripts/PlayerController.cs @@ -0,0 +1,315 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Unity.VisualScripting; +using UnityEngine; +using UnityEngine.Scripting.APIUpdating; + +/// <summary> +/// 角色控制器 +/// </summary> +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<Rigidbody>(); + m_HeadRigidBody = transform.Find("Rigidbodies/Head").GetComponent<Rigidbody>(); + m_TorsoRigidBody = transform.Find("Rigidbodies/Torso").GetComponent<Rigidbody>(); + m_LegLeftRigidBody = transform.Find("Rigidbodies/Leg_Left").GetComponent<Rigidbody>(); + m_LegRightRigidBody = transform.Find("Rigidbodies/Leg_Right").GetComponent<Rigidbody>(); + + info = GetComponent<CharacterInformation>(); + + 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); + } + } + + /// <summary> + /// 初始化rigidbody + /// </summary> + private void InitRigidBodies() //初始化刚体,编号 + { + this.m_AllRigidBodies = base.GetComponentsInChildren<Rigidbody>(); + DoActionToAllRigidbodies((rig, i) => { + }); + + IgnoreCollision(); + } + + /// <summary> + /// 屏蔽身体各部件之间的碰撞 + /// </summary> + 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>(); + Collider collider2 = m_AllRigidBodies[j].GetComponent<Collider>(); + Physics.IgnoreCollision(collider1, collider2, true); + } + } + } + + private void ApplyExtraGravity() + { + DoActionToAllRigidbodies((rig) => { + rig.AddForce(m_ExtraGravity * m_FallenGravityFactor, ForceMode.Acceleration); + }); + } + + private void DoActionToAllRigidbodies(Action<Rigidbody> action) + { + DoActionToAllRigidbodies((rig, i) => { + action(rig); + }); + } + + private void DoActionToAllRigidbodies(Action<Rigidbody, int> 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; + } + +}
\ No newline at end of file |