From fb2703b646d22bd4502fab6f0ca58cb922d1ed2c Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Fri, 8 Apr 2022 17:24:16 -0500 Subject: wip: no regerts fix jump; race condition(ish) in jump/fall/land events (?) impl trigger animations on events refactor control, (follow) camera, anim handlers into interfaces impl controller pattern for controls (FSM using lambdas + interfaces) come up with the rest of the todos --- Assets/Scripts/CharacterController2D.cs | 154 ++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 Assets/Scripts/CharacterController2D.cs (limited to 'Assets/Scripts/CharacterController2D.cs') diff --git a/Assets/Scripts/CharacterController2D.cs b/Assets/Scripts/CharacterController2D.cs new file mode 100644 index 0000000..bf62498 --- /dev/null +++ b/Assets/Scripts/CharacterController2D.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.Events; + +[RequireComponent(typeof(Rigidbody2D))] +[RequireComponent(typeof(CapsuleCollider2D))] + +public class CharacterController2D : MonoBehaviour +{ + public enum Direction + { + left = -1, + right = 1 + } + + [SerializeField] Camera mainCamera; + [SerializeField] float acceleration = 40f; + [SerializeField][Range(0, .3f)] float smoothing = .05f; + [SerializeField] float gravityScale = 1.5f; + [SerializeField] float jumpForce = 50f; + [SerializeField] int maxJumpCount = 1; + [SerializeField] bool airControl = true; + + internal UnityEvent OnIdleEvent; + internal UnityEvent OnFlip; + internal UnityEvent OnJump; + internal UnityEvent OnLand; + internal UnityEvent OnFall; + + public Direction direction = Direction.right; + public Vector2 velocity = Vector2.zero; + public int jumpCount = 0; + public bool isGrounded = false; + public Vector3 cameraPos; + public Rigidbody2D _rigidBody; + public CapsuleCollider2D _collider; + public Transform _transform; + + void Awake() + { + _rigidBody = GetComponent(); + _collider = GetComponent(); + OnIdleEvent ??= new UnityEvent(); + OnFlip ??= new UnityEvent(); + OnJump ??= new UnityEvent(); + OnFall ??= new UnityEvent(); + OnLand ??= new UnityEvent(); + } + + // Use this for initialization + void Start() + { + _transform = transform; + _rigidBody.freezeRotation = true; + _rigidBody.collisionDetectionMode = CollisionDetectionMode2D.Continuous; + _rigidBody.gravityScale = gravityScale; + direction = (Direction)(_transform.localScale.x / Mathf.Abs(_transform.localScale.x)); + + jumpCount = maxJumpCount; + + if (mainCamera) + cameraPos = mainCamera.transform.position; + + OnFlip.AddListener(HandleFlip); + OnJump.AddListener(HandleJump); + OnFall.AddListener(HandleFall); + OnLand.AddListener(HandleLand); + } + + void Update() + { + if (isGrounded || airControl) + HandleHorzInput(Input.GetAxisRaw("Horizontal")); + + // Changing this to `canJump` or `jumpCount > 0` would allow for things like double jumping. + if (jumpCount > 0 && Input.GetButtonDown("Jump")) + OnJump.Invoke(); + + + if (mainCamera) + { + var targetPos = new Vector3(_transform.position.x, cameraPos.y, cameraPos.z); + mainCamera.transform.position = Vector3.Lerp(mainCamera.transform.position, targetPos, 0.25f); + } + } + + void FixedUpdate() + { + CheckCollision(); + } + + public void Move(float magnitude) + { + Vector3 targetVelocity = new Vector2(magnitude, _rigidBody.velocity.y); + _rigidBody.velocity = Vector2.SmoothDamp(_rigidBody.velocity, targetVelocity, ref velocity, smoothing); + } + + void CheckCollision() + { + var evnt = isGrounded ? OnFall : OnLand; + + float colliderRadius = _collider.size.x * 0.4f * Mathf.Abs(transform.localScale.x); + Vector3 groundCheckPos = new Vector3(_collider.bounds.size.x * 0.5f, colliderRadius * 0.9f, 0) + _collider.bounds.min; + Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckPos, colliderRadius); + + if (Array.Exists(colliders, c => c != _collider)) + { + Debug.Log(Array.Find(colliders, c => c != _collider)); + evnt.Invoke(); + } + } + + void HandleHorzInput(float horzInput) + { + Move(horzInput * acceleration); + + if (horzInput * (int)direction < 0) + OnFlip.Invoke(); + } + + + void HandleFlip() + { + Debug.Log("Flipping"); + Vector3 theScale = transform.localScale; + theScale.x *= -1; + transform.localScale = theScale; + + direction = direction == Direction.left ? Direction.right : Direction.left; + } + + void HandleJump() + { + Debug.Log("Jumping"); + jumpCount--; + _rigidBody.AddForce(Vector2.up * jumpForce); + OnFall.Invoke(); + } + + + void HandleFall() + { + Debug.Log("Falling"); + isGrounded = false; + } + + void HandleLand() + { + Debug.Log("Landing"); + isGrounded = true; + jumpCount = maxJumpCount; + } +} -- cgit v1.2.3-70-g09d2