Projext/Assets/5.TestScript/Attack.cs

122 lines
4.2 KiB
C#
Raw Normal View History

2026-01-29 06:58:38 +00:00
using UnityEngine;
public class PlayerAttack : MonoBehaviour
{
[Header("--- 참조 ---")]
[SerializeField] private PlayerInteraction interaction;
[SerializeField] private Stats stats;
[SerializeField] private PlayerAnimator pAnim;
[SerializeField] private PlayerHealth playerHealth;
[SerializeField] private WeaponHitBox weaponHitBox;
[Header("--- 설정 ---")]
2026-01-29 06:58:38 +00:00
[SerializeField] private float attackCooldown = 0.5f;
2026-01-30 06:30:27 +00:00
[SerializeField] private float fullChargeTime = 2f;
2026-01-29 06:58:38 +00:00
private float _lastAttackTime, _chargeTimer;
private bool _isCharging;
public float ChargeProgress => Mathf.Clamp01(_chargeTimer / fullChargeTime);
public bool IsCharging => _isCharging;
private void Update()
{
if (_isCharging)
{
_chargeTimer += Time.deltaTime;
2026-01-30 06:30:27 +00:00
if (Input.GetMouseButtonDown(1)) { CancelCharging(); Debug.Log("차징 취소됨"); }
2026-01-29 06:58:38 +00:00
}
}
public void PerformNormalAttack()
{
if (playerHealth != null && playerHealth.isHit) return;
if (interaction.CurrentWeapon == null || pAnim == null) return;
if (Time.time < _lastAttackTime + attackCooldown) return;
pAnim.TriggerAttack();
_lastAttackTime = Time.time;
2026-01-30 06:30:27 +00:00
// ❌ 여기서 ShakeAttack()을 호출하지 않습니다. (애니메이션 이벤트로 이동)
2026-01-29 06:58:38 +00:00
}
2026-01-30 06:30:27 +00:00
// ⭐ [추가] 애니메이션 이벤트에서 실제 타격 시점에 호출할 함수
public void OnAttackShake()
{
Debug.Log("<color=cyan>[Event]</color> 타격 타이밍! 카메라 흔들기 명령 전송");
if (CinemachineShake.Instance != null)
{
CinemachineShake.Instance.ShakeAttack(); // 애니메이션 타이밍에 맞춰 쾅!
}
}
// (기존 StartWeaponCollision, StopWeaponCollision 로직 유지...)
2026-01-29 06:58:38 +00:00
public void StartWeaponCollision()
{
if (interaction.CurrentWeapon == null || weaponHitBox == null) return;
float damage = stats.BaseAttackDamage + interaction.CurrentWeapon.Config.BaseDamage;
weaponHitBox.EnableHitBox(damage);
}
public void StopWeaponCollision()
{
if (weaponHitBox != null) weaponHitBox.DisableHitBox();
}
public void ReleaseAttack()
{
if (!_isCharging || interaction.CurrentWeapon == null) return;
pAnim.TriggerThrow();
pAnim.SetCharging(false);
2026-01-30 06:30:27 +00:00
// 레이캐스트 조준 로직
2026-01-29 06:58:38 +00:00
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, transform.position);
2026-01-29 06:58:38 +00:00
float rayDistance;
Vector3 targetDirection = transform.forward;
2026-01-29 06:58:38 +00:00
if (groundPlane.Raycast(ray, out rayDistance))
{
Vector3 pointOnGround = ray.GetPoint(rayDistance);
2026-01-29 06:58:38 +00:00
targetDirection = (pointOnGround - transform.position).normalized;
targetDirection.y = 0;
2026-01-29 06:58:38 +00:00
}
if (targetDirection != Vector3.zero) transform.rotation = Quaternion.LookRotation(targetDirection);
2026-01-30 06:30:27 +00:00
// 차징 레벨 계산 및 무기 던지기
2026-01-29 06:58:38 +00:00
int lv = _chargeTimer >= 2f ? 3 : (_chargeTimer >= 1f ? 2 : 1);
float currentSpread = interaction.CurrentWeapon.Config.GetSpread(lv);
float throwForce = interaction.CurrentWeapon.Config.GetForce(lv);
2026-01-29 06:58:38 +00:00
Vector3 finalThrowDir = Quaternion.Euler(0, Random.Range(-currentSpread, currentSpread), 0) * targetDirection;
interaction.CurrentWeapon.OnThrown(finalThrowDir, throwForce, lv, stats);
2026-01-29 06:58:38 +00:00
2026-01-30 06:30:27 +00:00
// 상태 초기화 및 카메라 효과
2026-01-29 06:58:38 +00:00
interaction.ClearCurrentWeapon();
stats.ResetWeight();
_isCharging = false;
_chargeTimer = 0f;
2026-01-30 06:30:27 +00:00
CinemachineShake.Instance.SetZoom(false);
CinemachineShake.Instance.ShakeAttack(); // 강공격도 묵직하게 흔들어줌
2026-01-29 06:58:38 +00:00
}
public void StartCharging()
{
if (playerHealth != null && playerHealth.isHit) return;
if (interaction.CurrentWeapon == null) return;
_isCharging = true;
_chargeTimer = 0f;
pAnim.SetCharging(true);
2026-01-30 06:30:27 +00:00
CinemachineShake.Instance.SetZoom(true);
2026-01-29 06:58:38 +00:00
}
public void CancelCharging()
{
_isCharging = false;
_chargeTimer = 0f;
if (pAnim != null) pAnim.SetCharging(false);
2026-01-30 06:30:27 +00:00
CinemachineShake.Instance.SetZoom(false);
2026-01-29 06:58:38 +00:00
}
}