feat: 피격 반응 면역을 경직/넉백/다운으로 분리
- 상태이상 데이터와 관리자에서 단일 피격 면역을 경직, 넉백, 다운 개별 면역으로 분리 - 플레이어 프리팹과 디버그 메뉴, 공용 경직 애니메이션을 갱신해 분리된 면역 상태를 테스트 가능하게 정리 - PlayMode 테스트를 추가해 각 면역이 대응하는 반응만 차단하는지 검증
This commit is contained in:
41914
Assets/_Game/Animations/Anim_Common_경직.anim
Normal file
41914
Assets/_Game/Animations/Anim_Common_경직.anim
Normal file
File diff suppressed because it is too large
Load Diff
8
Assets/_Game/Animations/Anim_Common_경직.anim.meta
Normal file
8
Assets/_Game/Animations/Anim_Common_경직.anim.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c23cdc1de7e1def5b30d36847b8626e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -19,7 +19,9 @@ MonoBehaviour:
|
||||
isDebuff: 0
|
||||
showInUI: 1
|
||||
isShieldState: 1
|
||||
ignoreHitReaction: 0
|
||||
ignoreStagger: 0
|
||||
ignoreKnockback: 0
|
||||
ignoreDown: 0
|
||||
loopingVfxPrefab: {fileID: 0}
|
||||
loopingVfxOffset: {x: 0, y: 0, z: 0}
|
||||
loopingVfxScaleMultiplier: 1
|
||||
|
||||
@@ -18,7 +18,9 @@ MonoBehaviour:
|
||||
level: 1
|
||||
isDebuff: 0
|
||||
showInUI: 0
|
||||
ignoreHitReaction: 0
|
||||
ignoreStagger: 0
|
||||
ignoreKnockback: 0
|
||||
ignoreDown: 0
|
||||
loopingVfxPrefab: {fileID: 1800972780968652, guid: 205d983549fba2a47a7808abf228f4be, type: 3}
|
||||
loopingVfxOffset: {x: 0, y: 3.2, z: 0}
|
||||
loopingVfxScaleMultiplier: 6
|
||||
|
||||
@@ -18,7 +18,9 @@ MonoBehaviour:
|
||||
level: 1
|
||||
isDebuff: 0
|
||||
showInUI: 0
|
||||
ignoreHitReaction: 1
|
||||
ignoreStagger: 1
|
||||
ignoreKnockback: 0
|
||||
ignoreDown: 0
|
||||
statModifiers: []
|
||||
periodicInterval: 0
|
||||
periodicValue: 0
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b08cc671f858a3b409170a5356e960a0, type: 3}
|
||||
m_Name: Data_Abnormality_Player_넉백면역
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Abnormalities.AbnormalityData
|
||||
abnormalityName: 넉백 면역
|
||||
icon: {fileID: 0}
|
||||
duration: 0.6
|
||||
level: 1
|
||||
isDebuff: 0
|
||||
showInUI: 0
|
||||
ignoreStagger: 0
|
||||
ignoreKnockback: 1
|
||||
ignoreDown: 0
|
||||
statModifiers: []
|
||||
periodicInterval: 0
|
||||
periodicValue: 0
|
||||
controlType: 0
|
||||
slowMultiplier: 0.5
|
||||
incomingDamageMultiplier: 1
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13796a48dd6e48a8a391c1b8d25e7020
|
||||
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b08cc671f858a3b409170a5356e960a0, type: 3}
|
||||
m_Name: Data_Abnormality_Player_다운면역
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Abnormalities.AbnormalityData
|
||||
abnormalityName: 다운 면역
|
||||
icon: {fileID: 0}
|
||||
duration: 0.6
|
||||
level: 1
|
||||
isDebuff: 0
|
||||
showInUI: 0
|
||||
ignoreStagger: 0
|
||||
ignoreKnockback: 0
|
||||
ignoreDown: 1
|
||||
statModifiers: []
|
||||
periodicInterval: 0
|
||||
periodicValue: 0
|
||||
controlType: 0
|
||||
slowMultiplier: 0.5
|
||||
incomingDamageMultiplier: 1
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc4faad006db4769b2400d8b8a8a2706
|
||||
@@ -19,7 +19,9 @@ MonoBehaviour:
|
||||
isDebuff: 0
|
||||
showInUI: 1
|
||||
isShieldState: 1
|
||||
ignoreHitReaction: 0
|
||||
ignoreStagger: 0
|
||||
ignoreKnockback: 0
|
||||
ignoreDown: 0
|
||||
loopingVfxPrefab: {fileID: 0}
|
||||
loopingVfxOffset: {x: 0, y: 0, z: 0}
|
||||
loopingVfxScaleMultiplier: 1
|
||||
|
||||
@@ -19,7 +19,9 @@ MonoBehaviour:
|
||||
isDebuff: 0
|
||||
showInUI: 1
|
||||
isShieldState: 1
|
||||
ignoreHitReaction: 0
|
||||
ignoreStagger: 0
|
||||
ignoreKnockback: 0
|
||||
ignoreDown: 0
|
||||
loopingVfxPrefab: {fileID: 0}
|
||||
loopingVfxOffset: {x: 0, y: 0, z: 0}
|
||||
loopingVfxScaleMultiplier: 1
|
||||
|
||||
@@ -4726,6 +4726,7 @@ GameObject:
|
||||
- component: {fileID: 2540460367028266762}
|
||||
- component: {fileID: 1829782337872253002}
|
||||
- component: {fileID: 7647416756581242399}
|
||||
- component: {fileID: -263312875943034690}
|
||||
m_Layer: 0
|
||||
m_Name: Prefab_Player_Default
|
||||
m_TagString: Player
|
||||
@@ -4903,6 +4904,7 @@ MonoBehaviour:
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
characterStats: {fileID: -5132198055668300151}
|
||||
abnormalityManager: {fileID: 0}
|
||||
defenseController: {fileID: 0}
|
||||
shieldStateAbnormality: {fileID: 0}
|
||||
passivePrototypeCatalog: {fileID: 11400000, guid: 328a12c12954ef649a9ba5892323c345, type: 2}
|
||||
passiveTree: {fileID: 11400000, guid: 33ad68732732b6a4589e24da88253f8d, type: 2}
|
||||
@@ -4965,6 +4967,14 @@ MonoBehaviour:
|
||||
NameHash: 976603345
|
||||
Synchronize: 1
|
||||
ParameterType: 9
|
||||
- name: Hit
|
||||
NameHash: 1654612129
|
||||
Synchronize: 1
|
||||
ParameterType: 9
|
||||
- name: HitSpeedMultiplier
|
||||
NameHash: -316320400
|
||||
Synchronize: 1
|
||||
ParameterType: 1
|
||||
AnimatorParametersExpanded: 0
|
||||
--- !u!95 &3426985706796420257
|
||||
Animator:
|
||||
@@ -5026,19 +5036,29 @@ MonoBehaviour:
|
||||
registeredClips:
|
||||
- {fileID: 7400000, guid: e920395a39d50ca429748ac26967e22f, type: 2}
|
||||
- {fileID: 7400000, guid: 920ea8a73bbf84849b01d3875ff4e4c3, type: 2}
|
||||
- {fileID: 7400000, guid: 0e2ed792a5988304c82e86a671d181d9, type: 2}
|
||||
- {fileID: 7400000, guid: 5c93f4c7dbc1b314d8e7b318826ef530, type: 2}
|
||||
- {fileID: 7400000, guid: afba3dfa5c315c04fa8af0e2e52aee3c, type: 2}
|
||||
- {fileID: 7400000, guid: d8bb58f4f1cc36440896fec5c4002e59, type: 2}
|
||||
- {fileID: 7400000, guid: dc5e72498abe07149b02d93a308697db, type: 2}
|
||||
- {fileID: 7400000, guid: 7ba0436909058c54fb6203180daf8377, type: 2}
|
||||
- {fileID: 7400000, guid: 53d4b641824bfd248ab6ba10ec9c4b00, type: 2}
|
||||
- {fileID: 7400000, guid: 81732d3b50fdd8645b9465a4f12a99ae, type: 2}
|
||||
- {fileID: 7400000, guid: 55409975b480666448b276c21d9aeb3d, type: 2}
|
||||
- {fileID: 7400000, guid: 686713d64f5e0dd4585b6a3d00fb25a3, type: 2}
|
||||
- {fileID: 7400000, guid: fabf33afcfd658d47a5566582fdbf044, type: 2}
|
||||
- {fileID: 7400000, guid: 581f9de1a3e502f4eb95b1e922117c5c, type: 2}
|
||||
- {fileID: 7400000, guid: 60a7aefb54ade4a41904977685930f3d, type: 2}
|
||||
- {fileID: 7400000, guid: b08df23bb6e5efe4db4dae2bb02382b1, type: 2}
|
||||
- {fileID: 7400000, guid: 3fe6587798a1a3a47a568b0dea6ffbf4, type: 2}
|
||||
- {fileID: 7400000, guid: 448433a9cacf21e428d4e29f81741ad2, type: 2}
|
||||
- {fileID: 7400000, guid: e586d02e6719b56489738b82604abdcf, type: 2}
|
||||
- {fileID: 7400000, guid: 0c9ba11ed23236649929b0225a8beadb, type: 2}
|
||||
- {fileID: 7400000, guid: fe55ab7fad6cd644db9bd2b6183fe180, type: 2}
|
||||
- {fileID: 7400000, guid: 7813457eddc067249a6ed50f31b6fe8c, type: 2}
|
||||
- {fileID: 7400000, guid: b7223eada9e64304baa6b4c9dcdfcd15, type: 2}
|
||||
- {fileID: 7400000, guid: 295669009c1870f4ab5d43fa28fd6e30, type: 2}
|
||||
- {fileID: 7400000, guid: e7ef39b0eacfc6940a8c7e1f20ba97e7, type: 2}
|
||||
- {fileID: 7400000, guid: 7f0d64090ab5adf439b9437c98a0bdd0, type: 2}
|
||||
- {fileID: 7400000, guid: df8ffc011feaf17429b7f429f635db3f, type: 2}
|
||||
- {fileID: 7400000, guid: 23aba6e7f76aa57478374325cb4f454e, type: 2}
|
||||
@@ -5047,6 +5067,7 @@ MonoBehaviour:
|
||||
debugDrawDuration: 1
|
||||
lastCancelledSkillName:
|
||||
lastCancelReason: 0
|
||||
lastExecutionResult: 0
|
||||
--- !u!114 &6585367215453362640
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5208,6 +5229,7 @@ MonoBehaviour:
|
||||
abnormalityManager: {fileID: 0}
|
||||
skillController: {fileID: 0}
|
||||
hitReactionController: {fileID: 0}
|
||||
defenseController: {fileID: 0}
|
||||
spectator: {fileID: 0}
|
||||
--- !u!114 &2540460367028266762
|
||||
MonoBehaviour:
|
||||
@@ -5281,6 +5303,22 @@ MonoBehaviour:
|
||||
inRangeColor: {r: 0.2, g: 1, b: 0.2, a: 0.8}
|
||||
outOfRangeColor: {r: 1, g: 0.3, b: 0.3, a: 0.8}
|
||||
useSkillRange: 1
|
||||
--- !u!208 &-263312875943034690
|
||||
NavMeshObstacle:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6473031571298860035}
|
||||
m_Enabled: 0
|
||||
serializedVersion: 3
|
||||
m_Shape: 1
|
||||
m_Extents: {x: 0.5, y: 0.5, z: 0.5}
|
||||
m_MoveThreshold: 0.1
|
||||
m_Carve: 0
|
||||
m_CarveOnlyStationary: 1
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_TimeToStationary: 0.5
|
||||
--- !u!1 &6541621058422482552
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -71,8 +71,14 @@ namespace Colosseum.Abnormalities
|
||||
[Tooltip("보호막 계열 상태인지 여부 (보호막 인스턴스 동기화용)")]
|
||||
public bool isShieldState = false;
|
||||
|
||||
[Tooltip("활성 중에는 일반 피격 반응(경직, 넉백, 다운)을 무시할지 여부")]
|
||||
public bool ignoreHitReaction = false;
|
||||
[Tooltip("활성 중에는 경직을 무시할지 여부")]
|
||||
public bool ignoreStagger = false;
|
||||
|
||||
[Tooltip("활성 중에는 넉백을 무시할지 여부")]
|
||||
public bool ignoreKnockback = false;
|
||||
|
||||
[Tooltip("활성 중에는 다운을 무시할지 여부")]
|
||||
public bool ignoreDown = false;
|
||||
|
||||
[Header("시각 효과")]
|
||||
[Tooltip("이상 상태가 유지되는 동안 대상에 붙일 루핑 VFX 프리팹")]
|
||||
|
||||
@@ -32,7 +32,9 @@ namespace Colosseum.Abnormalities
|
||||
private int stunCount;
|
||||
private int silenceCount;
|
||||
private int invincibleCount;
|
||||
private int hitReactionImmuneCount;
|
||||
private int staggerImmuneCount;
|
||||
private int knockbackImmuneCount;
|
||||
private int downImmuneCount;
|
||||
private float slowMultiplier = 1f;
|
||||
private float incomingDamageMultiplier = 1f;
|
||||
|
||||
@@ -40,7 +42,9 @@ namespace Colosseum.Abnormalities
|
||||
private NetworkVariable<int> syncedStunCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<int> syncedSilenceCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<int> syncedInvincibleCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<int> syncedHitReactionImmuneCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<int> syncedStaggerImmuneCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<int> syncedKnockbackImmuneCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<int> syncedDownImmuneCount = new NetworkVariable<int>(0);
|
||||
private NetworkVariable<float> syncedSlowMultiplier = new NetworkVariable<float>(1f);
|
||||
|
||||
// 네트워크 동기화용 데이터
|
||||
@@ -62,9 +66,19 @@ namespace Colosseum.Abnormalities
|
||||
public bool IsInvincible => GetCurrentInvincibleCount() > 0;
|
||||
|
||||
/// <summary>
|
||||
/// 일반 피격 반응 무시 상태 여부
|
||||
/// 경직 면역 상태 여부
|
||||
/// </summary>
|
||||
public bool IsHitReactionImmune => GetCurrentHitReactionImmuneCount() > 0;
|
||||
public bool IsStaggerImmune => GetCurrentStaggerImmuneCount() > 0;
|
||||
|
||||
/// <summary>
|
||||
/// 넉백 면역 상태 여부
|
||||
/// </summary>
|
||||
public bool IsKnockbackImmune => GetCurrentKnockbackImmuneCount() > 0;
|
||||
|
||||
/// <summary>
|
||||
/// 다운 면역 상태 여부
|
||||
/// </summary>
|
||||
public bool IsDownImmune => GetCurrentDownImmuneCount() > 0;
|
||||
|
||||
/// <summary>
|
||||
/// 이동 속도 배율 (1.0 = 기본, 0.5 = 50% 감소)
|
||||
@@ -139,7 +153,9 @@ namespace Colosseum.Abnormalities
|
||||
syncedStunCount.OnValueChanged += HandleSyncedStunChanged;
|
||||
syncedSilenceCount.OnValueChanged += HandleSyncedSilenceChanged;
|
||||
syncedInvincibleCount.OnValueChanged += HandleSyncedInvincibleChanged;
|
||||
syncedHitReactionImmuneCount.OnValueChanged += HandleSyncedHitReactionImmuneChanged;
|
||||
syncedStaggerImmuneCount.OnValueChanged += HandleSyncedStaggerImmuneChanged;
|
||||
syncedKnockbackImmuneCount.OnValueChanged += HandleSyncedKnockbackImmuneChanged;
|
||||
syncedDownImmuneCount.OnValueChanged += HandleSyncedDownImmuneChanged;
|
||||
syncedSlowMultiplier.OnValueChanged += HandleSyncedSlowChanged;
|
||||
|
||||
if (networkController != null)
|
||||
@@ -161,7 +177,9 @@ namespace Colosseum.Abnormalities
|
||||
syncedStunCount.OnValueChanged -= HandleSyncedStunChanged;
|
||||
syncedSilenceCount.OnValueChanged -= HandleSyncedSilenceChanged;
|
||||
syncedInvincibleCount.OnValueChanged -= HandleSyncedInvincibleChanged;
|
||||
syncedHitReactionImmuneCount.OnValueChanged -= HandleSyncedHitReactionImmuneChanged;
|
||||
syncedStaggerImmuneCount.OnValueChanged -= HandleSyncedStaggerImmuneChanged;
|
||||
syncedKnockbackImmuneCount.OnValueChanged -= HandleSyncedKnockbackImmuneChanged;
|
||||
syncedDownImmuneCount.OnValueChanged -= HandleSyncedDownImmuneChanged;
|
||||
syncedSlowMultiplier.OnValueChanged -= HandleSyncedSlowChanged;
|
||||
|
||||
if (networkController != null)
|
||||
@@ -447,10 +465,14 @@ namespace Colosseum.Abnormalities
|
||||
{
|
||||
bool enteredStun = false;
|
||||
|
||||
if (data.ignoreHitReaction)
|
||||
{
|
||||
hitReactionImmuneCount++;
|
||||
}
|
||||
if (data.ignoreStagger)
|
||||
staggerImmuneCount++;
|
||||
|
||||
if (data.ignoreKnockback)
|
||||
knockbackImmuneCount++;
|
||||
|
||||
if (data.ignoreDown)
|
||||
downImmuneCount++;
|
||||
|
||||
switch (data.controlType)
|
||||
{
|
||||
@@ -482,10 +504,14 @@ namespace Colosseum.Abnormalities
|
||||
|
||||
private void RemoveControlEffect(AbnormalityData data)
|
||||
{
|
||||
if (data.ignoreHitReaction)
|
||||
{
|
||||
hitReactionImmuneCount = Mathf.Max(0, hitReactionImmuneCount - 1);
|
||||
}
|
||||
if (data.ignoreStagger)
|
||||
staggerImmuneCount = Mathf.Max(0, staggerImmuneCount - 1);
|
||||
|
||||
if (data.ignoreKnockback)
|
||||
knockbackImmuneCount = Mathf.Max(0, knockbackImmuneCount - 1);
|
||||
|
||||
if (data.ignoreDown)
|
||||
downImmuneCount = Mathf.Max(0, downImmuneCount - 1);
|
||||
|
||||
switch (data.controlType)
|
||||
{
|
||||
@@ -542,7 +568,11 @@ namespace Colosseum.Abnormalities
|
||||
|
||||
private int GetCurrentInvincibleCount() => IsServer ? invincibleCount : syncedInvincibleCount.Value;
|
||||
|
||||
private int GetCurrentHitReactionImmuneCount() => IsServer ? hitReactionImmuneCount : syncedHitReactionImmuneCount.Value;
|
||||
private int GetCurrentStaggerImmuneCount() => IsServer ? staggerImmuneCount : syncedStaggerImmuneCount.Value;
|
||||
|
||||
private int GetCurrentKnockbackImmuneCount() => IsServer ? knockbackImmuneCount : syncedKnockbackImmuneCount.Value;
|
||||
|
||||
private int GetCurrentDownImmuneCount() => IsServer ? downImmuneCount : syncedDownImmuneCount.Value;
|
||||
|
||||
private float GetCurrentSlowMultiplier() => IsServer ? slowMultiplier : syncedSlowMultiplier.Value;
|
||||
|
||||
@@ -554,7 +584,9 @@ namespace Colosseum.Abnormalities
|
||||
syncedStunCount.Value = stunCount;
|
||||
syncedSilenceCount.Value = silenceCount;
|
||||
syncedInvincibleCount.Value = invincibleCount;
|
||||
syncedHitReactionImmuneCount.Value = hitReactionImmuneCount;
|
||||
syncedStaggerImmuneCount.Value = staggerImmuneCount;
|
||||
syncedKnockbackImmuneCount.Value = knockbackImmuneCount;
|
||||
syncedDownImmuneCount.Value = downImmuneCount;
|
||||
syncedSlowMultiplier.Value = slowMultiplier;
|
||||
}
|
||||
|
||||
@@ -636,7 +668,23 @@ namespace Colosseum.Abnormalities
|
||||
OnAbnormalitiesChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void HandleSyncedHitReactionImmuneChanged(int oldValue, int newValue)
|
||||
private void HandleSyncedStaggerImmuneChanged(int oldValue, int newValue)
|
||||
{
|
||||
if (oldValue == newValue)
|
||||
return;
|
||||
|
||||
OnAbnormalitiesChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void HandleSyncedKnockbackImmuneChanged(int oldValue, int newValue)
|
||||
{
|
||||
if (oldValue == newValue)
|
||||
return;
|
||||
|
||||
OnAbnormalitiesChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void HandleSyncedDownImmuneChanged(int oldValue, int newValue)
|
||||
{
|
||||
if (oldValue == newValue)
|
||||
return;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Colosseum.Editor
|
||||
private const string StunAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Player_Stun.asset";
|
||||
private const string SilenceAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Player_Silence.asset";
|
||||
private const string MarkAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Player_집행자의낙인.asset";
|
||||
private const string HitReactionImmuneAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Player_경직면역.asset";
|
||||
private const string StaggerImmuneAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Player_경직면역.asset";
|
||||
private const string TestDebuffAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Test_Debuff.asset";
|
||||
private const string ShieldAbnormalityPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Common_보호막.asset";
|
||||
private const string ShieldTypeAPath = "Assets/_Game/Data/Abnormalities/Data_Abnormality_Test_보호막A.asset";
|
||||
@@ -729,7 +729,7 @@ namespace Colosseum.Editor
|
||||
SkillEffect damageEffect = AssetDatabase.LoadAssetAtPath<SkillEffect>("Assets/_Game/Data/Skills/Effects/Data_SkillEffect_Player_찌르기_0_데미지.asset");
|
||||
SkillEffect tauntEffect = AssetDatabase.LoadAssetAtPath<SkillEffect>("Assets/_Game/Data/Skills/Effects/Data_SkillEffect_Player_도발_0_도발.asset");
|
||||
SkillEffect shieldEffect = AssetDatabase.LoadAssetAtPath<SkillEffect>("Assets/_Game/Data/Skills/Effects/Data_SkillEffect_Player_보호막_0_보호막.asset");
|
||||
AbnormalityData hitReactionImmuneAbnormality = AssetDatabase.LoadAssetAtPath<AbnormalityData>(HitReactionImmuneAbnormalityPath);
|
||||
AbnormalityData staggerImmuneAbnormality = AssetDatabase.LoadAssetAtPath<AbnormalityData>(StaggerImmuneAbnormalityPath);
|
||||
AbnormalityData testDebuffAbnormality = AssetDatabase.LoadAssetAtPath<AbnormalityData>(TestDebuffAbnormalityPath);
|
||||
DamageEffect edgeDamageEffect = CreateOrUpdateDamageEffectAsset(EdgeDamageEffectPath, 4f);
|
||||
DamageEffect impactDamageEffect = CreateOrUpdateDamageEffectAsset(ImpactDamageEffectPath, 7f);
|
||||
@@ -821,7 +821,7 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
null,
|
||||
new[] { hitReactionImmuneAbnormality },
|
||||
new[] { staggerImmuneAbnormality },
|
||||
allowedSkillRoles: SkillRoleType.All,
|
||||
allowedSkillActivationTypes: SkillActivationType.All);
|
||||
|
||||
|
||||
@@ -84,9 +84,19 @@ namespace Colosseum.Player
|
||||
public bool IsStaggered => isStaggered.Value;
|
||||
|
||||
/// <summary>
|
||||
/// 피격 반응 무시 상태 여부
|
||||
/// 경직 면역 상태 여부
|
||||
/// </summary>
|
||||
public bool IsHitReactionImmune => abnormalityManager != null && abnormalityManager.IsHitReactionImmune;
|
||||
public bool IsStaggerImmune => abnormalityManager != null && abnormalityManager.IsStaggerImmune;
|
||||
|
||||
/// <summary>
|
||||
/// 넉백 면역 상태 여부
|
||||
/// </summary>
|
||||
public bool IsKnockbackImmune => abnormalityManager != null && abnormalityManager.IsKnockbackImmune;
|
||||
|
||||
/// <summary>
|
||||
/// 다운 면역 상태 여부
|
||||
/// </summary>
|
||||
public bool IsDownImmune => abnormalityManager != null && abnormalityManager.IsDownImmune;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -121,7 +131,7 @@ namespace Colosseum.Player
|
||||
if (networkController != null && networkController.IsDead)
|
||||
return;
|
||||
|
||||
if (IsHitReactionImmune || isDowned.Value)
|
||||
if (IsStaggerImmune || isDowned.Value)
|
||||
return;
|
||||
|
||||
if (duration <= 0f)
|
||||
@@ -153,7 +163,7 @@ namespace Colosseum.Player
|
||||
if (networkController != null && networkController.IsDead)
|
||||
return;
|
||||
|
||||
if (IsHitReactionImmune || isDowned.Value)
|
||||
if (IsKnockbackImmune || isDowned.Value)
|
||||
return;
|
||||
|
||||
if (duration <= 0f || worldVelocity.sqrMagnitude <= 0.0001f)
|
||||
@@ -187,7 +197,7 @@ namespace Colosseum.Player
|
||||
if (networkController != null && networkController.IsDead)
|
||||
return;
|
||||
|
||||
if (IsHitReactionImmune)
|
||||
if (IsDownImmune)
|
||||
return;
|
||||
|
||||
downRemainingTime = Mathf.Max(downRemainingTime, duration);
|
||||
|
||||
@@ -8,6 +8,7 @@ using UnityEngine.TestTools;
|
||||
using Unity.Netcode;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
|
||||
using Colosseum.Abnormalities;
|
||||
using Colosseum.Player;
|
||||
|
||||
namespace Colosseum.Tests
|
||||
@@ -26,6 +27,7 @@ namespace Colosseum.Tests
|
||||
private NetworkManager networkManager;
|
||||
private GameObject playerObject;
|
||||
private HitReactionController hitReactionController;
|
||||
private AbnormalityManager abnormalityManager;
|
||||
private Animator animator;
|
||||
|
||||
[UnitySetUp]
|
||||
@@ -55,6 +57,7 @@ namespace Colosseum.Tests
|
||||
playerObject.transform.position = Vector3.zero;
|
||||
|
||||
playerObject.AddComponent<NetworkObject>();
|
||||
abnormalityManager = playerObject.AddComponent<AbnormalityManager>();
|
||||
hitReactionController = playerObject.AddComponent<HitReactionController>();
|
||||
|
||||
GameObject visualObject = new GameObject("Visual");
|
||||
@@ -72,6 +75,7 @@ namespace Colosseum.Tests
|
||||
yield return null;
|
||||
|
||||
Assert.NotNull(hitReactionController, "HitReactionController를 생성하지 못했습니다.");
|
||||
Assert.NotNull(abnormalityManager, "AbnormalityManager를 생성하지 못했습니다.");
|
||||
Assert.NotNull(animator, "테스트용 Animator를 생성하지 못했습니다.");
|
||||
}
|
||||
|
||||
@@ -120,6 +124,69 @@ namespace Colosseum.Tests
|
||||
Assert.Greater(measuredDelta, 0.01f, "넉백에서 Hit 애니메이션이 재생되지 않았습니다.");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator StaggerImmunity_OnlyBlocksStagger()
|
||||
{
|
||||
AbnormalityData staggerImmunity = CreateImmunityAbnormality("테스트 경직 면역", ignoreStagger: true);
|
||||
abnormalityManager.ApplyAbnormality(staggerImmunity, playerObject);
|
||||
yield return null;
|
||||
|
||||
hitReactionController.ApplyStagger(0.4f, false);
|
||||
Assert.IsFalse(hitReactionController.IsStaggered, "경직 면역 상태인데 경직이 적용되었습니다.");
|
||||
yield return ResetHitReactionState();
|
||||
|
||||
hitReactionController.ApplyKnockback(Vector3.back * 3f, 0.25f, false);
|
||||
Assert.IsTrue(hitReactionController.IsKnockbackActive, "경직 면역이 넉백까지 막으면 안 됩니다.");
|
||||
yield return ResetHitReactionState();
|
||||
|
||||
hitReactionController.ApplyDown(0.3f);
|
||||
Assert.IsTrue(hitReactionController.IsDowned, "경직 면역이 다운까지 막으면 안 됩니다.");
|
||||
|
||||
Object.DestroyImmediate(staggerImmunity);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator KnockbackImmunity_OnlyBlocksKnockback()
|
||||
{
|
||||
AbnormalityData knockbackImmunity = CreateImmunityAbnormality("테스트 넉백 면역", ignoreKnockback: true);
|
||||
abnormalityManager.ApplyAbnormality(knockbackImmunity, playerObject);
|
||||
yield return null;
|
||||
|
||||
hitReactionController.ApplyStagger(0.4f, false);
|
||||
Assert.IsTrue(hitReactionController.IsStaggered, "넉백 면역이 경직까지 막으면 안 됩니다.");
|
||||
yield return ResetHitReactionState();
|
||||
|
||||
hitReactionController.ApplyKnockback(Vector3.back * 3f, 0.25f, false);
|
||||
Assert.IsFalse(hitReactionController.IsKnockbackActive, "넉백 면역 상태인데 넉백이 적용되었습니다.");
|
||||
yield return ResetHitReactionState();
|
||||
|
||||
hitReactionController.ApplyDown(0.3f);
|
||||
Assert.IsTrue(hitReactionController.IsDowned, "넉백 면역이 다운까지 막으면 안 됩니다.");
|
||||
|
||||
Object.DestroyImmediate(knockbackImmunity);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator DownImmunity_OnlyBlocksDown()
|
||||
{
|
||||
AbnormalityData downImmunity = CreateImmunityAbnormality("테스트 다운 면역", ignoreDown: true);
|
||||
abnormalityManager.ApplyAbnormality(downImmunity, playerObject);
|
||||
yield return null;
|
||||
|
||||
hitReactionController.ApplyStagger(0.4f, false);
|
||||
Assert.IsTrue(hitReactionController.IsStaggered, "다운 면역이 경직까지 막으면 안 됩니다.");
|
||||
yield return ResetHitReactionState();
|
||||
|
||||
hitReactionController.ApplyKnockback(Vector3.back * 3f, 0.25f, false);
|
||||
Assert.IsTrue(hitReactionController.IsKnockbackActive, "다운 면역이 넉백까지 막으면 안 됩니다.");
|
||||
yield return ResetHitReactionState();
|
||||
|
||||
hitReactionController.ApplyDown(0.3f);
|
||||
Assert.IsFalse(hitReactionController.IsDowned, "다운 면역 상태인데 다운이 적용되었습니다.");
|
||||
|
||||
Object.DestroyImmediate(downImmunity);
|
||||
}
|
||||
|
||||
private IEnumerator MeasureHitPlaybackDelta(System.Action applyReaction, float expectedSpeedMultiplier, System.Action<float> setMeasuredDelta)
|
||||
{
|
||||
hitReactionController.ClearHitReactionState();
|
||||
@@ -164,8 +231,33 @@ namespace Colosseum.Tests
|
||||
return (ushort)Random.Range(20000, 40000);
|
||||
}
|
||||
|
||||
private static AbnormalityData CreateImmunityAbnormality(string abnormalityName, bool ignoreStagger = false, bool ignoreKnockback = false, bool ignoreDown = false)
|
||||
{
|
||||
AbnormalityData abnormalityData = ScriptableObject.CreateInstance<AbnormalityData>();
|
||||
abnormalityData.abnormalityName = abnormalityName;
|
||||
abnormalityData.duration = 5f;
|
||||
abnormalityData.ignoreStagger = ignoreStagger;
|
||||
abnormalityData.ignoreKnockback = ignoreKnockback;
|
||||
abnormalityData.ignoreDown = ignoreDown;
|
||||
return abnormalityData;
|
||||
}
|
||||
|
||||
private IEnumerator ResetHitReactionState()
|
||||
{
|
||||
hitReactionController.ClearHitReactionState();
|
||||
yield return null;
|
||||
}
|
||||
|
||||
private void CleanupTestObjects()
|
||||
{
|
||||
if (NetworkManager.Singleton != null && NetworkManager.Singleton.gameObject != networkManagerObject)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsListening)
|
||||
NetworkManager.Singleton.Shutdown();
|
||||
|
||||
Object.DestroyImmediate(NetworkManager.Singleton.gameObject);
|
||||
}
|
||||
|
||||
if (playerObject != null)
|
||||
{
|
||||
Object.DestroyImmediate(playerObject);
|
||||
|
||||
Reference in New Issue
Block a user