using System.Collections; using System.Linq; using UnityEditor; using UnityEngine; using UnityEngine.UI; [SelectionBase] public class Player : MonoBehaviour { [Header("Asset/Prefab")] [SerializeField] public BuilderManager Builder; [Header("Movement")] [SerializeField] private Rigidbody2D RigidBody; [SerializeField] public Animator Animator; [SerializeField] private SpriteRenderer Renderer; [Header("Character Class")] [SerializeField] private ParticleSystem Aura; [SerializeField] private GameObject[] ClassIndicators; private ClassBase ActiveClass; [SerializeField] private MeleeFighterClass FighterClass; public AttackAnimatorFactory AttackAnimator; [Header("Movement Attributes")] [SerializeField] public float MoveSpeed = 8; [SerializeField] public float MoveSpeedDampener = 1; [SerializeField] private float DashMultiplier = 60; [SerializeField] private float DriftSpeed = 60; [SerializeField] private float DriftFactorial = 0.85f; [SerializeField] private float JumpDelay = 0.5f; [Header("VFX")] [SerializeField] private GameObject VfxDash; private VfxHandlerBase VfxDashHandler; [SerializeField] private GameObject VfxKineticSurge; [HideInInspector] public VfxHandlerBase VfxKineticSurgeHandler; private BoxCollider2D[] BoxColliders; public Vector2 PrevDirection = Vector2.zero; private Vector2 MoveDirection = Vector2.zero; private Directions FaceDir = Directions.Down; public bool IsJumping { get; private set; } public bool IsDashing { get; private set; } public float DashTime { get; private set; } public Vector2 DriftDirection { get; private set; } = Vector2.zero; private float Drift = 0; public bool SkillInUse = false; private enum Directions { Left, Right, Up, Down } void Awake() { Builder = GetComponent(); VfxDashHandler = new VfxHandlerBase(VfxDash, 5, 5); VfxKineticSurgeHandler = new VfxHandlerBase(VfxKineticSurge, 5, 5); FighterClass = new MeleeFighterClass(this); BoxColliders = GetComponentsInChildren(); SetClass(1); } private void Update() { GatherInput(); KeyPressActions(); ActiveClass.Tick(); } private void GatherInput() { MoveDirection.x = Input.GetAxisRaw("Horizontal"); MoveDirection.y = Input.GetAxisRaw("Vertical"); } private void KeyPressActions() { if (Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKeyDown(KeyCode.RightShift)) { Dash(MoveDirection); } else if (!IsJumping && Input.GetKeyDown(KeyCode.Space)) { Jump(); } else if (Input.GetKeyDown(KeyCode.F1)) { SetClass(0); } else if (Input.GetKeyDown(KeyCode.F2)) { SetClass(1); } else if (Input.GetKeyDown(KeyCode.F3)) { SetClass(2); } else if (Input.GetKeyDown(KeyCode.F4)) { SetClass(3); } if (Input.GetKeyDown(KeyCode.X)) ActiveClass.HandlePrimaryAttack(); else if (Input.GetKeyDown(KeyCode.C)) ActiveClass.HandleSecondaryAttack(); } private void Dash(Vector2 direction) { if (Drift > 0.5f) return; IsDashing = true; DashTime = Time.time; RigidBody.linearVelocity = (direction.normalized * MoveSpeed * DashMultiplier) / MoveSpeedDampener; float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg + 180; if (direction.normalized != Vector2.zero) VfxDashHandler.PlayAll(this.transform.position, Quaternion.Euler(0f, 0f, angle)); DriftDirection = direction.normalized; Drift = DriftSpeed; IsDashing = false; } private void Jump() { IsJumping = true; foreach (var col in BoxColliders) col.enabled = false; StartCoroutine(ResetJumpAfterDelay()); } private IEnumerator ResetJumpAfterDelay() { yield return new WaitForSeconds(JumpDelay); foreach (var col in BoxColliders) col.enabled = true; IsJumping = false; } private void SetClass(int classIdx) { Builder.SetBuildMode(classIdx == 3); ActiveClass = FighterClass; foreach (var (indicator, i) in ClassIndicators.Select((obj, i) => (obj, i))) if (i != classIdx) { indicator.transform.localScale = Vector3.one; indicator.transform.rotation = Quaternion.identity; } else { indicator.transform.localScale = Vector3.one * 2; indicator.transform.rotation = Quaternion.AngleAxis(90, Vector3.forward); } RawImage image = ClassIndicators[classIdx].GetComponent(); var main = Aura.main; main.startColor = image.color; } private void FixedUpdate() { MovementUpdate(); CalculateFacingDirection(); UpdateAnimation(); } private void MovementUpdate() { if (IsDashing) return; RigidBody.linearVelocity = (MoveDirection.normalized * MoveSpeed) / MoveSpeedDampener; if (Drift > 0.2f) { RigidBody.linearVelocity += DriftDirection * Drift; Drift *= DriftFactorial; } else { Drift = 0f; } } private void CalculateFacingDirection() { if (MoveDirection.x != 0) if (MoveDirection.x < 0) FaceDir = Directions.Left; else FaceDir = Directions.Right; } private void UpdateAnimation() { string state = GetAnimationState(MoveDirection); if (state.Last() == '_') state = state.Replace("_", ""); else state += LastDirection.ToString(); Animator.CrossFade(state, 0); } public enum Direction { Up, Down, Left, Right } public Direction LastDirection = Direction.Down; private string GetAnimationState(Vector2 input) { if (SkillInUse) return ActiveClass.AnimationToPlay; if (!IsJumping && input.sqrMagnitude < 0.01f) return "Idle"; if (Mathf.Abs(input.x) > 0) LastDirection = (input.x > 0) ? Direction.Right : Direction.Left; else if (Mathf.Abs(input.y) > 0) LastDirection = (input.y > 0) ? Direction.Up : Direction.Down; if (IsJumping) return "Jump"; return "Run"; } void OnDrawGizmos() { DrawPlayerDirection(); } private void DrawPlayerDirection() { if (RigidBody == null) RigidBody = GetComponent(); if (RigidBody == null) return; Gizmos.color = Color.cyan; Vector3 start = RigidBody.transform.position; Vector3 end = start + (Vector3)(RigidBody.linearVelocity * 1); Gizmos.DrawLine(start, end); DrawArrowHead(end, (end - start).normalized); } void DrawArrowHead(Vector3 position, Vector3 direction) { float arrowHeadAngle = 20f; float arrowHeadLength = 0.25f; Vector3 right = Quaternion.Euler(0, 0, arrowHeadAngle) * -direction; Vector3 left = Quaternion.Euler(0, 0, -arrowHeadAngle) * -direction; Gizmos.DrawLine(position, position + right * arrowHeadLength); Gizmos.DrawLine(position, position + left * arrowHeadLength); } }