2026-02-12 15:23:25 +00:00
|
|
|
|
using UnityEngine; // 유니티 기본 기능을 쓰기 위해 불러올거에요 -> UnityEngine를
|
|
|
|
|
|
|
|
|
|
|
|
public class EquippableItem : MonoBehaviour // 클래스를 선언할거에요 -> 장착/드랍/투척 가능한 아이템을 처리하는 EquippableItem을
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> EquippableItem 범위를
|
|
|
|
|
|
|
|
|
|
|
|
[SerializeField] private WeaponConfig config; // 변수를 선언할거에요 -> 이 아이템이 참조할 무기 설정(WeaponConfig)을 config에
|
|
|
|
|
|
public WeaponConfig Config => config; // 프로퍼티를 선언할거에요 -> 외부에서 config를 읽을 수 있게 Config로 노출
|
|
|
|
|
|
|
|
|
|
|
|
[Header("--- 데미지 밸런스 ---")] // 인스펙터에 제목을 표시할거에요 -> 데미지 밸런스 섹션을
|
|
|
|
|
|
[SerializeField] private float lv1Mult = 1.0f; // 변수를 선언할거에요 -> 차지 1단계 배율을 lv1Mult에
|
|
|
|
|
|
[SerializeField] private float lv2Mult = 1.5f; // 변수를 선언할거에요 -> 차지 2단계 배율을 lv2Mult에
|
|
|
|
|
|
[SerializeField] private float lv3Mult = 2.5f; // 변수를 선언할거에요 -> 차지 3단계 배율을 lv3Mult에
|
|
|
|
|
|
// [제거] strengthBonusFactor 변수 삭제 // 설명을 적을거에요 -> 힘 보너스 배율은 더 이상 사용하지 않음
|
|
|
|
|
|
|
|
|
|
|
|
private Rigidbody _rb; // 변수를 선언할거에요 -> 리지드바디를 저장할 _rb를
|
|
|
|
|
|
private Collider _col; // 변수를 선언할거에요 -> 콜라이더를 저장할 _col을
|
|
|
|
|
|
private bool _isThrown; // 변수를 선언할거에요 -> 현재 투척 상태인지 저장할 _isThrown을
|
|
|
|
|
|
private int _chargeLevel; // 변수를 선언할거에요 -> 투척 당시 차지 레벨을 저장할 _chargeLevel을
|
|
|
|
|
|
private Stats _thrower; // 변수를 선언할거에요 -> 투척한 주체(플레이어 스탯)를 저장할 _thrower를
|
|
|
|
|
|
private Vector3 _originalWorldScale; // 변수를 선언할거에요 -> 원래 월드 스케일을 저장할 _originalWorldScale을
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake() // 함수를 선언할거에요 -> 오브젝트가 켜질 때 1번 실행되는 Awake를
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> Awake 범위를
|
|
|
|
|
|
_rb = GetComponent<Rigidbody>(); // 컴포넌트를 가져올거에요 -> Rigidbody를 찾아 _rb에 저장
|
|
|
|
|
|
_col = GetComponent<Collider>(); // 컴포넌트를 가져올거에요 -> Collider를 찾아 _col에 저장
|
|
|
|
|
|
_originalWorldScale = transform.lossyScale; // 값을 저장할거에요 -> 현재 월드 기준 크기를 원본으로 기억
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> Awake를
|
|
|
|
|
|
|
|
|
|
|
|
public void OnPickedUp(Transform hand) // 함수를 선언할거에요 -> 아이템을 손에 집었을 때 처리하는 OnPickedUp을
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> OnPickedUp 범위를
|
|
|
|
|
|
_isThrown = false; // 상태를 바꿀거에요 -> 투척 상태를 해제(false)로
|
|
|
|
|
|
transform.SetParent(hand); // 부모를 바꿀거에요 -> 손(Hand) 트랜스폼에 붙이기
|
|
|
|
|
|
|
|
|
|
|
|
transform.localScale = new Vector3( // 값을 설정할거에요 -> 손의 스케일 변화에도 월드 크기 유지되게 로컬 스케일 계산
|
|
|
|
|
|
_originalWorldScale.x / hand.lossyScale.x, // x축 크기를 보정할거에요 -> 원본 월드 스케일 기준으로
|
|
|
|
|
|
_originalWorldScale.y / hand.lossyScale.y, // y축 크기를 보정할거에요 -> 원본 월드 스케일 기준으로
|
|
|
|
|
|
_originalWorldScale.z / hand.lossyScale.z // z축 크기를 보정할거에요 -> 원본 월드 스케일 기준으로
|
|
|
|
|
|
); // 로컬 스케일 설정을 끝낼거에요 -> 월드 크기 유지
|
|
|
|
|
|
|
|
|
|
|
|
transform.localPosition = Vector3.zero; // 위치를 맞출거에요 -> 손 기준 로컬 위치 0으로
|
|
|
|
|
|
transform.localRotation = Quaternion.identity; // 회전을 맞출거에요 -> 손 기준 로컬 회전 초기화
|
|
|
|
|
|
if (_rb) _rb.isKinematic = true; // 조건이 맞으면 실행할거에요 -> 리지드바디가 있으면 물리 비활성(키네마틱)으로
|
|
|
|
|
|
if (_col) _col.enabled = false; // 조건이 맞으면 실행할거에요 -> 콜라이더가 있으면 꺼서 손에서 충돌 안 나게
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> OnPickedUp을
|
|
|
|
|
|
|
|
|
|
|
|
public void OnDropped(Vector3 throwDir) // 함수를 선언할거에요 -> 아이템을 떨어뜨릴 때 처리하는 OnDropped를
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> OnDropped 범위를
|
|
|
|
|
|
_isThrown = false; // 상태를 바꿀거에요 -> 투척 상태가 아님(false)으로
|
|
|
|
|
|
transform.SetParent(null); // 부모를 해제할거에요 -> 월드에 놓기
|
|
|
|
|
|
transform.localScale = _originalWorldScale; // 스케일을 되돌릴거에요 -> 원래 월드 스케일로
|
|
|
|
|
|
|
|
|
|
|
|
if (_rb) // 조건을 검사할거에요 -> 리지드바디가 있는지
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> 물리 드랍 처리
|
|
|
|
|
|
_rb.isKinematic = false; // 값을 바꿀거에요 -> 물리 활성화
|
|
|
|
|
|
Vector3 force = (throwDir + Vector3.up * 0.5f).normalized * 5f; // 힘을 계산할거에요 -> 던지는 방향 + 살짝 위로 + 세기 5
|
|
|
|
|
|
_rb.AddForce(force, ForceMode.Impulse); // 힘을 줄거에요 -> 순간 힘(Impulse)으로 튕기듯 드랍
|
|
|
|
|
|
_rb.AddTorque(Random.insideUnitSphere * 3f, ForceMode.Impulse); // 회전도 줄거에요 -> 랜덤 토크로 자연스럽게 굴러가게
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> 물리 드랍 처리
|
|
|
|
|
|
|
|
|
|
|
|
if (_col) _col.enabled = true; // 조건이 맞으면 실행할거에요 -> 콜라이더를 다시 켜기
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> OnDropped를
|
|
|
|
|
|
|
|
|
|
|
|
public void OnThrown(Vector3 dir, float force, int lv, Stats s) // 함수를 선언할거에요 -> 투척 시작 세팅을 하는 OnThrown을
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> OnThrown 범위를
|
|
|
|
|
|
_isThrown = true; // 상태를 바꿀거에요 -> 투척 상태(true)로
|
|
|
|
|
|
_chargeLevel = lv; // 값을 저장할거에요 -> 투척 당시 차지 레벨을
|
|
|
|
|
|
_thrower = s; // 값을 저장할거에요 -> 던진 주체(스탯)를 저장
|
|
|
|
|
|
transform.SetParent(null); // 부모를 해제할거에요 -> 월드로 분리
|
|
|
|
|
|
transform.localScale = _originalWorldScale; // 스케일을 되돌릴거에요 -> 원래 월드 스케일로
|
|
|
|
|
|
|
|
|
|
|
|
if (_rb) // 조건을 검사할거에요 -> 리지드바디가 있는지
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> 물리 투척 처리
|
|
|
|
|
|
_rb.isKinematic = false; // 값을 바꿀거에요 -> 물리 활성화
|
|
|
|
|
|
_rb.AddForce(dir * force, ForceMode.Impulse); // 힘을 줄거에요 -> 던지는 방향 * force로 순간 가속
|
|
|
|
|
|
_rb.AddTorque(transform.right * 10f, ForceMode.Impulse); // 회전을 줄거에요 -> 오른쪽 축으로 스핀 주기
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> 물리 투척 처리
|
|
|
|
|
|
|
|
|
|
|
|
if (_col) _col.enabled = true; // 조건이 맞으면 실행할거에요 -> 콜라이더를 켜서 충돌 가능하게
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> OnThrown를
|
|
|
|
|
|
|
|
|
|
|
|
private void OnCollisionEnter(Collision collision) // 함수를 선언할거에요 -> 충돌이 일어나면 호출되는 OnCollisionEnter를
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> OnCollisionEnter 범위를
|
|
|
|
|
|
if (!_isThrown) return; // 조건이 맞으면 종료할거에요 -> 투척 상태가 아니면 무시
|
|
|
|
|
|
if (_thrower != null && collision.gameObject == _thrower.gameObject) return; // 조건이 맞으면 종료할거에요 -> 던진 본인에게는 맞지 않게
|
|
|
|
|
|
|
|
|
|
|
|
if (collision.gameObject.TryGetComponent<IDamageable>(out var target)) // 조건을 검사할거에요 -> 맞은 대상이 데미지를 받을 수 있는지
|
|
|
|
|
|
{ // 코드 블록을 시작할거에요 -> 데미지 처리
|
|
|
|
|
|
float mult = _chargeLevel == 3 ? lv3Mult : (_chargeLevel == 2 ? lv2Mult : lv1Mult); // 배율을 고를거에요 -> 차지 레벨에 따라 lv1/2/3 배율
|
|
|
|
|
|
|
|
|
|
|
|
// ✨ [수정] 힘 보너스 로직 제거. (플레이어 기본 공격력 + 무기 대미지) * 차지 배율 // 설명을 적을거에요 -> 최종 데미지 계산 공식
|
|
|
|
|
|
float finalDamage = (_thrower.BaseAttackDamage + config.BaseDamage) * mult; // 값을 계산할거에요 -> (플레이어 공격력 + 무기 기본 데미지) * 배율
|
|
|
|
|
|
|
|
|
|
|
|
target.TakeDamage(finalDamage); // 함수를 실행할거에요 -> 대상에게 finalDamage만큼 데미지 주기
|
|
|
|
|
|
Debug.Log($"<color=orange>[투척 적중]</color> {collision.gameObject.name}에게 {finalDamage:F1} 데미지!"); // 로그를 찍을거에요 -> 적중 결과 출력
|
|
|
|
|
|
_isThrown = false; // 상태를 바꿀거에요 -> 한 번 맞으면 투척 상태 해제
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> 데미지 처리
|
|
|
|
|
|
|
|
|
|
|
|
if (collision.gameObject.layer != LayerMask.NameToLayer("Player")) _isThrown = false; // 조건이 맞으면 실행할거에요 -> 플레이어 레이어가 아니면 투척 상태 해제
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> OnCollisionEnter를
|
|
|
|
|
|
|
|
|
|
|
|
} // 코드 블록을 끝낼거에요 -> EquippableItem을
|