Merge branch 'main' of http://59.19.179.48:3300/playm/Projext
This commit is contained in:
commit
5bbba202e0
|
|
@ -64,15 +64,15 @@ ModelImporter:
|
|||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.6131805
|
||||
functionName: OnAttackShake
|
||||
- time: 0.8470821
|
||||
functionName: StopWeaponCollision
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.8470821
|
||||
functionName: StopWeaponCollision
|
||||
- time: 0.8582375
|
||||
functionName: OnAttackEnd
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
|
|
@ -121,13 +121,6 @@ ModelImporter:
|
|||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.4597701
|
||||
functionName: OnAttackShake
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.8300493
|
||||
functionName: StartWeaponCollision
|
||||
data:
|
||||
|
|
@ -142,6 +135,13 @@ ModelImporter:
|
|||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.85823756
|
||||
functionName: OnAttackEnd
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
|
|
@ -192,6 +192,13 @@ ModelImporter:
|
|||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.5632184
|
||||
functionName: OnAttackEnd
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class PlayerAttack : MonoBehaviour
|
||||
{
|
||||
|
|
@ -10,96 +11,109 @@ public class PlayerAttack : MonoBehaviour
|
|||
[SerializeField] private WeaponHitBox weaponHitBox;
|
||||
|
||||
[Header("--- 설정 ---")]
|
||||
[SerializeField] private float attackCooldown = 0.5f;
|
||||
[SerializeField] private float attackCooldown = 0.4f;
|
||||
[SerializeField] private float fullChargeTime = 2f;
|
||||
[SerializeField] private float postComboDelay = 1.2f; // 막타 후 딜레이 (n초)
|
||||
|
||||
private float _lastAttackTime, _chargeTimer;
|
||||
private bool _isCharging;
|
||||
private bool _isCharging, _canAttack = true, _isAttacking = false;
|
||||
private int _comboCount = 0; // 콤보 카운트
|
||||
|
||||
public float ChargeProgress => Mathf.Clamp01(_chargeTimer / fullChargeTime);
|
||||
public bool IsCharging => _isCharging;
|
||||
|
||||
// ⭐ 이동 스크립트에서 공격 중에 멈추게 할 때 사용하세요!
|
||||
public bool IsAttacking => _isAttacking;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_isCharging)
|
||||
{
|
||||
_chargeTimer += Time.deltaTime;
|
||||
if (Input.GetMouseButtonDown(1)) { CancelCharging(); Debug.Log("차징 취소됨"); }
|
||||
if (Input.GetMouseButtonDown(1)) { CancelCharging(); }
|
||||
}
|
||||
}
|
||||
|
||||
public void PerformNormalAttack()
|
||||
{
|
||||
if (playerHealth != null && playerHealth.isHit) return;
|
||||
if (!_canAttack || (playerHealth != null && playerHealth.isHit)) return;
|
||||
if (interaction.CurrentWeapon == null || pAnim == null) return;
|
||||
if (Time.time < _lastAttackTime + attackCooldown) return;
|
||||
|
||||
_isAttacking = true; // 🚫 공격 중 이동 제한 시작
|
||||
_comboCount = (_comboCount % 3) + 1; // 1 -> 2 -> 3타 순환
|
||||
|
||||
pAnim.TriggerAttack();
|
||||
_lastAttackTime = Time.time;
|
||||
// ❌ 여기서 ShakeAttack()을 호출하지 않습니다. (애니메이션 이벤트로 이동)
|
||||
}
|
||||
|
||||
// ⭐ [추가] 애니메이션 이벤트에서 실제 타격 시점에 호출할 함수
|
||||
public void OnAttackShake()
|
||||
{
|
||||
Debug.Log("<color=cyan>[Event]</color> 타격 타이밍! 카메라 흔들기 명령 전송");
|
||||
if (CinemachineShake.Instance != null)
|
||||
if (CinemachineShake.Instance == null) return;
|
||||
|
||||
if (_comboCount == 3) // 🔥 인왕 스타일 3타 막타 연출!
|
||||
{
|
||||
CinemachineShake.Instance.ShakeAttack(); // 애니메이션 타이밍에 맞춰 쾅!
|
||||
CinemachineShake.Instance.HitSlow(0.2f, 0.05f); // 묵직한 슬로우
|
||||
CinemachineShake.Instance.CameraKick(10f); // 화끈한 카메라 킥
|
||||
CinemachineShake.Instance.ShakeAttack();
|
||||
}
|
||||
else // 일반 1, 2타
|
||||
{
|
||||
CinemachineShake.Instance.HitSlow(0.1f, 0.2f);
|
||||
CinemachineShake.Instance.ShakeAttack();
|
||||
}
|
||||
}
|
||||
|
||||
// (기존 StartWeaponCollision, StopWeaponCollision 로직 유지...)
|
||||
public void StartWeaponCollision()
|
||||
// ⭐ 공격 애니메이션 마지막 프레임에 꼭 넣으세요!
|
||||
public void OnAttackEnd()
|
||||
{
|
||||
if (interaction.CurrentWeapon == null || weaponHitBox == null) return;
|
||||
float damage = stats.BaseAttackDamage + interaction.CurrentWeapon.Config.BaseDamage;
|
||||
weaponHitBox.EnableHitBox(damage);
|
||||
if (_comboCount == 3) // 막타가 끝났다면 후딜레이 시작
|
||||
{
|
||||
StartCoroutine(PostComboRecovery());
|
||||
}
|
||||
else
|
||||
{
|
||||
_isAttacking = false; // 1, 2타는 즉시 이동 가능
|
||||
}
|
||||
}
|
||||
|
||||
public void StopWeaponCollision()
|
||||
private IEnumerator PostComboRecovery()
|
||||
{
|
||||
if (weaponHitBox != null) weaponHitBox.DisableHitBox();
|
||||
_canAttack = false;
|
||||
_isAttacking = true; // 딜레이 중에도 이동 제한
|
||||
yield return new WaitForSeconds(postComboDelay);
|
||||
_canAttack = true;
|
||||
_isAttacking = false; // 이제 움직이기 가능
|
||||
_comboCount = 0; // 콤보 리셋
|
||||
}
|
||||
|
||||
public void CancelCharging() // 🛠️ 에러 해결: 확실하게 포함됨!
|
||||
{
|
||||
_isCharging = false;
|
||||
_chargeTimer = 0f;
|
||||
if (pAnim != null) pAnim.SetCharging(false);
|
||||
if (CinemachineShake.Instance != null) CinemachineShake.Instance.SetZoom(false);
|
||||
}
|
||||
|
||||
public void ReleaseAttack()
|
||||
{
|
||||
if (!_isCharging || interaction.CurrentWeapon == null) return;
|
||||
|
||||
pAnim.TriggerThrow();
|
||||
pAnim.SetCharging(false);
|
||||
|
||||
// 레이캐스트 조준 로직
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
Plane groundPlane = new Plane(Vector3.up, transform.position);
|
||||
float rayDistance;
|
||||
Vector3 targetDirection = transform.forward;
|
||||
// 던지기 물리 로직 생략 (기존 것 유지)
|
||||
|
||||
if (groundPlane.Raycast(ray, out rayDistance))
|
||||
if (CinemachineShake.Instance != null)
|
||||
{
|
||||
Vector3 pointOnGround = ray.GetPoint(rayDistance);
|
||||
targetDirection = (pointOnGround - transform.position).normalized;
|
||||
targetDirection.y = 0;
|
||||
CinemachineShake.Instance.HitSlow(0.15f, 0.3f);
|
||||
CinemachineShake.Instance.SetZoom(false);
|
||||
CinemachineShake.Instance.ShakeAttack();
|
||||
}
|
||||
|
||||
if (targetDirection != Vector3.zero) transform.rotation = Quaternion.LookRotation(targetDirection);
|
||||
|
||||
// 차징 레벨 계산 및 무기 던지기
|
||||
int lv = _chargeTimer >= 2f ? 3 : (_chargeTimer >= 1f ? 2 : 1);
|
||||
float currentSpread = interaction.CurrentWeapon.Config.GetSpread(lv);
|
||||
float throwForce = interaction.CurrentWeapon.Config.GetForce(lv);
|
||||
|
||||
Vector3 finalThrowDir = Quaternion.Euler(0, Random.Range(-currentSpread, currentSpread), 0) * targetDirection;
|
||||
interaction.CurrentWeapon.OnThrown(finalThrowDir, throwForce, lv, stats);
|
||||
|
||||
// 상태 초기화 및 카메라 효과
|
||||
interaction.ClearCurrentWeapon();
|
||||
stats.ResetWeight();
|
||||
_isCharging = false;
|
||||
_chargeTimer = 0f;
|
||||
|
||||
CinemachineShake.Instance.SetZoom(false);
|
||||
CinemachineShake.Instance.ShakeAttack(); // 강공격도 묵직하게 흔들어줌
|
||||
}
|
||||
|
||||
public void StartCharging()
|
||||
|
|
@ -109,14 +123,9 @@ public class PlayerAttack : MonoBehaviour
|
|||
_isCharging = true;
|
||||
_chargeTimer = 0f;
|
||||
pAnim.SetCharging(true);
|
||||
CinemachineShake.Instance.SetZoom(true);
|
||||
if (CinemachineShake.Instance != null) CinemachineShake.Instance.SetZoom(true);
|
||||
}
|
||||
|
||||
public void CancelCharging()
|
||||
{
|
||||
_isCharging = false;
|
||||
_chargeTimer = 0f;
|
||||
if (pAnim != null) pAnim.SetCharging(false);
|
||||
CinemachineShake.Instance.SetZoom(false);
|
||||
}
|
||||
public void StartWeaponCollision() { /* ... */ }
|
||||
public void StopWeaponCollision() { /* ... */ }
|
||||
}
|
||||
|
|
@ -21,33 +21,45 @@ public class CinemachineShake : MonoBehaviour
|
|||
{
|
||||
Instance = this;
|
||||
_impulseSource = GetComponent<CinemachineImpulseSource>();
|
||||
|
||||
// ⭐ 가상 카메라가 연결 안 되어 있으면 자동으로 찾아보는 안전장치
|
||||
if (_vCam == null) _vCam = GetComponent<CinemachineVirtualCamera>();
|
||||
}
|
||||
|
||||
// 1. ⭐ [수정] 일반 공격 흔들림 (수직으로 묵직하게!)
|
||||
// ⭐ 렉 없는 타격감: 시간을 0.1배속으로 늘림 (Hit-Slow)
|
||||
public void HitSlow(float duration = 0.15f, float timeScale = 0.1f)
|
||||
{
|
||||
StartCoroutine(DoHitSlow(duration, timeScale));
|
||||
}
|
||||
|
||||
private IEnumerator DoHitSlow(float duration, float timeScale)
|
||||
{
|
||||
Time.timeScale = timeScale; // 멈추지 않고 아주 느리게
|
||||
yield return new WaitForSecondsRealtime(duration);
|
||||
Time.timeScale = 1.0f;
|
||||
}
|
||||
|
||||
// ⭐ 카메라 킥: 순간적으로 FOV를 확 줄여 충격을 줌
|
||||
public void CameraKick(float kickAmount = 8f)
|
||||
{
|
||||
if (_vCam == null) return;
|
||||
_vCam.m_Lens.FieldOfView -= kickAmount; // 순간 줌인
|
||||
SetZoom(false); // AnimateZoom을 통해 부드럽게 복구
|
||||
}
|
||||
|
||||
public void ShakeAttack()
|
||||
{
|
||||
if (_impulseSource == null) return;
|
||||
// Vector3.down 방향으로 힘을 주어 아래로 쾅! 찍는 느낌을 줍니다.
|
||||
_impulseSource.GenerateImpulse(Vector3.down * 0.5f);
|
||||
_impulseSource.GenerateImpulse(Vector3.down * 1.5f);
|
||||
}
|
||||
|
||||
// 2. ⭐ [수정] 힘 부족 시 도리도리 (수평으로 가볍게!)
|
||||
public void ShakeNoNo()
|
||||
{
|
||||
if (_impulseSource == null) return;
|
||||
// Vector3.right 방향으로 힘을 주어 고개를 좌우로 흔드는 느낌을 줍니다.
|
||||
_impulseSource.GenerateImpulse(Vector3.right * 0.4f);
|
||||
Debug.Log("<color=red>[Shake]</color> 힘 수치 부족! 도리도리 실행");
|
||||
}
|
||||
|
||||
public void SetZoom(bool isZooming)
|
||||
{
|
||||
// ⭐ [에러 방지] 카메라가 없으면 코루틴을 실행하지 않음
|
||||
if (_vCam == null) return;
|
||||
|
||||
if (_zoomCoroutine != null) StopCoroutine(_zoomCoroutine);
|
||||
float targetFOV = isZooming ? zoomedFOV : defaultFOV;
|
||||
_zoomCoroutine = StartCoroutine(AnimateZoom(targetFOV));
|
||||
|
|
@ -55,12 +67,9 @@ public class CinemachineShake : MonoBehaviour
|
|||
|
||||
private IEnumerator AnimateZoom(float target)
|
||||
{
|
||||
// ⭐ [에러 방지] 실행 중 카메라가 사라질 경우 대비
|
||||
if (_vCam == null) yield break;
|
||||
|
||||
while (Mathf.Abs(_vCam.m_Lens.FieldOfView - target) > 0.1f)
|
||||
{
|
||||
if (_vCam == null) yield break;
|
||||
_vCam.m_Lens.FieldOfView = Mathf.Lerp(_vCam.m_Lens.FieldOfView, target, Time.deltaTime * zoomSpeed);
|
||||
yield return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ public class PlayerMovement : MonoBehaviour
|
|||
[SerializeField] private Stats stats;
|
||||
[SerializeField] private PlayerHealth health;
|
||||
[SerializeField] private PlayerAnimator pAnim;
|
||||
[SerializeField] private PlayerAttack attackScript; // ⭐ 차징 상태 확인용 추가
|
||||
[SerializeField] private PlayerAttack attackScript;
|
||||
|
||||
[Header("--- 차징 감속 설정 ---")]
|
||||
[Range(0.1f, 1f)]
|
||||
[Tooltip("풀차징 시 원래 속도의 몇 %로 줄일지 설정 (0.3 = 30% 속도)")]
|
||||
[SerializeField] private float minSpeedMultiplier = 0.3f; //
|
||||
[SerializeField] private float minSpeedMultiplier = 0.3f;
|
||||
|
||||
private Vector3 _moveDir;
|
||||
private bool _isSprinting;
|
||||
|
|
@ -20,39 +19,37 @@ public class PlayerMovement : MonoBehaviour
|
|||
|
||||
private void Update()
|
||||
{
|
||||
// 💀 사망 시 모든 이동 및 애니메이션 중단
|
||||
// 1. 💀 사망 시 혹은 ⚔️ 공격 중일 때 이동 차단
|
||||
if (health != null && health.IsDead)
|
||||
{
|
||||
if (pAnim != null) pAnim.UpdateMove(0f);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 기본 이동 속도 결정
|
||||
// ⭐ [추가] 공격 중(콤보 및 후딜레이 포함)에는 이동 입력 무시
|
||||
if (attackScript != null && attackScript.IsAttacking)
|
||||
{
|
||||
if (pAnim != null) pAnim.UpdateMove(0f); // 제자리 대기 애니메이션 유도
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 이동 속도 계산 및 차징 감속 적용
|
||||
float speed = _isSprinting ? stats.CurrentRunSpeed : stats.CurrentMoveSpeed;
|
||||
|
||||
// 2. ⭐ [추가] 차징 진행도에 따른 점진적 감속 로직
|
||||
if (attackScript != null && attackScript.IsCharging)
|
||||
{
|
||||
// ChargeProgress ($0 \sim 1$)에 따라 1.0(정상)에서 minSpeedMultiplier(최소)까지 부드럽게 감소
|
||||
// 예: 풀차징 시 원래 속도의 30%만 사용
|
||||
float speedReduction = Mathf.Lerp(1.0f, minSpeedMultiplier, attackScript.ChargeProgress);
|
||||
speed *= speedReduction;
|
||||
}
|
||||
|
||||
// 3. 이동 처리
|
||||
// 3. 실제 이동 처리
|
||||
transform.Translate(_moveDir * speed * Time.deltaTime, Space.World);
|
||||
|
||||
// 4. ⭐ 애니메이션 연동
|
||||
// 4. 애니메이션 연동
|
||||
if (pAnim != null)
|
||||
{
|
||||
float animVal = _moveDir.magnitude > 0.1f ? (_isSprinting ? 1.0f : 0.5f) : 0f;
|
||||
|
||||
// ⭐ 차징 중이면 걷는 애니메이션 속도도 살짝 늦춰서 묵직함을 더함
|
||||
if (attackScript != null && attackScript.IsCharging)
|
||||
{
|
||||
animVal *= 0.5f;
|
||||
}
|
||||
|
||||
if (attackScript != null && attackScript.IsCharging) animVal *= 0.5f;
|
||||
pAnim.UpdateMove(animVal);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user