test
This commit is contained in:
parent
10ac5ab730
commit
9d2873644b
Binary file not shown.
|
|
@ -1,17 +0,0 @@
|
||||||
Target: mount:56e62dd7-241f-41e9-8c6b-dd4ca4513e62#My project/My project@14569616159046@cloud merged from: Merge 9
|
|
||||||
Directory conflict: EvilTwin 22550 -11
|
|
||||||
Directory conflict: EvilTwin 22551 -12
|
|
||||||
Directory conflict: EvilTwin 22566 -27
|
|
||||||
Directory conflict: EvilTwin 22567 -28
|
|
||||||
Directory conflict: EvilTwin 22554 -33
|
|
||||||
Directory conflict: EvilTwin 22555 -34
|
|
||||||
Directory conflict: EvilTwin 22556 -17
|
|
||||||
Directory conflict: EvilTwin 22558 -18
|
|
||||||
Directory conflict: EvilTwin 22574 -31
|
|
||||||
Directory conflict: EvilTwin 22575 -32
|
|
||||||
Directory conflict: EvilTwin 22576 -29
|
|
||||||
Directory conflict: EvilTwin 22577 -30
|
|
||||||
Directory conflict: EvilTwin 22578 -13
|
|
||||||
Directory conflict: EvilTwin 22579 -14
|
|
||||||
Directory conflict: EvilTwin 22580 -25
|
|
||||||
Directory conflict: EvilTwin 22581 -26
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,4 @@
|
||||||
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
||||||
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
||||||
|
|
||||||
public class ChargeMonster : MonsterClass // 클래스를 선언할거에요 -> 돌진 몬스터를
|
public class ChargeMonster : MonsterClass // 클래스를 선언할거에요 -> 돌진 몬스터를
|
||||||
|
|
@ -15,9 +15,6 @@ public class ChargeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
[SerializeField] private string prepareAnim = "Run-wait"; // 변수를 선언할거에요 -> 준비 State 이름을
|
[SerializeField] private string prepareAnim = "Run-wait"; // 변수를 선언할거에요 -> 준비 State 이름을
|
||||||
[SerializeField] private string walkAnim = "Run-walk"; // 변수를 선언할거에요 -> 걷기 State 이름을
|
[SerializeField] private string walkAnim = "Run-walk"; // 변수를 선언할거에요 -> 걷기 State 이름을
|
||||||
|
|
||||||
[Header("=== 디버그 ===")] // 인스펙터 제목을 달거에요 -> 디버그 설정을
|
|
||||||
[SerializeField] private bool showChargeDebugLog = true; // 변수를 선언할거에요 -> 디버그 로그 on/off를
|
|
||||||
|
|
||||||
private float lastChargeTime; // 변수를 선언할거에요 -> 마지막 돌진 시간을
|
private float lastChargeTime; // 변수를 선언할거에요 -> 마지막 돌진 시간을
|
||||||
private bool isCharging; // 변수를 선언할거에요 -> 돌진 중 여부를
|
private bool isCharging; // 변수를 선언할거에요 -> 돌진 중 여부를
|
||||||
private bool isPreparing; // 변수를 선언할거에요 -> 돌진 준비 중 여부를
|
private bool isPreparing; // 변수를 선언할거에요 -> 돌진 준비 중 여부를
|
||||||
|
|
@ -134,6 +131,9 @@ public class ChargeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
|
|
||||||
private Coroutine _chargeCoroutine; // 변수를 선언할거에요 -> 돌진 코루틴 핸들을
|
private Coroutine _chargeCoroutine; // 변수를 선언할거에요 -> 돌진 코루틴 핸들을
|
||||||
|
|
||||||
|
[Header("=== 디버그 ===")] // 인스펙터 제목을 달거에요 -> 디버그 설정을
|
||||||
|
[SerializeField] private bool showChargeDebugLog = true; // 변수를 선언할거에요 -> 디버그 로그 on/off를
|
||||||
|
|
||||||
private void StopChargingRoutine() // 함수를 선언할거에요 -> 돌진 코루틴만 종료를
|
private void StopChargingRoutine() // 함수를 선언할거에요 -> 돌진 코루틴만 종료를
|
||||||
{
|
{
|
||||||
// ⭐ StopAllCoroutines() 사용 안 함
|
// ⭐ StopAllCoroutines() 사용 안 함
|
||||||
|
|
@ -259,7 +259,7 @@ public class ChargeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
|
|
||||||
IDamageable t = col.gameObject.GetComponent<IDamageable>(); // 가져올거에요 -> 데미지 인터페이스를
|
IDamageable t = col.gameObject.GetComponent<IDamageable>(); // 가져올거에요 -> 데미지 인터페이스를
|
||||||
if (t != null) t.TakeDamage(attackDamage); // 입힐거에요 -> 데미지를
|
if (t != null) t.TakeDamage(attackDamage); // 입힐거에요 -> 데미지를
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
// 디버그 기즈모
|
// 디버그 기즈모
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
||||||
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
||||||
|
|
||||||
public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 -> 자폭 몬스터를
|
public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 -> 자폭 몬스터를
|
||||||
|
|
@ -23,6 +23,22 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
[SerializeField] private bool showExplodeDebugLog = true; // 변수를 선언할거에요 -> 디버그 로그 on/off를
|
[SerializeField] private bool showExplodeDebugLog = true; // 변수를 선언할거에요 -> 디버그 로그 on/off를
|
||||||
|
|
||||||
private bool hasExploded = false; // 변수를 선언할거에요 -> 폭발 완료 여부를
|
private bool hasExploded = false; // 변수를 선언할거에요 -> 폭발 완료 여부를
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────
|
||||||
|
// AI 로직
|
||||||
|
// ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
protected override void ExecuteAILogic() // 함수를 실행할거에요 -> AI 로직을
|
||||||
|
{
|
||||||
|
if (isAttacking || hasExploded) return; // 중단할거에요 -> 자폭 진행 중이면
|
||||||
|
|
||||||
|
float dist = Vector3.Distance(transform.position, playerTransform.position); // 계산할거에요 -> 플레이어와의 거리를
|
||||||
|
|
||||||
|
if (dist <= triggerRange) // 조건이 맞으면 실행할거에요 -> 자폭 감지 거리 안이면
|
||||||
|
StartCoroutine(ExplodeRoutine()); // 실행할거에요 -> 자폭 코루틴을
|
||||||
|
else // 조건이 틀리면 실행할거에요 -> 멀면
|
||||||
|
ChasePlayer(); // 실행할거에요 -> 추격을
|
||||||
|
}
|
||||||
private string _lastLoggedState = ""; // 변수를 선언할거에요 -> 직전 로그 State 이름을
|
private string _lastLoggedState = ""; // 변수를 선언할거에요 -> 직전 로그 State 이름을
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
|
|
@ -99,23 +115,6 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
|
||||||
// AI 로직
|
|
||||||
// ─────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
protected override void ExecuteAILogic() // 함수를 실행할거에요 -> AI 로직을
|
|
||||||
{
|
|
||||||
if (isAttacking || hasExploded) return; // 중단할거에요 -> 자폭 진행 중이면
|
|
||||||
|
|
||||||
float dist = Vector3.Distance(transform.position, playerTransform.position); // 계산할거에요 -> 플레이어와의 거리를
|
|
||||||
|
|
||||||
if (dist <= triggerRange) // 조건이 맞으면 실행할거에요 -> 자폭 감지 거리 안이면
|
|
||||||
StartCoroutine(ExplodeRoutine()); // 실행할거에요 -> 자폭 코루틴을
|
|
||||||
else // 조건이 틀리면 실행할거에요 -> 멀면
|
|
||||||
ChasePlayer(); // 실행할거에요 -> 추격을
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChasePlayer() // 함수를 선언할거에요 -> 추격 로직을
|
|
||||||
{
|
{
|
||||||
if (agent != null && agent.isOnNavMesh) // 조건이 맞으면 실행할거에요 -> 에이전트가 정상이면
|
if (agent != null && agent.isOnNavMesh) // 조건이 맞으면 실행할거에요 -> 에이전트가 정상이면
|
||||||
{
|
{
|
||||||
|
|
@ -127,7 +126,7 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
|
|
||||||
if (!animator.GetCurrentAnimatorStateInfo(0).IsName(runAnim)) // 조건이 맞으면 실행할거에요 -> 달리기 State가 아니면
|
if (!animator.GetCurrentAnimatorStateInfo(0).IsName(runAnim)) // 조건이 맞으면 실행할거에요 -> 달리기 State가 아니면
|
||||||
animator.Play(runAnim, 0, 0f); // 재생할거에요 -> 달리기 애니를
|
animator.Play(runAnim, 0, 0f); // 재생할거에요 -> 달리기 애니를
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
// 자폭 코루틴
|
// 자폭 코루틴
|
||||||
|
|
|
||||||
|
|
@ -65,12 +65,6 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
|
|
||||||
protected virtual void Awake() // 함수를 실행할거에요 -> 컴포넌트 캐싱을
|
protected virtual void Awake() // 함수를 실행할거에요 -> 컴포넌트 캐싱을
|
||||||
{
|
{
|
||||||
mobRenderer = GetComponentInChildren<Renderer>(); // 가져올거에요 -> 렌더러를
|
|
||||||
animator = GetComponent<Animator>(); // 가져올거에요 -> 애니메이터를
|
|
||||||
agent = GetComponent<NavMeshAgent>(); // 가져올거에요 -> 에이전트를
|
|
||||||
audioSource = GetComponent<AudioSource>(); // 가져올거에요 -> 오디오 소스를
|
|
||||||
if (agent != null) agent.speed = moveSpeed; // 설정할거에요 -> 이동 속도를
|
|
||||||
statusProcessor = new StatusEffectProcessor(this, this, agent, animator); // 생성할거에요 -> 상태이상 처리기를
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnEnable() // 함수를 실행할거에요 -> 활성화/스폰될 때마다
|
protected virtual void OnEnable() // 함수를 실행할거에요 -> 활성화/스폰될 때마다
|
||||||
|
|
@ -81,13 +75,15 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
if (MobUpdateManager.Instance != null) MobUpdateManager.Instance.RegisterMob(this); // 등록할거에요 -> 업데이트 매니저에
|
if (MobUpdateManager.Instance != null) MobUpdateManager.Instance.RegisterMob(this); // 등록할거에요 -> 업데이트 매니저에
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Init() { } // 가상 함수를 선언할거에요 -> 자식 클래스 전용 추가 초기화를
|
||||||
|
|
||||||
|
protected virtual void Init() { } // 비워둘거에요 -> MobUpdateManager가 OnManagedUpdate를 담당하니까
|
||||||
|
|
||||||
protected virtual void OnDisable() // 함수를 실행할거에요 -> 비활성화 시
|
protected virtual void OnDisable() // 함수를 실행할거에요 -> 비활성화 시
|
||||||
{
|
{
|
||||||
if (MobUpdateManager.Instance != null) MobUpdateManager.Instance.UnregisterMob(this); // 해제할거에요 -> 매니저에서
|
if (MobUpdateManager.Instance != null) MobUpdateManager.Instance.UnregisterMob(this); // 해제할거에요 -> 매니저에서
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Update() { } // 비워둘거에요 -> MobUpdateManager가 OnManagedUpdate를 담당하니까
|
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
// 리셋
|
// 리셋
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
|
|
@ -117,6 +113,8 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
OnResetStats(); // 실행할거에요 -> 자식 클래스 추가 리셋을
|
OnResetStats(); // 실행할거에요 -> 자식 클래스 추가 리셋을
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Update() => OnManagedUpdate(); // 실행할거에요 -> 관리형 업데이트를
|
||||||
|
|
||||||
public virtual void Reactivate() // 함수를 선언할거에요 -> 재활성화 추가 처리를
|
public virtual void Reactivate() // 함수를 선언할거에요 -> 재활성화 추가 처리를
|
||||||
{
|
{
|
||||||
if (agent != null && agent.isOnNavMesh)
|
if (agent != null && agent.isOnNavMesh)
|
||||||
|
|
@ -124,11 +122,8 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
agent.isStopped = false; // 재개할거에요 -> 이동을
|
agent.isStopped = false; // 재개할거에요 -> 이동을
|
||||||
if (IsAggroed && playerTransform != null)
|
if (IsAggroed && playerTransform != null)
|
||||||
agent.SetDestination(playerTransform.position); // 이동할거에요 -> 플레이어에게
|
agent.SetDestination(playerTransform.position); // 이동할거에요 -> 플레이어에게
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mobRenderer != null) mobRenderer.enabled = true; // 켤거에요 -> 렌더러를
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Init() { } // 가상 함수를 선언할거에요 -> 자식 클래스 전용 추가 초기화를
|
|
||||||
protected abstract void ExecuteAILogic(); // 추상 함수를 선언할거에요 -> 자식이 반드시 구현해야 하는 AI를
|
protected abstract void ExecuteAILogic(); // 추상 함수를 선언할거에요 -> 자식이 반드시 구현해야 하는 AI를
|
||||||
protected virtual void OnResetStats() { } // 가상 함수를 선언할거에요 -> 자식 클래스 추가 리셋을
|
protected virtual void OnResetStats() { } // 가상 함수를 선언할거에요 -> 자식 클래스 추가 리셋을
|
||||||
|
|
||||||
|
|
@ -184,7 +179,6 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
if (!animator.GetCurrentAnimatorStateInfo(0).IsName(Monster_Idle))
|
if (!animator.GetCurrentAnimatorStateInfo(0).IsName(Monster_Idle))
|
||||||
animator.Play(Monster_Idle, 0, 0f); // 재생할거에요 -> 대기 애니를
|
animator.Play(Monster_Idle, 0, 0f); // 재생할거에요 -> 대기 애니를
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
// 피격 처리
|
// 피격 처리
|
||||||
|
|
@ -205,10 +199,10 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
OnHealthChanged?.Invoke(currentHP, maxHP); // 알릴거에요 -> UI에 체력 변경을
|
OnHealthChanged?.Invoke(currentHP, maxHP); // 알릴거에요 -> UI에 체력 변경을
|
||||||
|
|
||||||
if (currentHP <= 0) // 조건이 맞으면 실행할거에요 -> 체력이 바닥났으면
|
if (currentHP <= 0) // 조건이 맞으면 실행할거에요 -> 체력이 바닥났으면
|
||||||
{
|
{
|
||||||
Die(); // 실행할거에요 -> 사망 처리를
|
Die(); // 실행할거에요 -> 사망 처리를
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isHit) // 조건이 맞으면 실행할거에요 -> 아직 피격 상태가 아니면
|
if (!isHit) // 조건이 맞으면 실행할거에요 -> 아직 피격 상태가 아니면
|
||||||
StartHit(); // 실행할거에요 -> 피격 처리를
|
StartHit(); // 실행할거에요 -> 피격 처리를
|
||||||
|
|
@ -222,7 +216,6 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
OnHealthChanged?.Invoke(currentHP, maxHP); // 알릴거에요 -> UI에
|
OnHealthChanged?.Invoke(currentHP, maxHP); // 알릴거에요 -> UI에
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void StartHit() // 함수를 선언할거에요 -> 피격 시작을
|
|
||||||
{
|
{
|
||||||
isHit = true; // 설정할거에요 -> 피격 상태를
|
isHit = true; // 설정할거에요 -> 피격 상태를
|
||||||
isAttacking = false; // 해제할거에요 -> 공격 상태를
|
isAttacking = false; // 해제할거에요 -> 공격 상태를
|
||||||
|
|
@ -278,7 +271,6 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
if (myWeapon != null) myWeapon.DisableHitBox(); // 끌거에요 -> 무기 판정을
|
if (myWeapon != null) myWeapon.DisableHitBox(); // 끌거에요 -> 무기 판정을
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnHitEnd() // 함수를 선언할거에요 -> 피격 종료를
|
|
||||||
{
|
{
|
||||||
isHit = false; // 해제할거에요 -> 피격 상태를
|
isHit = false; // 해제할거에요 -> 피격 상태를
|
||||||
_hitCoroutine = null; // 초기화할거에요 -> 코루틴 핸들을
|
_hitCoroutine = null; // 초기화할거에요 -> 코루틴 핸들을
|
||||||
|
|
@ -329,20 +321,16 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
|
||||||
isAttacking = true; // 설정할거에요 -> 공격 중으로
|
isAttacking = true; // 설정할거에요 -> 공격 중으로
|
||||||
isResting = false; // 해제할거에요 -> 휴식 상태를
|
isResting = false; // 해제할거에요 -> 휴식 상태를
|
||||||
if (myWeapon != null) myWeapon.EnableHitBox(); // 켤거에요 -> 무기 판정을
|
if (myWeapon != null) myWeapon.EnableHitBox(); // 켤거에요 -> 무기 판정을
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnAttackEnd() // 함수를 선언할거에요 -> 공격 종료를
|
|
||||||
{
|
{
|
||||||
if (myWeapon != null) myWeapon.DisableHitBox(); // 끌거에요 -> 무기 판정을
|
if (myWeapon != null) myWeapon.DisableHitBox(); // 끌거에요 -> 무기 판정을
|
||||||
isAttacking = false; // 해제할거에요 -> 공격 상태를
|
isAttacking = false; // 해제할거에요 -> 공격 상태를
|
||||||
if (!isDead && !isHit) StartCoroutine(RestAfterAttack()); // 시작할거에요 -> 공격 후 휴식을
|
if (!isDead && !isHit) StartCoroutine(RestAfterAttack()); // 시작할거에요 -> 공격 후 휴식을
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IEnumerator RestAfterAttack() // 코루틴을 선언할거에요 -> 공격 후 휴식 로직을
|
protected virtual IEnumerator RestAfterAttack() // 코루틴을 선언할거에요 -> 공격 후 휴식 로직을
|
||||||
{
|
{
|
||||||
isResting = true; // 설정할거에요 -> 휴식 중으로
|
|
||||||
yield return new WaitForSeconds(attackRestDuration); // 기다릴거에요 -> 휴식 시간만큼
|
|
||||||
isResting = false; // 해제할거에요 -> 휴식 상태를
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -58,17 +58,12 @@ public class MeleeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryAttack() // 함수를 선언할거에요 -> 공격 시도를
|
|
||||||
{
|
{
|
||||||
if (Time.time < lastAttackTime + attackDelay) return; // 중단할거에요 -> 쿨타임이면
|
|
||||||
lastAttackTime = Time.time; // 갱신할거에요 -> 공격 시간을
|
|
||||||
isAttacking = true; // 설정할거에요 -> 공격 중으로
|
|
||||||
if (agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; } // 멈출거에요 -> 이동을
|
|
||||||
|
|
||||||
string animName = attackAnimations[attackIndex]; // 가져올거에요 -> 애니 이름을
|
string animName = attackAnimations[attackIndex]; // 가져올거에요 -> 애니 이름을
|
||||||
attackIndex = (attackIndex + 1) % attackAnimations.Length; // 갱신할거에요 -> 인덱스를
|
attackIndex = (attackIndex + 1) % attackAnimations.Length; // 갱신할거에요 -> 인덱스를
|
||||||
animator.Play(animName, 0, 0f); // 재생할거에요 -> 공격 애니를 (레이어 0 명시)
|
animator.Play(animName, 0, 0f); // 재생할거에요 -> 공격 애니를 (레이어 0 명시)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDie() // 함수를 실행할거에요 -> 사망 시
|
protected override void OnDie() // 함수를 실행할거에요 -> 사망 시
|
||||||
{
|
{
|
||||||
|
|
@ -98,4 +93,4 @@ public class MeleeMonster : MonsterClass // 클래스를 선언할거에요 ->
|
||||||
Gizmos.color = Color.red; // 설정할거에요 -> 빨강 외곽선을
|
Gizmos.color = Color.red; // 설정할거에요 -> 빨강 외곽선을
|
||||||
Gizmos.DrawWireSphere(transform.position, attackRange); // 그릴거에요 -> 공격 범위 외곽선을
|
Gizmos.DrawWireSphere(transform.position, attackRange); // 그릴거에요 -> 공격 범위 외곽선을
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -41,11 +41,7 @@ public class UniversalRangedMonster : MonsterClass // 클래스를 선언할거
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryAttack() // 함수를 선언할거에요 -> 공격 시도를
|
|
||||||
{
|
{
|
||||||
if (Time.time < lastAttackTime + attackDelay) return; // 중단할거에요 -> 쿨타임 중이면
|
|
||||||
lastAttackTime = Time.time; isAttacking = true; // 갱신할거에요 -> 시간과 상태를
|
|
||||||
if (agent.isOnNavMesh) agent.isStopped = true; // 멈출거에요 -> 이동을
|
|
||||||
|
|
||||||
Vector3 dir = (playerTransform.position - transform.position).normalized; dir.y = 0; // 계산할거에요 -> 방향을
|
Vector3 dir = (playerTransform.position - transform.position).normalized; dir.y = 0; // 계산할거에요 -> 방향을
|
||||||
transform.rotation = Quaternion.LookRotation(dir); // 회전할거에요 -> 방향대로
|
transform.rotation = Quaternion.LookRotation(dir); // 회전할거에요 -> 방향대로
|
||||||
|
|
@ -101,4 +97,4 @@ public class UniversalRangedMonster : MonsterClass // 클래스를 선언할거
|
||||||
Gizmos.DrawSphere(firePoint.position, 0.1f); // 그릴거에요 -> 발사 위치 점을
|
Gizmos.DrawSphere(firePoint.position, 0.1f); // 그릴거에요 -> 발사 위치 점을
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
||||||
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
||||||
|
using System.Collections.Generic; // Dictionary를 사용할거에요 -> System.Collections.Generic을
|
||||||
|
|
||||||
public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> MonsterClass를 상속받는 NorcielBoss를
|
public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> MonsterClass를 상속받는 NorcielBoss를
|
||||||
{
|
{ // 코드 블록을 시작할거에요 -> NorcielBoss 범위를
|
||||||
// ══════════════════════════════════════════════
|
// ══════════════════════════════════════════════
|
||||||
// 인스펙터 설정
|
// 인스펙터 설정
|
||||||
// ══════════════════════════════════════════════
|
// ══════════════════════════════════════════════
|
||||||
|
|
@ -43,6 +44,8 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
|
|
||||||
private bool isBattleStarted = false; // 변수를 선언할거에요 -> 전투 시작 여부를
|
private bool isBattleStarted = false; // 변수를 선언할거에요 -> 전투 시작 여부를
|
||||||
private bool isWeaponless = false; // 변수를 선언할거에요 -> 쇠공 분실 여부를
|
private bool isWeaponless = false; // 변수를 선언할거에요 -> 쇠공 분실 여부를
|
||||||
|
|
||||||
|
private readonly Dictionary<string, float> _clipLengthCache = new Dictionary<string, float>(); // 딕셔너리를 선언할거에요 -> 애니메이션 길이를 저장할 캐시를
|
||||||
private bool isPerformingAction = false; // 변수를 선언할거에요 -> 행동 수행 중 여부를
|
private bool isPerformingAction = false; // 변수를 선언할거에요 -> 행동 수행 중 여부를
|
||||||
|
|
||||||
// 애니메이션 이벤트 신호용 플래그
|
// 애니메이션 이벤트 신호용 플래그
|
||||||
|
|
@ -60,6 +63,114 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
ballRb = ironBall != null ? ironBall.GetComponent<Rigidbody>() : null; // 가져올거에요 -> 쇠공 Rigidbody를
|
ballRb = ironBall != null ? ironBall.GetComponent<Rigidbody>() : null; // 가져올거에요 -> 쇠공 Rigidbody를
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float GetClipLength(string clipName, float fallback = 1.0f) // 함수를 정의할거에요 -> 이름으로 길이를 찾는 기능을
|
||||||
|
{ // 코드 블록을 시작할거에요 -> GetClipLength 범위를
|
||||||
|
if (_clipLengthCache.TryGetValue(clipName, out float length)) // 조건이 맞으면 실행할거에요 -> 캐시에서 바로 찾았다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 즉시 반환 범위를
|
||||||
|
return length; // 반환할거에요 -> 찾은 길이를
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 즉시 반환 끝
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, float> kvp in _clipLengthCache) // 반복할거에요 -> 캐시 전체를 뒤져서
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 부분 매칭 범위를
|
||||||
|
if (kvp.Key.EndsWith(clipName)) // 조건이 맞으면 실행할거에요 -> 이름 끝부분이 일치한다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 매칭 성공 범위를
|
||||||
|
_clipLengthCache[clipName] = kvp.Value; // 저장할거에요 -> 다음 검색을 위해 짧은 이름도 캐싱
|
||||||
|
Debug.Log($"🔗 [Boss] 부분 매칭 성공: \"{clipName}\" → \"{kvp.Key}\" ({kvp.Value:F2}초)"); // 로그를 찍을거에요
|
||||||
|
return kvp.Value; // 반환할거에요 -> 매칭된 길이를
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 매칭 성공 끝
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 부분 매칭 끝
|
||||||
|
|
||||||
|
Debug.LogWarning($"⚠️ [Boss] 클립 \"{clipName}\"을 찾지 못했습니다! fallback={fallback:F2}초 사용"); // 경고를 찍을거에요 -> 못 찾았을 때
|
||||||
|
return fallback; // 반환할거에요 -> 기본값을
|
||||||
|
} // 코드 블록을 끝낼거에요 -> GetClipLength를
|
||||||
|
|
||||||
|
private IEnumerator PlayAndWait(string animName, float fallback = 1.0f) // 코루틴을 정의할거에요 -> 애니 재생 후 길이만큼 대기하는 기능을
|
||||||
|
{ // 코드 블록을 시작할거에요 -> PlayAndWait 범위를
|
||||||
|
if (animator == null) // 조건이 맞으면 실행할거에요 -> 애니메이터가 없다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 예외 처리 범위를
|
||||||
|
Debug.LogWarning($"⚠️ [Boss] Animator 없음! \"{animName}\" fallback={fallback}초 대기"); // 경고를 찍을거에요
|
||||||
|
yield return new WaitForSeconds(Mathf.Max(0.1f, fallback)); // 대기할거에요 -> 최소 0.1초 또는 기본값만큼
|
||||||
|
yield break; // 종료할거에요
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 예외 처리 끝
|
||||||
|
|
||||||
|
int stateHash = Animator.StringToHash(animName); // 계산할거에요 -> 상태 이름의 해시값을
|
||||||
|
bool stateExists = animator.HasState(0, stateHash); // 확인할거에요 -> 상태가 실제로 존재하는지
|
||||||
|
|
||||||
|
if (!stateExists) // 조건이 맞으면 실행할거에요 -> 상태가 존재하지 않는다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 에러 처리 범위를
|
||||||
|
Debug.LogError($"❌ [Boss] Animator에 State \"{animName}\"이 없습니다! Animator Controller를 확인하세요."); // 에러를 찍을거에요
|
||||||
|
yield return new WaitForSeconds(Mathf.Max(0.1f, fallback)); // 대기할거에요 -> 기본값만큼
|
||||||
|
yield break; // 종료할거에요
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 에러 처리 끝
|
||||||
|
|
||||||
|
animator.Play(animName, 0, 0f); // 재생할거에요 -> 해당 애니메이션을 처음부터
|
||||||
|
yield return null; // 대기할거에요 -> 1프레임 동안 (상태 갱신)
|
||||||
|
|
||||||
|
float duration = GetClipLength(animName, -1f); // 가져올거에요 -> 캐싱된 길이를
|
||||||
|
|
||||||
|
if (duration < 0f) // 조건이 맞으면 실행할거에요 -> 캐시에 없는 경우
|
||||||
|
{ // 코드 블록을 시작할거에요 -> State 길이로 보정 범위를
|
||||||
|
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0); // 가져올거에요 -> 현재 상태 정보를
|
||||||
|
duration = stateInfo.length; // 가져올거에요 -> 상태의 길이를
|
||||||
|
|
||||||
|
if (duration > 0f) // 조건이 맞으면 실행할거에요 -> 유효한 길이면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 캐싱 범위를
|
||||||
|
_clipLengthCache[animName] = duration; // 저장할거에요 -> 캐시에 등록
|
||||||
|
Debug.Log($"🎬 [Boss] State에서 길이 확인 & 캐싱: \"{animName}\" = {duration:F2}초"); // 로그를 찍을거에요
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 캐싱 끝
|
||||||
|
else // 조건이 틀리면 실행할거에요 -> 길이가 이상하면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> fallback 적용 범위를
|
||||||
|
duration = Mathf.Max(0.1f, fallback); // 설정할거에요 -> 기본값으로 보장
|
||||||
|
Debug.LogWarning($"⚠️ [Boss] State \"{animName}\" 길이 비정상({stateInfo.length}초)! fallback={duration}초 사용"); // 경고를 찍을거에요
|
||||||
|
} // 코드 블록을 끝낼거에요 -> fallback 적용 끝
|
||||||
|
} // 코드 블록을 끝낼거에요 -> State 길이 보정 끝
|
||||||
|
|
||||||
|
float remaining = duration - Time.deltaTime; // 계산할거에요 -> 1프레임을 뺀 남은 시간을
|
||||||
|
|
||||||
|
if (remaining > 0f) // 조건이 맞으면 실행할거에요 -> 남은 시간이 양수면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 대기 범위를
|
||||||
|
yield return new WaitForSeconds(remaining); // 기다릴거에요 -> 남은 시간만큼
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 대기 끝
|
||||||
|
} // 코드 블록을 끝낼거에요 -> PlayAndWait를
|
||||||
|
|
||||||
|
private void CacheAllClipLengths() // 함수를 정의할거에요 -> 애니메이션 길이를 캐싱하는 로직을
|
||||||
|
{ // 코드 블록을 시작할거에요 -> CacheAllClipLengths 범위를
|
||||||
|
_clipLengthCache.Clear(); // 비울거에요 -> 기존 캐시 데이터를
|
||||||
|
|
||||||
|
if (animator == null || animator.runtimeAnimatorController == null) // 조건이 맞으면 실행할거에요 -> 애니메이터가 없다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 에러 처리 범위를
|
||||||
|
Debug.LogError("❌ [Boss] Animator 또는 RuntimeAnimatorController가 없습니다! 클립 길이를 캐싱할 수 없습니다."); // 에러를 출력할거에요
|
||||||
|
return; // 중단할거에요
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 에러 처리 끝
|
||||||
|
|
||||||
|
AnimationClip[] clips = animator.runtimeAnimatorController.animationClips; // 배열을 가져올거에요 -> 모든 애니메이션 클립을
|
||||||
|
|
||||||
|
foreach (AnimationClip clip in clips) // 반복할거에요 -> 모든 클립을 돌면서
|
||||||
|
{ // 코드 블록을 시작할거에요 -> foreach 범위를
|
||||||
|
|
||||||
|
if (!_clipLengthCache.ContainsKey(clip.name)) // 조건이 맞으면 실행할거에요 -> 이름이 캐시에 없다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 캐시 저장 범위를
|
||||||
|
_clipLengthCache[clip.name] = clip.length; // 저장할거에요 -> 원본 이름을 키로 길이를
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 캐시 저장 끝
|
||||||
|
|
||||||
|
int pipeIndex = clip.name.IndexOf('|'); // 위치를 찾을거에요 -> "|" 기호의 위치를
|
||||||
|
|
||||||
|
if (pipeIndex >= 0 && pipeIndex < clip.name.Length - 1) // 조건이 맞으면 실행할거에요 -> "|" 기호가 존재하면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 단축 이름 처리 범위를
|
||||||
|
string shortName = clip.name.Substring(pipeIndex + 1); // 추출할거에요 -> "|" 뒤의 짧은 이름을
|
||||||
|
|
||||||
|
if (!_clipLengthCache.ContainsKey(shortName)) // 조건이 맞으면 실행할거에요 -> 짧은 이름이 캐시에 없다면
|
||||||
|
{ // 코드 블록을 시작할거에요 -> 단축 이름 캐시 저장 범위를
|
||||||
|
_clipLengthCache[shortName] = clip.length; // 저장할거에요 -> 짧은 이름도 키로 등록
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 단축 이름 저장 끝
|
||||||
|
} // 코드 블록을 끝낼거에요 -> 단축 이름 처리 끝
|
||||||
|
|
||||||
|
Debug.Log($"🎬 [Boss] 클립 캐싱: \"{clip.name}\" = {clip.length:F2}초"); // 로그를 찍을거에요 -> 캐싱 정보를
|
||||||
|
} // 코드 블록을 끝낼거에요 -> foreach 끝
|
||||||
|
|
||||||
|
Debug.Log($"✅ [Boss] 총 {_clipLengthCache.Count}개 키 캐싱 완료! (원본 + 단축이름 포함)"); // 로그를 찍을거에요 -> 완료 정보를
|
||||||
|
} // 코드 블록을 끝낼거에요 -> CacheAllClipLengths를
|
||||||
|
|
||||||
protected override void Init() // 함수를 실행할거에요 -> 스탯/상태 초기화를
|
protected override void Init() // 함수를 실행할거에요 -> 스탯/상태 초기화를
|
||||||
{
|
{
|
||||||
base.Init(); // 실행할거에요 -> 부모 Init를
|
base.Init(); // 실행할거에요 -> 부모 Init를
|
||||||
|
|
@ -80,7 +191,7 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
{
|
{
|
||||||
PlayerMovement pm = FindObjectOfType<PlayerMovement>(); // 찾을거에요 -> PlayerMovement 스크립트로
|
PlayerMovement pm = FindObjectOfType<PlayerMovement>(); // 찾을거에요 -> PlayerMovement 스크립트로
|
||||||
if (pm != null) target = playerTransform = pm.transform; // 설정할거에요 -> 타겟을
|
if (pm != null) target = playerTransform = pm.transform; // 설정할거에요 -> 타겟을
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target == null) Debug.LogError("❌ [Boss] 플레이어를 찾지 못했습니다!"); // 에러를 찍을거에요
|
if (target == null) Debug.LogError("❌ [Boss] 플레이어를 찾지 못했습니다!"); // 에러를 찍을거에요
|
||||||
|
|
||||||
|
|
@ -104,7 +215,7 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
|
|
||||||
if (agent.isOnNavMesh) agent.isStopped = true; // 정지시킬거에요 -> NavMesh 위면
|
if (agent.isOnNavMesh) agent.isStopped = true; // 정지시킬거에요 -> NavMesh 위면
|
||||||
agent.enabled = false; // 끌거에요 -> 전투 시작 전까지 비활성화
|
agent.enabled = false; // 끌거에요 -> 전투 시작 전까지 비활성화
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start() // 함수를 실행할거에요 -> 게임 시작 시
|
private void Start() // 함수를 실행할거에요 -> 게임 시작 시
|
||||||
{
|
{
|
||||||
|
|
@ -115,7 +226,7 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
{
|
{
|
||||||
base.Update(); // 실행할거에요 -> 부모 Update를
|
base.Update(); // 실행할거에요 -> 부모 Update를
|
||||||
if (!isDead) ExecuteAILogic(); // 실행할거에요 -> 살아있으면 AI를
|
if (!isDead) ExecuteAILogic(); // 실행할거에요 -> 살아있으면 AI를
|
||||||
}
|
}
|
||||||
|
|
||||||
// ══════════════════════════════════════════════
|
// ══════════════════════════════════════════════
|
||||||
// 🎬 Animation Event 수신 함수
|
// 🎬 Animation Event 수신 함수
|
||||||
|
|
@ -238,8 +349,8 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
|
|
||||||
if (agent.isOnNavMesh) agent.isStopped = false; // 켤거에요 -> 이동을
|
if (agent.isOnNavMesh) agent.isStopped = false; // 켤거에요 -> 이동을
|
||||||
else Debug.LogError("❌ [Boss] NavMesh 연결 실패!"); // 에러를 찍을거에요
|
else Debug.LogError("❌ [Boss] NavMesh 연결 실패!"); // 에러를 찍을거에요
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ══════════════════════════════════════════════
|
// ══════════════════════════════════════════════
|
||||||
// 패턴 결정 & 실행
|
// 패턴 결정 & 실행
|
||||||
|
|
@ -401,7 +512,7 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
if (dir != Vector3.zero) // 조건이 맞으면 실행할거에요 -> 방향이 있다면
|
if (dir != Vector3.zero) // 조건이 맞으면 실행할거에요 -> 방향이 있다면
|
||||||
transform.rotation = Quaternion.Slerp(transform.rotation,
|
transform.rotation = Quaternion.Slerp(transform.rotation,
|
||||||
Quaternion.LookRotation(dir), Time.deltaTime * 5f); // 회전할거에요 -> 부드럽게
|
Quaternion.LookRotation(dir), Time.deltaTime * 5f); // 회전할거에요 -> 부드럽게
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMoveAnim() // 함수를 선언할거에요 -> 이동 애니메이션 갱신을
|
private void UpdateMoveAnim() // 함수를 선언할거에요 -> 이동 애니메이션 갱신을
|
||||||
{
|
{
|
||||||
|
|
@ -428,4 +539,5 @@ public class NorcielBoss : MonsterClass // 클래스를 선언할거에요 -> Mo
|
||||||
else Debug.LogError("[Boss] ObsessionSystem 인스턴스 없음!"); // 에러를 찍을거에요
|
else Debug.LogError("[Boss] ObsessionSystem 인스턴스 없음!"); // 에러를 찍을거에요
|
||||||
base.OnDie(); // 실행할거에요 -> 부모 사망 처리를
|
base.OnDie(); // 실행할거에요 -> 부모 사망 처리를
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // 코드 블록을 끝낼거에요 -> NorcielBoss를
|
||||||
|
|
@ -47,7 +47,7 @@ public class PlayerBehaviorTracker : MonoBehaviour // 클래스를 선언할거
|
||||||
{
|
{
|
||||||
if (Instance != null && Instance != this) { Destroy(gameObject); return; } // 중복이면 파괴할거에요
|
if (Instance != null && Instance != this) { Destroy(gameObject); return; } // 중복이면 파괴할거에요
|
||||||
Instance = this; // 값을 저장할거에요 -> 싱글톤 인스턴스를
|
Instance = this; // 값을 저장할거에요 -> 싱글톤 인스턴스를
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start() // 함수를 실행할거에요 -> 시작 시
|
private void Start() // 함수를 실행할거에요 -> 시작 시
|
||||||
{
|
{
|
||||||
|
|
@ -116,27 +116,27 @@ public class PlayerBehaviorTracker : MonoBehaviour // 클래스를 선언할거
|
||||||
int recentDashes = CountInWindow(dodgeTimestamps, dashCheckWindow); // 셀거에요 -> 설정된 시간 내 대쉬 횟수를
|
int recentDashes = CountInWindow(dodgeTimestamps, dashCheckWindow); // 셀거에요 -> 설정된 시간 내 대쉬 횟수를
|
||||||
|
|
||||||
if (recentDashes >= dashCountTrigger) // 조건이 맞으면 실행할거에요 -> 기준 횟수를 넘었다면
|
if (recentDashes >= dashCountTrigger) // 조건이 맞으면 실행할거에요 -> 기준 횟수를 넘었다면
|
||||||
{
|
{
|
||||||
ReportAction(CounterType.FrequentDash); // 보고할거에요 -> 대쉬 남발 행동을
|
ReportAction(CounterType.FrequentDash); // 보고할거에요 -> 대쉬 남발 행동을
|
||||||
// 너무 자주 보고하지 않게 리스트 일부 정리하거나 쿨타임 활용 (여기선 ReportAction의 쿨타임에 의존)
|
// 너무 자주 보고하지 않게 리스트 일부 정리하거나 쿨타임 활용 (여기선 ReportAction의 쿨타임에 의존)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RecordAimStart() // 함수를 선언할거에요 -> 조준 시작 기록을
|
public void RecordAimStart() // 함수를 선언할거에요 -> 조준 시작 기록을
|
||||||
{
|
{
|
||||||
if (!isAiming) { isAiming = true; currentAimStartTime = Time.time; } // 상태를 바꿀거에요 -> 조준 중으로
|
if (!isAiming) { isAiming = true; currentAimStartTime = Time.time; } // 상태를 바꿀거에요 -> 조준 중으로
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RecordAimEnd() // 함수를 선언할거에요 -> 조준 종료 기록을
|
public void RecordAimEnd() // 함수를 선언할거에요 -> 조준 종료 기록을
|
||||||
{
|
{
|
||||||
if (isAiming) { isAiming = false; aimStartTimes.Add(currentAimStartTime); aimEndTimes.Add(Time.time); } // 추가할거에요 -> 시작/종료 시간을
|
if (isAiming) { isAiming = false; aimStartTimes.Add(currentAimStartTime); aimEndTimes.Add(Time.time); } // 추가할거에요 -> 시작/종료 시간을
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RecordShot(bool isPierce) // 함수를 선언할거에요 -> 발사 기록을
|
public void RecordShot(bool isPierce) // 함수를 선언할거에요 -> 발사 기록을
|
||||||
{
|
{
|
||||||
totalShotTimestamps.Add(Time.time); // 추가할거에요 -> 전체 사격에
|
totalShotTimestamps.Add(Time.time); // 추가할거에요 -> 전체 사격에
|
||||||
if (isPierce) pierceShotTimestamps.Add(Time.time); // 추가할거에요 -> 관통 사격에
|
if (isPierce) pierceShotTimestamps.Add(Time.time); // 추가할거에요 -> 관통 사격에
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetForNewRun() // 함수를 선언할거에요 -> 초기화를
|
public void ResetForNewRun() // 함수를 선언할거에요 -> 초기화를
|
||||||
{
|
{
|
||||||
|
|
@ -165,10 +165,10 @@ public class PlayerBehaviorTracker : MonoBehaviour // 클래스를 선언할거
|
||||||
if (aimEndTimes[i] < cutoff) { aimStartTimes.RemoveAt(i); aimEndTimes.RemoveAt(i); continue; } // 삭제할거에요 -> 오래된 기록을
|
if (aimEndTimes[i] < cutoff) { aimStartTimes.RemoveAt(i); aimEndTimes.RemoveAt(i); continue; } // 삭제할거에요 -> 오래된 기록을
|
||||||
float start = Mathf.Max(aimStartTimes[i], cutoff); // 보정할거에요 -> 시작 시간을
|
float start = Mathf.Max(aimStartTimes[i], cutoff); // 보정할거에요 -> 시작 시간을
|
||||||
total += aimEndTimes[i] - start; // 더할거에요 -> 조준 시간을
|
total += aimEndTimes[i] - start; // 더할거에요 -> 조준 시간을
|
||||||
}
|
}
|
||||||
if (isAiming) { float start = Mathf.Max(currentAimStartTime, cutoff); total += Time.time - start; } // 더할거에요 -> 현재 조준 중인 시간을
|
if (isAiming) { float start = Mathf.Max(currentAimStartTime, cutoff); total += Time.time - start; } // 더할거에요 -> 현재 조준 중인 시간을
|
||||||
return total; // 반환할거에요 -> 총 시간을
|
return total; // 반환할거에요 -> 총 시간을
|
||||||
}
|
}
|
||||||
|
|
||||||
private float CalculatePierceRatio() // 함수를 선언할거에요 -> 관통 비율 계산을
|
private float CalculatePierceRatio() // 함수를 선언할거에요 -> 관통 비율 계산을
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -59,3 +59,5 @@ crashlytics-build.properties
|
||||||
.DS_Store*
|
.DS_Store*
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
Desktop.ini
|
Desktop.ini
|
||||||
|
.git
|
||||||
|
.git/*
|
||||||
Loading…
Reference in New Issue
Block a user