using UnityEngine; using UnityEngine.InputSystem; public enum AttackState : byte { Idle = 0, Light, Medium, Heavy } [RequireComponent(typeof(Rigidbody2D), typeof(Animator), typeof(InputBase))] public class Player : MonoBehaviour { // Will want to create an "Input Actions" asset, this should allow the user to set their bindings in a menu and I'll be able to load that during the game. // The above is super important for this prototype, but could be used for all other prototypes. public float speed; public float jumpForce; public HitBox bodyHitBox; public HitBox lightHitBox; public HitBox mediumHitBox; public HitBox heavyHitBox; public float maxHealth; private Rigidbody2D _rigidbody; private bool _isGrounded; private Vector2 _verticalVelocity; private Animator _animator; private AttackState _currentAttack; private int _currentAnimationStateIndex; private InputBase _input; private float _health; private float _hitStunStartTime; private float _hitStunDuration; private bool _isHitStun; private const string CurrentAttackText = "CurrentAttack"; private bool IsAttacking => _currentAttack != AttackState.Idle; private void Start() { _health = maxHealth; _rigidbody = GetComponent(); _animator = GetComponent(); _input = GetComponent(); _input.AttackCallback = ChangeAttackingState; _rigidbody.gravityScale = 0; if (_animator.parameterCount < 1) { Debug.LogAssertion("Animator needs to have one property named \"CurrentState\""); } foreach (var parameter in _animator.parameters) { if (parameter.name == CurrentAttackText) { _currentAnimationStateIndex = parameter.nameHash; } } bodyHitBox.DamageAmount = 0; bodyHitBox.DoesDealDamage = false; bodyHitBox.TakeDamage += DealDamage; lightHitBox.TakeDamage += DealDamage; mediumHitBox.TakeDamage += DealDamage; heavyHitBox.TakeDamage += DealDamage; } private void DealDamage(float damage, float hitStunDuration) { _health -= damage; _hitStunDuration = hitStunDuration; _hitStunStartTime = Time.time; _isHitStun = true; _animator.SetBool("IsHitStun", _isHitStun); if (_health <= 0) { Debug.Log("You are dead!"); } } public float HealthPercent() => _health / maxHealth; public void StopAttack() { _currentAttack = AttackState.Idle; } private void ChangeAttackingState(AttackState state) { _currentAttack = state; } private void JumpPerform(InputAction.CallbackContext callbackContext) { if (_isGrounded) { _verticalVelocity.y = jumpForce; _verticalVelocity.x = _input.GetMovementDirection() * speed; _isGrounded = false; } } private void Update() { if (_isGrounded) { if (Time.time >= _hitStunStartTime + _hitStunDuration) { _isHitStun = false; _animator.SetBool("IsHitStun", _isHitStun); } if (!IsAttacking && !_isHitStun) { var dir = _input.GetMovementDirection(); var pos = _rigidbody.position; pos.x += dir * speed * Time.deltaTime; _rigidbody.position = pos; } _animator.SetInteger(_currentAnimationStateIndex, (int)_currentAttack); } else { var pos = _rigidbody.position; pos += _verticalVelocity * Time.deltaTime; _rigidbody.position = pos; _verticalVelocity += Physics2D.gravity * Time.deltaTime; } } private void OnCollisionEnter2D(Collision2D other) { foreach (var contact in other.contacts) { // Depending how crouch is implemented this might break or be fickle. if (contact.point.y < _rigidbody.transform.position.y) { _isGrounded = true; break; } } } }