aboutsummaryrefslogtreecommitdiffstats
path: root/Assets/Scripts/CharacterController2D.cs
blob: bf624983bedd07cd8f83e866338c534e49f544bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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;
    }
}