diff options
author | Toby Vincent <tobyv13@gmail.com> | 2022-04-08 17:24:16 -0500 |
---|---|---|
committer | Toby Vincent <tobyv13@gmail.com> | 2022-04-08 17:24:16 -0500 |
commit | fb2703b646d22bd4502fab6f0ca58cb922d1ed2c (patch) | |
tree | 37a9584cd0d194082749161fef417cc4c4e965fe /Assets/Scripts/CharacterController2D.cs | |
parent | a16d177920a16d4364e0b1ceff8dc7639ba6ca17 (diff) |
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
Diffstat (limited to 'Assets/Scripts/CharacterController2D.cs')
-rw-r--r-- | Assets/Scripts/CharacterController2D.cs | 154 |
1 files changed, 154 insertions, 0 deletions
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<Rigidbody2D>(); + _collider = GetComponent<CapsuleCollider2D>(); + 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; + } +} |