using System.Collections; using System.Collections.Generic; using TreeEditor; using UnityEngine; using UnityEngine.InputSystem; [System.Serializable] public class PlayerStat { public PlayerData data; public PlayerStat() { } public PlayerStat(PlayerData data) { this.data = data; } } public class PlayerController : MonoBehaviour { [Header("Player Datas")] [SerializeField] private PlayerData playerData; // 런타임에서 계산된 스탯을 담아둘 리스트 private PlayerStat playerStat; private PlayerStat currentStat; [SerializeField] private Rigidbody2D rbody; private Vector2 moveInput; private float axisH = 0.0f; // 좌우 입력 값 저장 bool isDash = false; // 대시 플래그 bool goJump = false; // 점프 개시 플래그 bool isDead = false; // 사망 플래그 bool onGround = false; // 지면에 서 있는 플래그 bool isHit = false; private bool isInvincible = false; public LayerMask groundLayer; // 착지할 수 있는 레이어 private Animator animator; private Animator nanimator; private Animator tanimator; private PlayerAttacks playerAttacks; SpriteRenderer spriteRenderer; [SerializeField] private GameObject nano; [SerializeField] private GameObject tera; bool isnano = false; bool istera = false; int CurrentHp; [Header("Tag System")] private float maxGauge = 60f; // 한 칸을 채우는 데 필요한 게이지 private float CurrentGauge; private int TagCount; private int maxTagCount = 5; void Start() { if (playerData != null) playerStat = new PlayerStat(playerData); nano.SetActive(true); isnano = true; tera.SetActive(false); currentStat = playerStat; rbody = GetComponent(); nanimator = nano.GetComponent(); tanimator = tera.GetComponent(); playerAttacks = GetComponent(); CurrentHp = playerStat.data.playerHp; CurrentGauge = playerStat.data.playerCurrentGauge; TagCount = playerStat.data.playerTagCount; } public void ChargeTagGauge(float amount) { // 태그 카운트가 이미 최대라면 더 이상 충전하지 않음 if (TagCount >= maxTagCount) return; CurrentGauge += amount; Debug.Log($"게이지 충전: +{amount} / 현재 게이지: {CurrentGauge}"); // 게이지가 60을 넘었을 때 카운트 처리 (이월 포함) while (CurrentGauge >= maxGauge && TagCount < maxTagCount) { CurrentGauge -= maxGauge; // 오버된 만큼 이월 TagCount++; Debug.Log($"태그 카운트 상승! 현재 카운트: {TagCount}"); // 카운트가 최대치에 도달하면 게이지를 0으로 고정하고 탈출 if (TagCount >= maxTagCount) { CurrentGauge = 0; Debug.Log("태그 카운트 최대 도달! 태그 준비 완료."); break; } } } public void OnTagKey(InputValue value) { if (isDead) return; if (!value.isPressed) return; if (TagCount < maxTagCount) { Debug.Log($"태그 불가! 카운트가 부족합니다. (현재: {TagCount}/{maxTagCount})"); return; } Debug.Log(" Z 버튼 눌림! "); isnano = !isnano; istera = !isnano; nano.SetActive(isnano); tera.SetActive(istera); if (CurrentHp < 5) { CurrentHp += 1; } animator = (isnano) ? nanimator : tanimator; TagCount = 0; CurrentGauge = 0; } void OnMove(InputValue value) { if (isDead) return; // Vector2 값 중 x축(좌우) 값만 가져옴 Vector2 inputVector = value.Get(); axisH = inputVector.x; } void OnDash(InputValue value) { if (isDead) return; isDash = value.isPressed; if (isDash) Debug.Log("대시 중..."); else Debug.Log("대시 중단"); } public void OnJump(InputValue value) { if (isDead) return; // 버튼이 눌린 순간(isPressed)이고 지면 위라면 점프 예약 if (value.isPressed && onGround) { goJump = true; if (isnano) nanimator.SetBool("jump", true); else if (istera) tanimator.SetBool("jump", true); Debug.Log(" 점프 버튼 눌림! "); } } public void OnSAtk(InputValue value) { if (isDead) return; if (!value.isPressed) return; Debug.Log(" s 버튼 눌림! "); if (playerAttacks.IsAnyWeaponInUse) return; playerAttacks.IsAnyWeaponInUse = true; StartCoroutine(playerAttacks.ableAtk(0, "SAtk", isnano)); } public void OnAAtk(InputValue value) { if (isDead) return; if (!value.isPressed) return; Debug.Log(" a 버튼 눌림! "); if (playerAttacks.IsAnyWeaponInUse) return; playerAttacks.IsAnyWeaponInUse = true; StartCoroutine(playerAttacks.ableAtk(0, "AAtk", isnano)); } void Update() { if (isDead) return; bool isMoving = axisH != 0; // 지면 상태 확인 if (isnano) nanimator.SetBool("jump", !onGround); else if (istera) tanimator.SetBool("jump", !onGround); if (isnano) nanimator.SetBool("Dash", isDash); else if (istera) tanimator.SetBool("Dash", isDash); if (isnano) nanimator.SetBool("Move", isMoving); else if (istera) tanimator.SetBool("Move", isMoving); // 플래그 초기화 if (Keyboard.current.leftShiftKey.wasReleasedThisFrame) isDash = false; // 방향 조절 if (isMoving && !playerAttacks.IsAnyWeaponInUse) { float direction = axisH > 0 ? 1 : -1; transform.localScale = new Vector2(direction, 1); } else { if (isnano) nanimator.SetBool("Dash", false); else if (istera) tanimator.SetBool("Dash", false); } } private void FixedUpdate() { onGround = Physics2D.Linecast(transform.position, transform.position - (transform.up * 0.1f), groundLayer); if (isDead || isHit) return; // 공격중인지 확인 if (playerAttacks.IsAnyWeaponInUse && onGround) { rbody.linearVelocity = new Vector2(0, rbody.linearVelocity.y); // 정지 return; } float speed = (isDash && onGround) ? currentStat.data.playerDashSpeed : currentStat.data.playerDefaultSpeed; rbody.linearVelocity = new Vector2(axisH * speed, rbody.linearVelocity.y); if (goJump) { Debug.Log("점프!"); rbody.AddForce(Vector2.up * currentStat.data.playerJumpPower, ForceMode2D.Impulse); goJump = false; } } private void OnTriggerEnter2D(Collider2D collision) { if (isDead) return; if (collision.CompareTag("Goal")) { GameStop(); } else if (collision.CompareTag("Dead")) { GameOver(); } } public void TakeDamage(int damageAmount, Vector2 attackerPos) //데미지 크기, 공격 위치 { // 이미 죽었거나, 무적 상태라면 데미지 무시 if (isDead || isInvincible) return; // 체력 감소 CurrentHp -= damageAmount; Debug.Log($"남은 체력: {CurrentHp}"); // 체력 0 체크 if (CurrentHp <= 0) { Die(); return; } // 넉백 및 무적 코루틴 실행 StartCoroutine(KnockBack(attackerPos)); } IEnumerator KnockBack(Vector2 attackerPos) { isHit = true; isInvincible = true; Vector2 knockbackDir = (transform.position - (Vector3)attackerPos).normalized; rbody.linearVelocity = Vector2.zero; rbody.AddForce(knockbackDir * 2f + Vector2.up * 1f, ForceMode2D.Impulse); if (spriteRenderer != null) spriteRenderer.color = new Color(1, 0, 0, 0.5f); yield return new WaitForSeconds(0.5f); isHit = false; if (spriteRenderer != null) spriteRenderer.color = Color.white; yield return new WaitForSeconds(1f); isInvincible = false; } void Die() { isDead = true; animator.SetTrigger("Die"); rbody.linearVelocity = Vector2.zero; GetComponent().enabled = false; } public void GameStop() { rbody.linearVelocity = Vector2.zero; } public void GameOver() { isDead = true; animator.SetBool("Move", false); //anim.SetTrigger("Die"); GameStop(); } }