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("Nano Datas")] [SerializeField] private PlayerData nanoData; [Header("Tera Datas")] [SerializeField] private PlayerData teraData; // 런타임에서 계산된 스탯을 담아둘 리스트 private PlayerStat nanoStat; private PlayerStat teraStat; private PlayerStat currentStat; [SerializeField] private Rigidbody2D rbody; private Vector2 moveInput; /*[SerializeField] private float speed = 3.0f; // 이동 속도 [SerializeField] private float dashspeed = 5.4f; [SerializeField] private float jumpForce = 5.0f; // 점프력*/ 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; //private GameObject nano; //private GameObject tera; [SerializeField] private GameObject nano; [SerializeField] private GameObject tera; bool isnano = false; bool istera = false; int nanoCurrentHp; int teraCurrentHp; void Start() { if (nanoData != null) nanoStat = new PlayerStat(nanoData); if (teraData != null) teraStat = new PlayerStat(teraData); nano.SetActive(true); isnano = true; tera.SetActive(false); currentStat = nanoStat; //Rigidbody2D 가져오기 rbody = GetComponent(); //Animator 가져오기 //animator = GetComponent(); nanimator = nano.GetComponent(); tanimator = tera.GetComponent(); playerAttacks = GetComponent(); nanoCurrentHp = nanoStat.data.playerHp; teraCurrentHp = teraStat.data.playerHp; } public void OnTagKey(InputValue value) { if (!value.isPressed) return; Debug.Log(" Z 버튼 눌림! "); if (isnano) { tera.SetActive(true); nano.SetActive(false); isnano = false; istera = true; } else if (istera) { tera.SetActive(false); nano.SetActive(true); isnano = true; istera = false; } currentStat = (isnano) ? nanoStat : teraStat; animator = (isnano) ? nanimator : tanimator; } void OnMove(InputValue value) { // Vector2 값 중 x축(좌우) 값만 가져옴 Vector2 inputVector = value.Get(); axisH = inputVector.x; } void OnDash(InputValue value) { isDash = value.isPressed; if (isDash) Debug.Log("대시 중..."); else Debug.Log("대시 중단"); } public void OnJump(InputValue value) { // 버튼이 눌린 순간(isPressed)이고 지면 위라면 점프 예약 if (value.isPressed && onGround) { goJump = true; nanimator.SetBool("jump", true); tanimator.SetBool("jump", true); Debug.Log(" 점프 버튼 눌림! "); } } public void OnSAtk(InputValue value) { if (!value.isPressed) return; Debug.Log(" s 버튼 눌림! "); if (playerAttacks.IsAnyWeaponInUse) return; playerAttacks.IsAnyWeaponInUse = true; //playerAttacks.weaponInfos[0].isUse = true; StartCoroutine(playerAttacks.ableAtk(0, "SAtk", isnano)); } public void OnAAtk(InputValue value) { if (!value.isPressed) return; Debug.Log(" a 버튼 눌림! "); if (playerAttacks.IsAnyWeaponInUse) return; playerAttacks.IsAnyWeaponInUse = true; //playerAttacks.weaponInfos[1].isUse = 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; // 체력 감소 nanoCurrentHp -= damageAmount; teraCurrentHp -= damageAmount; // 현재 캐릭터 체력만 깎거나 둘 다 깎거나 정책에 따라 수정 Debug.Log($"남은 체력: {nanoCurrentHp}"); // 체력 0 체크 if (nanoCurrentHp <= 0 || teraCurrentHp <= 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; //anim.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(); } }