study/first_study/Assets/Scripts/PlayerSc/PlayerController.cs
jh04010421 e08e5b3c7c 윤지호 | LostBits 기능 구현
20226.01.29 수정 (공격, 피격, 아이템 드랍 및 획득 구현 완료, 히트박스 트리거 버그 수정완)
다음 작업 : 공중몬스터 구현, 태그 스킬 구현
2026-02-02 21:41:06 +09:00

298 lines
8.2 KiB
C#

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<Rigidbody2D>();
//Animator 가져오기
//animator = GetComponent<Animator>();
nanimator = nano.GetComponent<Animator>();
tanimator = tera.GetComponent<Animator>();
playerAttacks = GetComponent<PlayerAttacks>();
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<Vector2>();
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<Collider2D>().enabled = false;
}
public void GameStop()
{
rbody.linearVelocity = Vector2.zero;
}
public void GameOver()
{
isDead = true;
animator.SetBool("Move", false);
//anim.SetTrigger("Die");
GameStop();
}
}