using UnityEngine; namespace Unity.Cinemachine.Samples { /// /// This is a very basic 2D implementation of SimplePlayerControllerBase. /// /// It requires a [Rigidbody2D](https://docs.unity3d.com/ScriptReference/Rigidbody2D.html) component /// to be placed on the player GameObject. Because it works with a Rigidbody2D, motion control is /// implemented in the `FixedUpdate()` method. /// /// Ground detection only works if the player has a small trigger collider under its feet. /// [RequireComponent(typeof(Rigidbody2D))] public class SimplePlayerController2D : SimplePlayerControllerBase { [Tooltip("Reference to the child object that holds the player's visible geometry. " + "'It is rotated to face the direction of motion")] public Transform PlayerGeometry; [Tooltip("Makes possible to influence the direction of motion while the character is " + "in the air. Otherwise, the more realistic rule that the feet must be touching the ground applies.")] public bool MotionControlWhileInAir; bool m_IsSprinting; bool m_IsGrounded; Rigidbody2D m_Rigidbody2D; #if UNITY_6000_1_OR_NEWER public override bool IsMoving => Mathf.Abs(m_Rigidbody2D.linearVelocity.x) > 0.01f; #else #pragma warning disable CS0618 // obsolete for 6000.0.0f11 and newer public override bool IsMoving => Mathf.Abs(m_Rigidbody2D.velocity.x) > 0.01f; #pragma warning restore CS0618 #endif public bool IsSprinting => m_IsSprinting; public bool IsJumping => !m_IsGrounded; void Start() => TryGetComponent(out m_Rigidbody2D); private void OnEnable() { m_IsGrounded = true; m_IsSprinting = false; } void FixedUpdate() { PreUpdate?.Invoke(); #if UNITY_6000_1_OR_NEWER var vel = m_Rigidbody2D.linearVelocity; #else #pragma warning disable CS0618 // obsolete for 6000.0.0f11 and newer var vel = m_Rigidbody2D.velocity; #pragma warning restore CS0618 #endif // Compute the new velocity and move the player, but only if not mid-jump if (m_IsGrounded || MotionControlWhileInAir) { // Read the input from the user m_IsSprinting = Sprint.Value > 0.5f; vel.x = MoveX.Value * (m_IsSprinting ? SprintSpeed : Speed); if (m_IsGrounded && Mathf.Max(MoveZ.Value, Jump.Value) > 0.01f) vel.y = m_IsSprinting ? SprintJumpSpeed : JumpSpeed; } // Rotate the player to face movement direction if (PlayerGeometry.rotation != null) { if (vel.x > Speed * 0.5f) PlayerGeometry.rotation = Quaternion.Euler(new Vector3(0, 90, 0)); if (vel.x < -Speed * 0.5f) PlayerGeometry.rotation = Quaternion.Euler(new Vector3(0, -90, 0)); } #if UNITY_6000_1_OR_NEWER m_Rigidbody2D.linearVelocity = vel; #else #pragma warning disable CS0618 // obsolete for 6000.0.0f11 and newer m_Rigidbody2D.velocity = vel; #pragma warning restore CS0618 #endif PostUpdate?.Invoke( new Vector3(0, vel.y, Mathf.Abs(vel.x)), m_IsSprinting ? JumpSpeed / SprintJumpSpeed : 1); } // Ground detection only works if the player has a small trigger collider under its feet void OnTriggerEnter2D(Collider2D collision) { if (!collision.isTrigger && !m_IsGrounded) { EndJump?.Invoke(); Landed.Invoke(); m_IsGrounded = true; } } void OnTriggerExit2D(Collider2D collision) { if (!collision.isTrigger && m_IsGrounded) { StartJump?.Invoke(); m_IsGrounded = false; } } void OnTriggerStay2D(Collider2D collision) => OnTriggerEnter2D(collision); } }