using System.Linq; using UnityEngine; public abstract class Character : MonoBehaviour { [SerializeField] protected Animator _animator; [SerializeField] private float _movementSpeed = 1.5f; [SerializeField] protected GameObject _bonesSide; [SerializeField] protected GameObject _bonesBack; [SerializeField] protected GameObject _spawnPoint; [SerializeField] private LayerMask _mapLayer; private Rigidbody2D _body; private CapsuleCollider2D _capsuleCollider; protected bool _isOnBridge; private bool _isOnLadder = false; protected bool _isFalling; protected bool _facingRight = true; protected bool isAllowVertical = true; protected bool isAllowRight = true; protected bool isAllowLeft = true; private Vector2 _cellSize; private void Start() { _body = GetComponent(); _capsuleCollider = GetComponent(); _cellSize = new Vector2(0.6f, 1f); } protected void Spawn() { transform.position = _spawnPoint.transform.position; } protected void MoveTo(float inputHorizontal, float inputVertical) { var block = GetMapElement(); if (block?.ElementSO.ElementType == MapElementType.Water) { Death(); } _isOnBridge = block?.ElementSO.ElementType == MapElementType.Bridge && !_isFalling; if (block) { isAllowVertical = false; _isFalling = false; float h_movement = inputHorizontal; if (h_movement > 0 && !_facingRight || h_movement < 0 && _facingRight) { FlipCharacter(); } SetWalkingAnimation(h_movement != 0); _isOnLadder = block.ElementSO.ElementType == MapElementType.Ladder; if (_isOnLadder) { float ladderCenterDistance = Mathf.Abs(transform.position.x - block.transform.position.x); float v_movement = inputVertical; isAllowVertical = ladderCenterDistance < 0.3f; SetClimbingAnimation(v_movement != 0); _body.velocity = new Vector2(h_movement * _movementSpeed, v_movement * _movementSpeed); } else { _body.velocity = new Vector2(h_movement * _movementSpeed, _body.velocity.y); } } else { _isFalling = true; _isOnLadder = false; } if (_isOnLadder || _isOnBridge) { _body.gravityScale = 0; } else { _body.gravityScale = 1; } if (_isFalling) { _body.velocity = new Vector2(0, _body.velocity.y); SetWalkingAnimation(false); if (block?.ElementSO.ElementType == MapElementType.Ladder) { _body.velocity = Vector2.zero; _isOnLadder = true; } } } private void Death() { OnDeath(); } private MapElement GetMapElement() { var playerBounds = _capsuleCollider.bounds.center; var collider = BoxCast(playerBounds, _cellSize, 0f, Vector3.forward, .01f, _mapLayer); Color color = Color.red; MapElement mapElement = null; if (collider.Length > 0) { var elements=collider.Select(x=>x.transform.GetComponent()); mapElement = elements.Where(x => x.ElementSO.ElementType == MapElementType.Ladder).FirstOrDefault(); if(mapElement == null) { mapElement = elements.First(); } } return mapElement; } protected abstract void OnDeath(); protected abstract void SetWalkingAnimation(bool isWalking); protected abstract void SetClimbingAnimation(bool isClimbing); private void FlipCharacter() { Vector3 currentScale = gameObject.transform.localScale; currentScale.x *= -1; gameObject.transform.localScale = currentScale; _facingRight = !_facingRight; } static public Collider2D[] BoxCast(Vector2 origin, Vector2 size, float angle, Vector2 direction, float distance, int mask) { //RaycastHit2D hit = Physics2D.BoxCast(origin, size, angle, direction, distance, mask); var collider = Physics2D.OverlapBoxAll(origin, size, angle, mask); //Setting up the points to draw the cast Vector2 p1, p2, p3, p4, p5, p6, p7, p8; float w = size.x * 0.5f; float h = size.y * 0.5f; p1 = new Vector2(-w, h); p2 = new Vector2(w, h); p3 = new Vector2(w, -h); p4 = new Vector2(-w, -h); Quaternion q = Quaternion.AngleAxis(angle, new Vector3(0, 0, 1)); p1 = q * p1; p2 = q * p2; p3 = q * p3; p4 = q * p4; p1 += origin; p2 += origin; p3 += origin; p4 += origin; Vector2 realDistance = direction.normalized * distance; p5 = p1 + realDistance; p6 = p2 + realDistance; p7 = p3 + realDistance; p8 = p4 + realDistance; //Drawing the cast Color castColor = collider.Length > 0 ? Color.red : Color.green; Debug.DrawLine(p1, p2, castColor); Debug.DrawLine(p2, p3, castColor); Debug.DrawLine(p3, p4, castColor); Debug.DrawLine(p4, p1, castColor); Debug.DrawLine(p5, p6, castColor); Debug.DrawLine(p6, p7, castColor); Debug.DrawLine(p7, p8, castColor); Debug.DrawLine(p8, p5, castColor); Debug.DrawLine(p1, p5, Color.grey); Debug.DrawLine(p2, p6, Color.grey); Debug.DrawLine(p3, p7, Color.grey); Debug.DrawLine(p4, p8, Color.grey); //collider //if (hit) //{ // var color = hit.point.x > origin.x ? Color.yellow : Color.cyan; // Debug.DrawLine(hit.point, hit.point + hit.normal.normalized * 0.2f, color); //} return collider; } }