feat: 플레이어 경직/다운 회복 구간 추가
- HitReactionController에 경직, 다운 회복 가능 구간, Hit 속도 배율 파라미터 처리를 추가 - DownBegin/Recover 상태 종료를 StateMachineBehaviour로 받아 구르기 허용 구간과 다운 해제를 분리 - 드로그 발구르기를 경직 이펙트로 전환하고 넉백/경직 이펙트에서 Hit 애니메이션 속도 배율을 설정 가능하게 정리 - PlayMode 테스트를 추가해 경직/넉백이 Hit 애니메이션 속도 배율을 실제로 반영하는지 자동 검증
This commit is contained in:
@@ -27,6 +27,33 @@ AnimatorState:
|
|||||||
m_MirrorParameter:
|
m_MirrorParameter:
|
||||||
m_CycleOffsetParameter:
|
m_CycleOffsetParameter:
|
||||||
m_TimeParameter:
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &-7325123755187262477
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Hit
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: -4328548395604843749}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 1
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: -4467167322993697325, guid: 575336e929435dc4398adefbfa9cde78, type: 3}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter: HitSpeedMultiplier
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
--- !u!1101 &-5485275494767118128
|
--- !u!1101 &-5485275494767118128
|
||||||
AnimatorStateTransition:
|
AnimatorStateTransition:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
@@ -88,12 +115,16 @@ AnimatorStateMachine:
|
|||||||
- serializedVersion: 1
|
- serializedVersion: 1
|
||||||
m_State: {fileID: 1111345123456789014}
|
m_State: {fileID: 1111345123456789014}
|
||||||
m_Position: {x: -1260, y: 140, z: 0}
|
m_Position: {x: -1260, y: 140, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -7325123755187262477}
|
||||||
|
m_Position: {x: -450, y: 60, z: 0}
|
||||||
m_ChildStateMachines: []
|
m_ChildStateMachines: []
|
||||||
m_AnyStateTransitions:
|
m_AnyStateTransitions:
|
||||||
- {fileID: -754003289131015157}
|
- {fileID: -754003289131015157}
|
||||||
- {fileID: 469741948129995159}
|
- {fileID: 469741948129995159}
|
||||||
- {fileID: 6228136561094308872}
|
- {fileID: 6228136561094308872}
|
||||||
- {fileID: 1111345123456789021}
|
- {fileID: 1111345123456789021}
|
||||||
|
- {fileID: -4832749926410887626}
|
||||||
m_EntryTransitions: []
|
m_EntryTransitions: []
|
||||||
m_StateMachineTransitions: {}
|
m_StateMachineTransitions: {}
|
||||||
m_StateMachineBehaviours: []
|
m_StateMachineBehaviours: []
|
||||||
@@ -102,6 +133,31 @@ AnimatorStateMachine:
|
|||||||
m_ExitPosition: {x: 280, y: 270, z: 0}
|
m_ExitPosition: {x: 280, y: 270, z: 0}
|
||||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||||
m_DefaultState: {fileID: -7908033645098541312}
|
m_DefaultState: {fileID: -7908033645098541312}
|
||||||
|
--- !u!1101 &-4832749926410887626
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Hit
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7325123755187262477}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.75
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
--- !u!1102 &-4652545120162758660
|
--- !u!1102 &-4652545120162758660
|
||||||
AnimatorState:
|
AnimatorState:
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
@@ -129,6 +185,40 @@ AnimatorState:
|
|||||||
m_MirrorParameter:
|
m_MirrorParameter:
|
||||||
m_CycleOffsetParameter:
|
m_CycleOffsetParameter:
|
||||||
m_TimeParameter:
|
m_TimeParameter:
|
||||||
|
--- !u!1101 &-4328548395604843749
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions: []
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7908033645098541312}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.95
|
||||||
|
m_HasExitTime: 1
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!114 &-2635712880128095960
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
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: 372818b6c3ad2c3028f7411ec532d127, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Player.PlayerDownRecoverExitBehaviour
|
||||||
--- !u!1102 &-2487449162152911812
|
--- !u!1102 &-2487449162152911812
|
||||||
AnimatorState:
|
AnimatorState:
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
@@ -345,6 +435,18 @@ AnimatorController:
|
|||||||
m_DefaultInt: 0
|
m_DefaultInt: 0
|
||||||
m_DefaultBool: 0
|
m_DefaultBool: 0
|
||||||
m_Controller: {fileID: 9100000}
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Hit
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: HitSpeedMultiplier
|
||||||
|
m_Type: 1
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
m_AnimatorLayers:
|
m_AnimatorLayers:
|
||||||
- serializedVersion: 5
|
- serializedVersion: 5
|
||||||
m_Name: Base Layer
|
m_Name: Base Layer
|
||||||
@@ -421,7 +523,8 @@ AnimatorState:
|
|||||||
m_CycleOffset: 0
|
m_CycleOffset: 0
|
||||||
m_Transitions:
|
m_Transitions:
|
||||||
- {fileID: 1111345123456789022}
|
- {fileID: 1111345123456789022}
|
||||||
m_StateMachineBehaviours: []
|
m_StateMachineBehaviours:
|
||||||
|
- {fileID: 2761124885249802742}
|
||||||
m_Position: {x: 50, y: 50, z: 0}
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
m_IKOnFeet: 0
|
m_IKOnFeet: 0
|
||||||
m_WriteDefaultValues: 1
|
m_WriteDefaultValues: 1
|
||||||
@@ -475,7 +578,8 @@ AnimatorState:
|
|||||||
m_CycleOffset: 0
|
m_CycleOffset: 0
|
||||||
m_Transitions:
|
m_Transitions:
|
||||||
- {fileID: 1111345123456789024}
|
- {fileID: 1111345123456789024}
|
||||||
m_StateMachineBehaviours: []
|
m_StateMachineBehaviours:
|
||||||
|
- {fileID: -2635712880128095960}
|
||||||
m_Position: {x: 50, y: 50, z: 0}
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
m_IKOnFeet: 0
|
m_IKOnFeet: 0
|
||||||
m_WriteDefaultValues: 1
|
m_WriteDefaultValues: 1
|
||||||
@@ -584,6 +688,18 @@ AnimatorStateTransition:
|
|||||||
m_InterruptionSource: 0
|
m_InterruptionSource: 0
|
||||||
m_OrderedInterruption: 1
|
m_OrderedInterruption: 1
|
||||||
m_CanTransitionToSelf: 1
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!114 &2761124885249802742
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
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: 05c1f0fd1467993a7992e73162aebccc, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Player.PlayerDownBeginExitBehaviour
|
||||||
--- !u!1101 &3552691702041008167
|
--- !u!1101 &3552691702041008167
|
||||||
AnimatorStateTransition:
|
AnimatorStateTransition:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ MonoBehaviour:
|
|||||||
maxGemSlotCount: 0
|
maxGemSlotCount: 0
|
||||||
castStartEffects:
|
castStartEffects:
|
||||||
- {fileID: 11400000, guid: 9aff354899593121f89a55ada9ed27c8, type: 2}
|
- {fileID: 11400000, guid: 9aff354899593121f89a55ada9ed27c8, type: 2}
|
||||||
- {fileID: 11400000, guid: 3952a1b7ae34d1ee5b0b4bfc9faad041, type: 2}
|
- {fileID: 11400000, guid: 86d49ab180b62b395a64b1ba88045d97, type: 2}
|
||||||
triggeredEffects: []
|
triggeredEffects: []
|
||||||
isChanneling: 0
|
isChanneling: 0
|
||||||
channelDuration: 3
|
channelDuration: 3
|
||||||
|
|||||||
@@ -27,3 +27,5 @@ MonoBehaviour:
|
|||||||
force: 8
|
force: 8
|
||||||
upwardForce: 2
|
upwardForce: 2
|
||||||
duration: 0.25
|
duration: 0.25
|
||||||
|
playHitAnimation: 1
|
||||||
|
hitAnimationSpeedMultiplier: 1
|
||||||
|
|||||||
@@ -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: 675a8e51dce8ee00db904424ae5c8d9d, type: 3}
|
||||||
|
m_Name: "Data_SkillEffect_Drog_\uBC1C\uAD6C\uB974\uAE30_1_\uACBD\uC9C1"
|
||||||
|
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.StaggerEffect
|
||||||
|
targetType: 1
|
||||||
|
targetTeam: 0
|
||||||
|
areaCenter: 0
|
||||||
|
areaShape: 0
|
||||||
|
targetLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
includeCasterInArea: 0
|
||||||
|
areaRadius: 4.75
|
||||||
|
fanOriginDistance: 1
|
||||||
|
fanRadius: 4.75
|
||||||
|
fanHalfAngle: 180
|
||||||
|
duration: 0.35
|
||||||
|
playHitAnimation: 1
|
||||||
|
hitAnimationSpeedMultiplier: 1
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 86d49ab180b62b395a64b1ba88045d97
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -27,3 +27,5 @@ MonoBehaviour:
|
|||||||
force: 5
|
force: 5
|
||||||
upwardForce: 1
|
upwardForce: 1
|
||||||
duration: 0.18
|
duration: 0.18
|
||||||
|
playHitAnimation: 1
|
||||||
|
hitAnimationSpeedMultiplier: 1
|
||||||
|
|||||||
@@ -248,11 +248,11 @@ namespace Colosseum.Editor
|
|||||||
180f,
|
180f,
|
||||||
AreaCenterType.Caster);
|
AreaCenterType.Caster);
|
||||||
|
|
||||||
KnockbackEffect stompKnockback = CreateKnockbackEffect(
|
StaggerEffect stompStagger = CreateStaggerEffect(
|
||||||
$"{EffectsFolder}/Data_SkillEffect_Drog_발구르기_1_넉백.asset",
|
$"{EffectsFolder}/Data_SkillEffect_Drog_발구르기_1_경직.asset",
|
||||||
6f,
|
0.35f,
|
||||||
1.5f,
|
true,
|
||||||
0.2f,
|
1f,
|
||||||
AreaShapeType.Sphere,
|
AreaShapeType.Sphere,
|
||||||
4.75f,
|
4.75f,
|
||||||
1f,
|
1f,
|
||||||
@@ -277,6 +277,8 @@ namespace Colosseum.Editor
|
|||||||
8f,
|
8f,
|
||||||
2f,
|
2f,
|
||||||
0.25f,
|
0.25f,
|
||||||
|
true,
|
||||||
|
1f,
|
||||||
AreaShapeType.Sphere,
|
AreaShapeType.Sphere,
|
||||||
4.2f,
|
4.2f,
|
||||||
1f,
|
1f,
|
||||||
@@ -302,6 +304,8 @@ namespace Colosseum.Editor
|
|||||||
5f,
|
5f,
|
||||||
1f,
|
1f,
|
||||||
0.18f,
|
0.18f,
|
||||||
|
true,
|
||||||
|
1f,
|
||||||
AreaShapeType.Sphere,
|
AreaShapeType.Sphere,
|
||||||
2.8f,
|
2.8f,
|
||||||
1f,
|
1f,
|
||||||
@@ -513,7 +517,7 @@ namespace Colosseum.Editor
|
|||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
stompDamage,
|
stompDamage,
|
||||||
stompKnockback);
|
stompStagger);
|
||||||
|
|
||||||
SkillData leapPrepareSkill = CreateSkill(
|
SkillData leapPrepareSkill = CreateSkill(
|
||||||
$"{SkillsFolder}/Data_Skill_Drog_도약_준비.asset",
|
$"{SkillsFolder}/Data_Skill_Drog_도약_준비.asset",
|
||||||
@@ -1050,6 +1054,8 @@ namespace Colosseum.Editor
|
|||||||
float force,
|
float force,
|
||||||
float upwardForce,
|
float upwardForce,
|
||||||
float duration,
|
float duration,
|
||||||
|
bool playHitAnimation,
|
||||||
|
float hitAnimationSpeedMultiplier,
|
||||||
AreaShapeType areaShape,
|
AreaShapeType areaShape,
|
||||||
float areaRadius,
|
float areaRadius,
|
||||||
float fanOriginDistance,
|
float fanOriginDistance,
|
||||||
@@ -1064,6 +1070,36 @@ namespace Colosseum.Editor
|
|||||||
serializedObject.FindProperty("force").floatValue = force;
|
serializedObject.FindProperty("force").floatValue = force;
|
||||||
serializedObject.FindProperty("upwardForce").floatValue = upwardForce;
|
serializedObject.FindProperty("upwardForce").floatValue = upwardForce;
|
||||||
serializedObject.FindProperty("duration").floatValue = duration;
|
serializedObject.FindProperty("duration").floatValue = duration;
|
||||||
|
serializedObject.FindProperty("playHitAnimation").boolValue = playHitAnimation;
|
||||||
|
serializedObject.FindProperty("hitAnimationSpeedMultiplier").floatValue = hitAnimationSpeedMultiplier;
|
||||||
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||||||
|
|
||||||
|
EditorUtility.SetDirty(effect);
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 범위 경직 효과를 생성하거나 갱신합니다.
|
||||||
|
/// </summary>
|
||||||
|
private static StaggerEffect CreateStaggerEffect(
|
||||||
|
string path,
|
||||||
|
float duration,
|
||||||
|
bool playHitAnimation,
|
||||||
|
float hitAnimationSpeedMultiplier,
|
||||||
|
AreaShapeType areaShape,
|
||||||
|
float areaRadius,
|
||||||
|
float fanOriginDistance,
|
||||||
|
float fanRadius,
|
||||||
|
float fanHalfAngle,
|
||||||
|
AreaCenterType areaCenter)
|
||||||
|
{
|
||||||
|
StaggerEffect effect = LoadOrCreateAsset<StaggerEffect>(path);
|
||||||
|
SerializedObject serializedObject = new SerializedObject(effect);
|
||||||
|
|
||||||
|
ConfigureAreaEffect(serializedObject, areaShape, areaRadius, fanOriginDistance, fanRadius, fanHalfAngle, areaCenter);
|
||||||
|
serializedObject.FindProperty("duration").floatValue = duration;
|
||||||
|
serializedObject.FindProperty("playHitAnimation").boolValue = playHitAnimation;
|
||||||
|
serializedObject.FindProperty("hitAnimationSpeedMultiplier").floatValue = hitAnimationSpeedMultiplier;
|
||||||
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||||||
|
|
||||||
EditorUtility.SetDirty(effect);
|
EditorUtility.SetDirty(effect);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Colosseum.Player
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 플레이어의 피격 제어 상태를 관리합니다.
|
/// 플레이어의 피격 제어 상태를 관리합니다.
|
||||||
/// 넉백 강제 이동과 다운 상태, 피격 애니메이션 재생을 담당합니다.
|
/// 경직, 넉백, 다운 상태와 피격 애니메이션 재생을 담당합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
[RequireComponent(typeof(PlayerMovement))]
|
[RequireComponent(typeof(PlayerMovement))]
|
||||||
@@ -35,6 +35,9 @@ namespace Colosseum.Player
|
|||||||
[Tooltip("일반 피격 트리거 이름")]
|
[Tooltip("일반 피격 트리거 이름")]
|
||||||
[SerializeField] private string hitTriggerParam = "Hit";
|
[SerializeField] private string hitTriggerParam = "Hit";
|
||||||
|
|
||||||
|
[Tooltip("일반 피격 애니메이션 속도 배율 파라미터 이름")]
|
||||||
|
[SerializeField] private string hitSpeedMultiplierParam = "HitSpeedMultiplier";
|
||||||
|
|
||||||
[Tooltip("다운 시작 트리거 이름")]
|
[Tooltip("다운 시작 트리거 이름")]
|
||||||
[SerializeField] private string downTriggerParam = "Down";
|
[SerializeField] private string downTriggerParam = "Down";
|
||||||
|
|
||||||
@@ -42,21 +45,42 @@ namespace Colosseum.Player
|
|||||||
[SerializeField] private string recoverTriggerParam = "Recover";
|
[SerializeField] private string recoverTriggerParam = "Recover";
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
|
[Tooltip("DownBegin 종료 후 구르기 가능 구간까지 대기 시간")]
|
||||||
|
[Min(0f)] [SerializeField] private float downRecoverableDelayAfterBeginExit = 0.2f;
|
||||||
|
|
||||||
[Tooltip("애니메이션 파라미터가 없을 때 경고 로그 출력")]
|
[Tooltip("애니메이션 파라미터가 없을 때 경고 로그 출력")]
|
||||||
[SerializeField] private bool logMissingAnimationParams = false;
|
[SerializeField] private bool logMissingAnimationParams = false;
|
||||||
|
|
||||||
private readonly NetworkVariable<bool> isDowned = new NetworkVariable<bool>(false);
|
private readonly NetworkVariable<bool> isDowned = new NetworkVariable<bool>(false);
|
||||||
|
private readonly NetworkVariable<bool> isDownRecoverable = new NetworkVariable<bool>(false);
|
||||||
|
private readonly NetworkVariable<bool> isKnockbackActive = new NetworkVariable<bool>(false);
|
||||||
|
private readonly NetworkVariable<bool> isStaggered = new NetworkVariable<bool>(false);
|
||||||
|
|
||||||
private float downRemainingTime;
|
private float downRemainingTime;
|
||||||
|
private float downRecoverableDelayRemaining = -1f;
|
||||||
|
private float knockbackRemainingTime;
|
||||||
|
private float staggerRemainingTime;
|
||||||
|
private bool isDownRecoveryAnimating;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 다운 상태 여부
|
/// 다운 상태 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDowned => isDowned.Value;
|
public bool IsDowned => isDowned.Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 다운 중 구르기 가능 구간 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDownRecoverable => isDownRecoverable.Value;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 넉백 강제 이동 진행 여부
|
/// 넉백 강제 이동 진행 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsKnockbackActive => playerMovement != null && playerMovement.IsForcedMoving;
|
public bool IsKnockbackActive => isKnockbackActive.Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 경직 상태 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool IsStaggered => isStaggered.Value;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 피격 반응 무시 상태 여부
|
/// 피격 반응 무시 상태 여부
|
||||||
@@ -75,20 +99,18 @@ namespace Colosseum.Player
|
|||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (!IsServer || !isDowned.Value)
|
if (!IsServer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
downRemainingTime -= Time.deltaTime;
|
UpdateKnockbackState(Time.deltaTime);
|
||||||
if (downRemainingTime <= 0f)
|
UpdateStaggerState(Time.deltaTime);
|
||||||
{
|
UpdateDownState(Time.deltaTime);
|
||||||
RecoverFromDown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 넉백을 적용합니다.
|
/// 경직을 적용합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ApplyKnockback(Vector3 worldVelocity, float duration, bool playHitAnimation = true)
|
public void ApplyStagger(float duration, bool playHitAnimation = true, float hitAnimationSpeedMultiplier = 1f)
|
||||||
{
|
{
|
||||||
if (!IsServer)
|
if (!IsServer)
|
||||||
return;
|
return;
|
||||||
@@ -98,14 +120,56 @@ namespace Colosseum.Player
|
|||||||
if (networkController != null && networkController.IsDead)
|
if (networkController != null && networkController.IsDead)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (IsHitReactionImmune)
|
if (IsHitReactionImmune || isDowned.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (duration <= 0f)
|
||||||
|
{
|
||||||
|
ClearStaggerState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
staggerRemainingTime = Mathf.Max(staggerRemainingTime, duration);
|
||||||
|
isStaggered.Value = true;
|
||||||
|
skillController?.CancelSkill(SkillCancelReason.Stagger);
|
||||||
|
|
||||||
|
if (playHitAnimation)
|
||||||
|
{
|
||||||
|
TriggerAnimationRpc(hitTriggerParam, hitAnimationSpeedMultiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 넉백을 적용합니다.
|
||||||
|
/// </summary>
|
||||||
|
public void ApplyKnockback(Vector3 worldVelocity, float duration, bool playHitAnimation = true, float hitAnimationSpeedMultiplier = 1f)
|
||||||
|
{
|
||||||
|
if (!IsServer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ResolveReferences();
|
||||||
|
|
||||||
|
if (networkController != null && networkController.IsDead)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsHitReactionImmune || isDowned.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (duration <= 0f || worldVelocity.sqrMagnitude <= 0.0001f)
|
||||||
|
{
|
||||||
|
ClearKnockbackState();
|
||||||
|
playerMovement?.ClearForcedMovement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
knockbackRemainingTime = Mathf.Max(knockbackRemainingTime, duration);
|
||||||
|
isKnockbackActive.Value = true;
|
||||||
|
skillController?.CancelSkill(SkillCancelReason.HitReaction);
|
||||||
playerMovement?.ApplyForcedMovement(worldVelocity, duration);
|
playerMovement?.ApplyForcedMovement(worldVelocity, duration);
|
||||||
|
|
||||||
if (playHitAnimation)
|
if (playHitAnimation)
|
||||||
{
|
{
|
||||||
TriggerAnimationRpc(hitTriggerParam);
|
TriggerAnimationRpc(hitTriggerParam, hitAnimationSpeedMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,22 +195,48 @@ namespace Colosseum.Player
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
isDowned.Value = true;
|
isDowned.Value = true;
|
||||||
|
isDownRecoverable.Value = false;
|
||||||
|
isDownRecoveryAnimating = false;
|
||||||
|
downRecoverableDelayRemaining = -1f;
|
||||||
|
ClearKnockbackState();
|
||||||
|
ClearStaggerState();
|
||||||
skillController?.CancelSkill(SkillCancelReason.HitReaction);
|
skillController?.CancelSkill(SkillCancelReason.HitReaction);
|
||||||
playerMovement?.ClearForcedMovement();
|
playerMovement?.ClearForcedMovement();
|
||||||
TriggerAnimationRpc(downTriggerParam);
|
TriggerAnimationRpc(downTriggerParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 다운 상태를 해제합니다.
|
/// DownBegin 종료 시점을 전달받아 구르기 가능 타이머를 시작합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RecoverFromDown()
|
public void NotifyDownBeginExited()
|
||||||
{
|
{
|
||||||
if (!IsServer || !isDowned.Value)
|
if (!IsServer || !isDowned.Value || isDownRecoveryAnimating)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
isDowned.Value = false;
|
downRecoverableDelayRemaining = downRecoverableDelayAfterBeginExit;
|
||||||
downRemainingTime = 0f;
|
}
|
||||||
TriggerAnimationRpc(recoverTriggerParam);
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recover 상태가 끝났을 때 다운 상태를 최종 해제합니다.
|
||||||
|
/// </summary>
|
||||||
|
public void NotifyDownRecoverAnimationExited()
|
||||||
|
{
|
||||||
|
if (!IsServer || !isDowned.Value || !isDownRecoveryAnimating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ClearDownState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 다운 회복 가능 구간에서 구르기를 사용하며 다운 상태를 종료합니다.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryConsumeDownRecoverableEvade()
|
||||||
|
{
|
||||||
|
if (!IsServer || !isDowned.Value || !isDownRecoverable.Value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ClearDownState();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -160,12 +250,13 @@ namespace Colosseum.Player
|
|||||||
ResolveReferences();
|
ResolveReferences();
|
||||||
|
|
||||||
playerMovement?.ClearForcedMovement();
|
playerMovement?.ClearForcedMovement();
|
||||||
|
ClearKnockbackState();
|
||||||
|
ClearStaggerState();
|
||||||
|
|
||||||
if (!isDowned.Value)
|
if (!isDowned.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
isDowned.Value = false;
|
ClearDownState();
|
||||||
downRemainingTime = 0f;
|
|
||||||
|
|
||||||
if (playRecoverAnimation)
|
if (playRecoverAnimation)
|
||||||
{
|
{
|
||||||
@@ -174,13 +265,18 @@ namespace Colosseum.Player
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Rpc(SendTo.Everyone)]
|
[Rpc(SendTo.Everyone)]
|
||||||
private void TriggerAnimationRpc(string triggerName)
|
private void TriggerAnimationRpc(string triggerName, float hitAnimationSpeedMultiplier = 1f)
|
||||||
{
|
{
|
||||||
ResolveReferences();
|
ResolveReferences();
|
||||||
|
|
||||||
if (animator == null || string.IsNullOrWhiteSpace(triggerName))
|
if (animator == null || string.IsNullOrWhiteSpace(triggerName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (triggerName == hitTriggerParam)
|
||||||
|
{
|
||||||
|
SetFloatParameterIfExists(hitSpeedMultiplierParam, Mathf.Max(0.01f, hitAnimationSpeedMultiplier));
|
||||||
|
}
|
||||||
|
|
||||||
if (!HasTrigger(triggerName))
|
if (!HasTrigger(triggerName))
|
||||||
{
|
{
|
||||||
if (logMissingAnimationParams)
|
if (logMissingAnimationParams)
|
||||||
@@ -193,6 +289,27 @@ namespace Colosseum.Player
|
|||||||
animator.SetTrigger(triggerName);
|
animator.SetTrigger(triggerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetFloatParameterIfExists(string parameterName, float value)
|
||||||
|
{
|
||||||
|
if (animator == null || string.IsNullOrWhiteSpace(parameterName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < animator.parameterCount; i++)
|
||||||
|
{
|
||||||
|
AnimatorControllerParameter parameter = animator.GetParameter(i);
|
||||||
|
if (parameter.type == AnimatorControllerParameterType.Float && parameter.name == parameterName)
|
||||||
|
{
|
||||||
|
animator.SetFloat(parameterName, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logMissingAnimationParams)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[HitReaction] Animator float parameter not found: {parameterName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool HasTrigger(string triggerName)
|
private bool HasTrigger(string triggerName)
|
||||||
{
|
{
|
||||||
if (animator == null || string.IsNullOrWhiteSpace(triggerName))
|
if (animator == null || string.IsNullOrWhiteSpace(triggerName))
|
||||||
@@ -225,5 +342,92 @@ namespace Colosseum.Player
|
|||||||
if (animator == null)
|
if (animator == null)
|
||||||
animator = GetComponentInChildren<Animator>();
|
animator = GetComponentInChildren<Animator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateKnockbackState(float deltaTime)
|
||||||
|
{
|
||||||
|
if (!isKnockbackActive.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
knockbackRemainingTime -= deltaTime;
|
||||||
|
if (knockbackRemainingTime <= 0f)
|
||||||
|
{
|
||||||
|
ClearKnockbackState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateStaggerState(float deltaTime)
|
||||||
|
{
|
||||||
|
if (!isStaggered.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
staggerRemainingTime -= deltaTime;
|
||||||
|
if (staggerRemainingTime <= 0f)
|
||||||
|
{
|
||||||
|
ClearStaggerState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDownState(float deltaTime)
|
||||||
|
{
|
||||||
|
if (!isDowned.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
downRemainingTime -= deltaTime;
|
||||||
|
|
||||||
|
if (!isDownRecoverable.Value && downRecoverableDelayRemaining >= 0f)
|
||||||
|
{
|
||||||
|
downRecoverableDelayRemaining -= deltaTime;
|
||||||
|
if (downRecoverableDelayRemaining <= 0f)
|
||||||
|
{
|
||||||
|
EnterDownRecoverableState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downRemainingTime <= 0f)
|
||||||
|
{
|
||||||
|
BeginDownRecoveryAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnterDownRecoverableState()
|
||||||
|
{
|
||||||
|
if (!isDowned.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isDownRecoverable.Value = true;
|
||||||
|
downRecoverableDelayRemaining = -1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginDownRecoveryAnimation()
|
||||||
|
{
|
||||||
|
if (!isDowned.Value || isDownRecoveryAnimating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnterDownRecoverableState();
|
||||||
|
isDownRecoveryAnimating = true;
|
||||||
|
downRemainingTime = 0f;
|
||||||
|
TriggerAnimationRpc(recoverTriggerParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearDownState()
|
||||||
|
{
|
||||||
|
isDowned.Value = false;
|
||||||
|
isDownRecoverable.Value = false;
|
||||||
|
isDownRecoveryAnimating = false;
|
||||||
|
downRemainingTime = 0f;
|
||||||
|
downRecoverableDelayRemaining = -1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearKnockbackState()
|
||||||
|
{
|
||||||
|
isKnockbackActive.Value = false;
|
||||||
|
knockbackRemainingTime = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearStaggerState()
|
||||||
|
{
|
||||||
|
isStaggered.Value = false;
|
||||||
|
staggerRemainingTime = 0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ namespace Colosseum.Player
|
|||||||
GUILayout.Label($"사망 상태: {(networkController != null && networkController.IsDead ? "Dead" : "Alive")}");
|
GUILayout.Label($"사망 상태: {(networkController != null && networkController.IsDead ? "Dead" : "Alive")}");
|
||||||
if (TryGetComponent<PlayerActionState>(out var actionState))
|
if (TryGetComponent<PlayerActionState>(out var actionState))
|
||||||
{
|
{
|
||||||
GUILayout.Label($"무적:{(actionState.IsDamageImmune ? "On" : "Off")} / 다운:{(actionState.IsDowned ? "On" : "Off")} / 이동:{actionState.CanMove} / 스킬:{actionState.CanUseSkills}");
|
GUILayout.Label($"무적:{(actionState.IsDamageImmune ? "On" : "Off")} / 경직:{(actionState.IsStaggered ? "On" : "Off")} / 넉백:{(actionState.IsKnockbackActive ? "On" : "Off")} / 다운:{(actionState.IsDowned ? "On" : "Off")} / 다운회복:{(actionState.IsDownRecoverable ? "On" : "Off")}");
|
||||||
|
GUILayout.Label($"이동:{actionState.CanMove} / 스킬:{actionState.CanUseSkills} / 구르기:{actionState.CanEvade}");
|
||||||
}
|
}
|
||||||
GUILayout.Label("입력 예시: 기절 / Data_Abnormality_Player_Stun / 0");
|
GUILayout.Label("입력 예시: 기절 / Data_Abnormality_Player_Stun / 0");
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ namespace Colosseum.Player
|
|||||||
Verify("초기 상태: 사망 아님", !networkController.IsDead);
|
Verify("초기 상태: 사망 아님", !networkController.IsDead);
|
||||||
Verify("초기 상태: 이동 가능", actionState.CanMove);
|
Verify("초기 상태: 이동 가능", actionState.CanMove);
|
||||||
Verify("초기 상태: 스킬 사용 가능", actionState.CanUseSkills);
|
Verify("초기 상태: 스킬 사용 가능", actionState.CanUseSkills);
|
||||||
|
Verify("초기 상태: 구르기 가능", actionState.CanEvade);
|
||||||
Verify("초기 상태: 무적 상태 아님", !actionState.IsDamageImmune);
|
Verify("초기 상태: 무적 상태 아님", !actionState.IsDamageImmune);
|
||||||
Verify("초기 상태: 마지막 취소 이유 없음", skillController == null || skillController.LastCancelReason == SkillCancelReason.None);
|
Verify("초기 상태: 마지막 취소 이유 없음", skillController == null || skillController.LastCancelReason == SkillCancelReason.None);
|
||||||
|
|
||||||
@@ -331,6 +332,12 @@ namespace Colosseum.Player
|
|||||||
Vector3 knockbackVelocity = Vector3.back * 6f;
|
Vector3 knockbackVelocity = Vector3.back * 6f;
|
||||||
|
|
||||||
RequestKnockbackRpc(knockbackVelocity, 0.2f);
|
RequestKnockbackRpc(knockbackVelocity, 0.2f);
|
||||||
|
yield return new WaitForSeconds(0.05f);
|
||||||
|
|
||||||
|
Verify("넉백 적용: IsKnockbackActive", actionState.IsKnockbackActive);
|
||||||
|
Verify("넉백 적용: 스킬 사용 불가", !actionState.CanUseSkills);
|
||||||
|
Verify("넉백 적용: 구르기 불가", !actionState.CanEvade);
|
||||||
|
|
||||||
yield return new WaitForSeconds(0.3f);
|
yield return new WaitForSeconds(0.3f);
|
||||||
|
|
||||||
float movedDistance = Vector3.Distance(startPosition, transform.position);
|
float movedDistance = Vector3.Distance(startPosition, transform.position);
|
||||||
@@ -371,13 +378,32 @@ namespace Colosseum.Player
|
|||||||
Verify("다운 적용: 이동 불가", !actionState.CanMove);
|
Verify("다운 적용: 이동 불가", !actionState.CanMove);
|
||||||
Verify("다운 적용: 점프 불가", !actionState.CanJump);
|
Verify("다운 적용: 점프 불가", !actionState.CanJump);
|
||||||
Verify("다운 적용: 스킬 사용 불가", !actionState.CanUseSkills);
|
Verify("다운 적용: 스킬 사용 불가", !actionState.CanUseSkills);
|
||||||
|
Verify("다운 적용: 초기 구르기 불가", !actionState.CanEvade);
|
||||||
Verify("다운 적용: 이동속도 0", Mathf.Approximately(actionState.MoveSpeedMultiplier, 0f));
|
Verify("다운 적용: 이동속도 0", Mathf.Approximately(actionState.MoveSpeedMultiplier, 0f));
|
||||||
|
|
||||||
yield return WaitForConditionOrTimeout(() => !hitReactionController.IsDowned, 1.5f);
|
RequestDownBeginExitedRpc();
|
||||||
|
yield return WaitForConditionOrTimeout(() => hitReactionController.IsDownRecoverable, settleDelay + 1f);
|
||||||
|
|
||||||
|
Verify("다운 회복 가능 진입: IsDownRecoverable", hitReactionController.IsDownRecoverable);
|
||||||
|
Verify("다운 회복 가능 진입: 일반 스킬 사용 불가 유지", !actionState.CanUseSkills);
|
||||||
|
|
||||||
|
SkillData evadeSkill = skillInput != null ? skillInput.GetSkill(6) : null;
|
||||||
|
if (evadeSkill != null)
|
||||||
|
{
|
||||||
|
Verify("다운 회복 가능 진입: 구르기 시작 가능", actionState.CanStartSkill(evadeSkill));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppendLine("[SKIP] 다운 회복 가능 진입: 구르기 스킬이 없습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return WaitForConditionOrTimeout(() => !hitReactionController.IsDowned, 2.5f);
|
||||||
|
|
||||||
Verify("다운 해제: IsDowned false", !hitReactionController.IsDowned);
|
Verify("다운 해제: IsDowned false", !hitReactionController.IsDowned);
|
||||||
|
Verify("다운 해제: IsDownRecoverable false", !hitReactionController.IsDownRecoverable);
|
||||||
Verify("다운 해제: 이동 가능 복구", actionState.CanMove);
|
Verify("다운 해제: 이동 가능 복구", actionState.CanMove);
|
||||||
Verify("다운 해제: 스킬 사용 가능 복구", actionState.CanUseSkills);
|
Verify("다운 해제: 스킬 사용 가능 복구", actionState.CanUseSkills);
|
||||||
|
Verify("다운 해제: 구르기 가능 복구", actionState.CanEvade);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Rpc(SendTo.Server)]
|
[Rpc(SendTo.Server)]
|
||||||
@@ -386,6 +412,12 @@ namespace Colosseum.Player
|
|||||||
hitReactionController?.ApplyDown(duration);
|
hitReactionController?.ApplyDown(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Rpc(SendTo.Server)]
|
||||||
|
private void RequestDownBeginExitedRpc()
|
||||||
|
{
|
||||||
|
hitReactionController?.NotifyDownBeginExited();
|
||||||
|
}
|
||||||
|
|
||||||
[Rpc(SendTo.Server)]
|
[Rpc(SendTo.Server)]
|
||||||
private void RequestKnockbackRpc(Vector3 velocity, float duration)
|
private void RequestKnockbackRpc(Vector3 velocity, float duration)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,11 +38,26 @@ namespace Colosseum.Player
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsStunned => abnormalityManager != null && abnormalityManager.IsStunned;
|
public bool IsStunned => abnormalityManager != null && abnormalityManager.IsStunned;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 경직 상태 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool IsStaggered => hitReactionController != null && hitReactionController.IsStaggered;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 넉백 상태 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool IsKnockbackActive => hitReactionController != null && hitReactionController.IsKnockbackActive;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 다운 상태 여부
|
/// 다운 상태 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDowned => hitReactionController != null && hitReactionController.IsDowned;
|
public bool IsDowned => hitReactionController != null && hitReactionController.IsDowned;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 다운 중 구르기 가능 구간 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDownRecoverable => hitReactionController != null && hitReactionController.IsDownRecoverable;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 침묵 상태 여부
|
/// 침묵 상태 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -76,17 +91,28 @@ namespace Colosseum.Player
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 플레이어가 직접 이동 입력을 사용할 수 있는지 여부
|
/// 플레이어가 직접 이동 입력을 사용할 수 있는지 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanMove => CanReceiveInput && !IsStunned && !IsDowned && !BlocksMovementForCurrentSkill();
|
public bool CanMove => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsDowned && !BlocksMovementForCurrentSkill();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 점프 가능 여부
|
/// 점프 가능 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanJump => CanReceiveInput && !IsStunned && !IsDowned && !BlocksJumpForCurrentSkill();
|
public bool CanJump => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsDowned && !BlocksJumpForCurrentSkill();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 일반 스킬 시작 가능 여부
|
/// 일반 스킬 시작 가능 여부
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanUseSkills => CanReceiveInput && !IsStunned && !IsDowned && !IsSilenced && !BlocksSkillUseForCurrentSkill();
|
public bool CanUseSkills => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsDowned && !IsSilenced && !BlocksSkillUseForCurrentSkill();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 회피 스킬 시작 가능 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool CanEvade => CanReceiveInput
|
||||||
|
&& !IsStunned
|
||||||
|
&& !IsStaggered
|
||||||
|
&& !IsKnockbackActive
|
||||||
|
&& !IsSilenced
|
||||||
|
&& (!IsDowned || IsDownRecoverable)
|
||||||
|
&& !BlocksSkillUseForCurrentSkill();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 특정 스킬의 시작 가능 여부.
|
/// 특정 스킬의 시작 가능 여부.
|
||||||
@@ -97,9 +123,15 @@ namespace Colosseum.Player
|
|||||||
if (skill == null)
|
if (skill == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CanReceiveInput || IsStunned || IsDowned || IsSilenced)
|
if (!CanReceiveInput || IsStunned || IsStaggered || IsKnockbackActive || IsSilenced)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (IsDowned)
|
||||||
|
{
|
||||||
|
if (!IsDownRecoverable || !skill.IsEvadeSkill)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return !BlocksSkillUseForCurrentSkill();
|
return !BlocksSkillUseForCurrentSkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +142,7 @@ namespace Colosseum.Player
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!CanReceiveInput || IsStunned || IsDowned)
|
if (!CanReceiveInput || IsStunned || IsStaggered || IsKnockbackActive || IsDowned)
|
||||||
return 0f;
|
return 0f;
|
||||||
|
|
||||||
return abnormalityManager != null ? abnormalityManager.MoveSpeedMultiplier : 1f;
|
return abnormalityManager != null ? abnormalityManager.MoveSpeedMultiplier : 1f;
|
||||||
|
|||||||
19
Assets/_Game/Scripts/Player/PlayerDownBeginExitBehaviour.cs
Normal file
19
Assets/_Game/Scripts/Player/PlayerDownBeginExitBehaviour.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Colosseum.Player
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DownBegin 상태 종료를 HitReactionController에 전달합니다.
|
||||||
|
/// </summary>
|
||||||
|
public class PlayerDownBeginExitBehaviour : StateMachineBehaviour
|
||||||
|
{
|
||||||
|
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||||
|
{
|
||||||
|
if (animator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HitReactionController hitReactionController = animator.GetComponentInParent<HitReactionController>();
|
||||||
|
hitReactionController?.NotifyDownBeginExited();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 05c1f0fd1467993a7992e73162aebccc
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Colosseum.Player
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Recover 상태 종료를 HitReactionController에 전달합니다.
|
||||||
|
/// </summary>
|
||||||
|
public class PlayerDownRecoverExitBehaviour : StateMachineBehaviour
|
||||||
|
{
|
||||||
|
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||||
|
{
|
||||||
|
if (animator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HitReactionController hitReactionController = animator.GetComponentInParent<HitReactionController>();
|
||||||
|
hitReactionController?.NotifyDownRecoverAnimationExited();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 372818b6c3ad2c3028f7411ec532d127
|
||||||
@@ -15,6 +15,13 @@ namespace Colosseum.Skills.Effects
|
|||||||
[SerializeField] private float upwardForce = 2f;
|
[SerializeField] private float upwardForce = 2f;
|
||||||
[Min(0.05f)] [SerializeField] private float duration = 0.2f;
|
[Min(0.05f)] [SerializeField] private float duration = 0.2f;
|
||||||
|
|
||||||
|
[Header("Hit Animation")]
|
||||||
|
[Tooltip("넉백 적용 시 경직 애니메이션 재생 여부")]
|
||||||
|
[SerializeField] private bool playHitAnimation = true;
|
||||||
|
|
||||||
|
[Tooltip("경직 애니메이션 재생 속도 배율")]
|
||||||
|
[Min(0.01f)] [SerializeField] private float hitAnimationSpeedMultiplier = 1f;
|
||||||
|
|
||||||
protected override void ApplyEffect(GameObject caster, GameObject target)
|
protected override void ApplyEffect(GameObject caster, GameObject target)
|
||||||
{
|
{
|
||||||
if (target == null || caster == null) return;
|
if (target == null || caster == null) return;
|
||||||
@@ -34,7 +41,7 @@ namespace Colosseum.Skills.Effects
|
|||||||
|
|
||||||
if (hitReactionController != null)
|
if (hitReactionController != null)
|
||||||
{
|
{
|
||||||
hitReactionController.ApplyKnockback(knockbackVelocity, duration);
|
hitReactionController.ApplyKnockback(knockbackVelocity, duration, playHitAnimation, hitAnimationSpeedMultiplier);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
Assets/_Game/Scripts/Skills/Effects/StaggerEffect.cs
Normal file
44
Assets/_Game/Scripts/Skills/Effects/StaggerEffect.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Colosseum.Player;
|
||||||
|
|
||||||
|
namespace Colosseum.Skills.Effects
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 대상에게 제자리 경직을 적용하는 스킬 효과입니다.
|
||||||
|
/// </summary>
|
||||||
|
[CreateAssetMenu(fileName = "StaggerEffect", menuName = "Colosseum/Skills/Effects/Stagger")]
|
||||||
|
public class StaggerEffect : SkillEffect
|
||||||
|
{
|
||||||
|
[Header("Settings")]
|
||||||
|
[Tooltip("경직 지속 시간")]
|
||||||
|
[Min(0f)] [SerializeField] private float duration = 0.35f;
|
||||||
|
|
||||||
|
[Tooltip("경직 적용 시 피격 애니메이션 재생 여부")]
|
||||||
|
[SerializeField] private bool playHitAnimation = true;
|
||||||
|
|
||||||
|
[Tooltip("경직 애니메이션 재생 속도 배율")]
|
||||||
|
[Min(0.01f)] [SerializeField] private float hitAnimationSpeedMultiplier = 1f;
|
||||||
|
|
||||||
|
protected override void ApplyEffect(GameObject caster, GameObject target)
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[StaggerEffect] Target is null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HitReactionController hitReactionController = target.GetComponent<HitReactionController>();
|
||||||
|
if (hitReactionController == null)
|
||||||
|
hitReactionController = target.GetComponentInParent<HitReactionController>();
|
||||||
|
|
||||||
|
if (hitReactionController == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[StaggerEffect] HitReactionController not found on target: {target.name}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hitReactionController.ApplyStagger(duration, playHitAnimation, hitAnimationSpeedMultiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 675a8e51dce8ee00db904424ae5c8d9d
|
||||||
@@ -6,6 +6,7 @@ using UnityEngine;
|
|||||||
using Unity.Netcode;
|
using Unity.Netcode;
|
||||||
|
|
||||||
using Colosseum.Abnormalities;
|
using Colosseum.Abnormalities;
|
||||||
|
using Colosseum.Player;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
@@ -23,6 +24,7 @@ namespace Colosseum.Skills
|
|||||||
Interrupt,
|
Interrupt,
|
||||||
Death,
|
Death,
|
||||||
Stun,
|
Stun,
|
||||||
|
Stagger,
|
||||||
HitReaction,
|
HitReaction,
|
||||||
Respawn,
|
Respawn,
|
||||||
Revive,
|
Revive,
|
||||||
@@ -361,6 +363,12 @@ namespace Colosseum.Skills
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skill.IsEvadeSkill)
|
||||||
|
{
|
||||||
|
HitReactionController hitReactionController = GetComponent<HitReactionController>();
|
||||||
|
hitReactionController?.TryConsumeDownRecoverableEvade();
|
||||||
|
}
|
||||||
|
|
||||||
currentLoadoutEntry = loadoutEntry != null ? loadoutEntry.CreateCopy() : SkillLoadoutEntry.CreateTemporary(skill);
|
currentLoadoutEntry = loadoutEntry != null ? loadoutEntry.CreateCopy() : SkillLoadoutEntry.CreateTemporary(skill);
|
||||||
currentSkill = skill;
|
currentSkill = skill;
|
||||||
lastCancelReason = SkillCancelReason.None;
|
lastCancelReason = SkillCancelReason.None;
|
||||||
|
|||||||
@@ -245,6 +245,8 @@ namespace Colosseum.Skills
|
|||||||
public SkillRoleType SkillRole => skillRole;
|
public SkillRoleType SkillRole => skillRole;
|
||||||
public SkillActivationType ActivationType => activationType;
|
public SkillActivationType ActivationType => activationType;
|
||||||
public SkillBaseType BaseTypes => baseTypes;
|
public SkillBaseType BaseTypes => baseTypes;
|
||||||
|
public bool IsEvadeSkill => ((baseTypes & SkillBaseType.Mobility) != 0)
|
||||||
|
&& (ContainsEvadeKeyword(skillName) || ContainsEvadeKeyword(name));
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 순차 재생할 클립 목록입니다.
|
/// 순차 재생할 클립 목록입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -307,6 +309,15 @@ namespace Colosseum.Skills
|
|||||||
|
|
||||||
return (equippedTraits & allowedWeaponTraits) == allowedWeaponTraits;
|
return (equippedTraits & allowedWeaponTraits) == allowedWeaponTraits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool ContainsEvadeKeyword(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return value.IndexOf("구르기", StringComparison.OrdinalIgnoreCase) >= 0
|
||||||
|
|| value.IndexOf("회피", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
8
Assets/_Game/Tests/PlayMode.meta
Normal file
8
Assets/_Game/Tests/PlayMode.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f666991c90023e380b39b439b8407864
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
23
Assets/_Game/Tests/PlayMode/Colosseum.Tests.PlayMode.asmdef
Normal file
23
Assets/_Game/Tests/PlayMode/Colosseum.Tests.PlayMode.asmdef
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "Colosseum.Tests.PlayMode",
|
||||||
|
"rootNamespace": "Colosseum.Tests",
|
||||||
|
"references": [
|
||||||
|
"Colosseum.Game",
|
||||||
|
"Unity.Netcode.Runtime",
|
||||||
|
"Unity.Networking.Transport"
|
||||||
|
],
|
||||||
|
"optionalUnityReferences": [
|
||||||
|
"TestAssemblies"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": true,
|
||||||
|
"precompiledReferences": [
|
||||||
|
"nunit.framework.dll"
|
||||||
|
],
|
||||||
|
"autoReferenced": false,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a28b72c4fca3e56d7a3e149189f1c976
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
191
Assets/_Game/Tests/PlayMode/HitReactionAnimationSpeedTests.cs
Normal file
191
Assets/_Game/Tests/PlayMode/HitReactionAnimationSpeedTests.cs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
using Unity.Netcode;
|
||||||
|
using Unity.Netcode.Transports.UTP;
|
||||||
|
|
||||||
|
using Colosseum.Player;
|
||||||
|
|
||||||
|
namespace Colosseum.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 피격 반응 애니메이션의 속도 배율 반영을 검증하는 PlayMode 테스트입니다.
|
||||||
|
/// </summary>
|
||||||
|
public class HitReactionAnimationSpeedTests
|
||||||
|
{
|
||||||
|
private const string AnimatorControllerResourcePath = "AC_Player_Default_PlayModeTest";
|
||||||
|
private const string HitStateName = "Hit";
|
||||||
|
private const string HitSpeedMultiplierParam = "HitSpeedMultiplier";
|
||||||
|
private const float AnimationSampleWindow = 0.08f;
|
||||||
|
|
||||||
|
private GameObject networkManagerObject;
|
||||||
|
private NetworkManager networkManager;
|
||||||
|
private GameObject playerObject;
|
||||||
|
private HitReactionController hitReactionController;
|
||||||
|
private Animator animator;
|
||||||
|
|
||||||
|
[UnitySetUp]
|
||||||
|
public IEnumerator SetUp()
|
||||||
|
{
|
||||||
|
CleanupTestObjects();
|
||||||
|
|
||||||
|
networkManagerObject = new GameObject("TestNetworkManager");
|
||||||
|
networkManager = networkManagerObject.AddComponent<NetworkManager>();
|
||||||
|
|
||||||
|
UnityTransport transport = networkManagerObject.AddComponent<UnityTransport>();
|
||||||
|
transport.SetConnectionData("127.0.0.1", AllocateTestPort());
|
||||||
|
|
||||||
|
networkManager.NetworkConfig = new NetworkConfig
|
||||||
|
{
|
||||||
|
NetworkTransport = transport,
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.IsTrue(networkManager.StartHost(), "테스트용 호스트 시작에 실패했습니다.");
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
RuntimeAnimatorController controller = Resources.Load<RuntimeAnimatorController>(AnimatorControllerResourcePath);
|
||||||
|
Assert.NotNull(controller, $"테스트용 AnimatorController를 찾을 수 없습니다: Resources/{AnimatorControllerResourcePath}");
|
||||||
|
|
||||||
|
playerObject = new GameObject("HitReactionTestPlayer");
|
||||||
|
playerObject.SetActive(false);
|
||||||
|
playerObject.transform.position = Vector3.zero;
|
||||||
|
|
||||||
|
playerObject.AddComponent<NetworkObject>();
|
||||||
|
hitReactionController = playerObject.AddComponent<HitReactionController>();
|
||||||
|
|
||||||
|
GameObject visualObject = new GameObject("Visual");
|
||||||
|
visualObject.transform.SetParent(playerObject.transform, false);
|
||||||
|
|
||||||
|
animator = visualObject.AddComponent<Animator>();
|
||||||
|
animator.runtimeAnimatorController = controller;
|
||||||
|
animator.applyRootMotion = false;
|
||||||
|
|
||||||
|
playerObject.SetActive(true);
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
NetworkObject networkObject = playerObject.GetComponent<NetworkObject>();
|
||||||
|
networkObject.SpawnWithOwnership(networkManager.LocalClientId);
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
Assert.NotNull(hitReactionController, "HitReactionController를 생성하지 못했습니다.");
|
||||||
|
Assert.NotNull(animator, "테스트용 Animator를 생성하지 못했습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTearDown]
|
||||||
|
public IEnumerator TearDown()
|
||||||
|
{
|
||||||
|
if (networkManager != null && networkManager.IsListening)
|
||||||
|
{
|
||||||
|
networkManager.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
CleanupTestObjects();
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ApplyStagger_ReusesHitAnimationAndReflectsSpeedMultiplier()
|
||||||
|
{
|
||||||
|
float slowDelta = 0f;
|
||||||
|
yield return MeasureHitPlaybackDelta(
|
||||||
|
() => hitReactionController.ApplyStagger(0.4f, true, 0.5f),
|
||||||
|
0.5f,
|
||||||
|
value => slowDelta = value);
|
||||||
|
|
||||||
|
float fastDelta = 0f;
|
||||||
|
yield return MeasureHitPlaybackDelta(
|
||||||
|
() => hitReactionController.ApplyStagger(0.4f, true, 2f),
|
||||||
|
2f,
|
||||||
|
value => fastDelta = value);
|
||||||
|
|
||||||
|
Assert.Greater(slowDelta, 0.01f, "느린 경직 재생에서 normalizedTime이 전진하지 않았습니다.");
|
||||||
|
Assert.Greater(fastDelta, slowDelta * 1.75f, $"빠른 경직 재생 전진량이 충분하지 않습니다. slow={slowDelta:F3}, fast={fastDelta:F3}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ApplyKnockback_AlsoAppliesHitAnimationSpeedMultiplier()
|
||||||
|
{
|
||||||
|
float measuredDelta = 0f;
|
||||||
|
yield return MeasureHitPlaybackDelta(
|
||||||
|
() => hitReactionController.ApplyKnockback(Vector3.back * 3f, 0.25f, true, 1.6f),
|
||||||
|
1.6f,
|
||||||
|
value => measuredDelta = value);
|
||||||
|
|
||||||
|
Assert.Greater(measuredDelta, 0.01f, "넉백에서 Hit 애니메이션이 재생되지 않았습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator MeasureHitPlaybackDelta(System.Action applyReaction, float expectedSpeedMultiplier, System.Action<float> setMeasuredDelta)
|
||||||
|
{
|
||||||
|
hitReactionController.ClearHitReactionState();
|
||||||
|
animator.Rebind();
|
||||||
|
animator.Update(0f);
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
applyReaction.Invoke();
|
||||||
|
yield return WaitForHitState();
|
||||||
|
|
||||||
|
float actualMultiplier = animator.GetFloat(HitSpeedMultiplierParam);
|
||||||
|
Assert.AreEqual(expectedSpeedMultiplier, actualMultiplier, 0.01f, "Hit 속도 배율 파라미터가 기대값과 다릅니다.");
|
||||||
|
|
||||||
|
float startNormalizedTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
|
||||||
|
yield return new WaitForSeconds(AnimationSampleWindow);
|
||||||
|
float endNormalizedTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
|
||||||
|
|
||||||
|
setMeasuredDelta(endNormalizedTime - startNormalizedTime);
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator WaitForHitState()
|
||||||
|
{
|
||||||
|
int hitStateHash = Animator.StringToHash(HitStateName);
|
||||||
|
|
||||||
|
for (int frame = 0; frame < 120; frame++)
|
||||||
|
{
|
||||||
|
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||||||
|
if (!animator.IsInTransition(0) && stateInfo.shortNameHash == hitStateHash)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail("Hit 상태 진입을 시간 내에 확인하지 못했습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ushort AllocateTestPort()
|
||||||
|
{
|
||||||
|
return (ushort)Random.Range(20000, 40000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanupTestObjects()
|
||||||
|
{
|
||||||
|
if (playerObject != null)
|
||||||
|
{
|
||||||
|
Object.DestroyImmediate(playerObject);
|
||||||
|
playerObject = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Camera camera in Object.FindObjectsByType<Camera>(FindObjectsSortMode.None))
|
||||||
|
{
|
||||||
|
if (camera != null && camera.gameObject.name == "PlayerCamera")
|
||||||
|
{
|
||||||
|
Object.DestroyImmediate(camera.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkManagerObject != null)
|
||||||
|
{
|
||||||
|
Object.DestroyImmediate(networkManagerObject);
|
||||||
|
networkManagerObject = null;
|
||||||
|
networkManager = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9ad1b0615e5d4a13da258e727d9ef00a
|
||||||
8
Assets/_Game/Tests/PlayMode/Resources.meta
Normal file
8
Assets/_Game/Tests/PlayMode/Resources.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 16e8a9b532e7b9d9ea9323e4c1f668c3
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,804 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1102 &-7908033645098541312
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Idle
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: 3552691702041008167}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: ebc8e8e59d375104babccd596aa3bdc0, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &-7325123755187262477
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Hit
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: -4328548395604843749}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 1
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: -4467167322993697325, guid: 575336e929435dc4398adefbfa9cde78, type: 3}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter: HitSpeedMultiplier
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1101 &-5485275494767118128
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions: []
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7908033645098541312}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0
|
||||||
|
m_HasExitTime: 1
|
||||||
|
m_HasFixedDuration: 0
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1107 &-5279407469294999195
|
||||||
|
AnimatorStateMachine:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Base Layer
|
||||||
|
m_ChildStates:
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -7908033645098541312}
|
||||||
|
m_Position: {x: 30, y: 180, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -585817098472771744}
|
||||||
|
m_Position: {x: 30, y: 270, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -4652545120162758660}
|
||||||
|
m_Position: {x: 290, y: 180, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: 7693173606830535998}
|
||||||
|
m_Position: {x: -210, y: 180, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: 580927713284550422}
|
||||||
|
m_Position: {x: 30, y: 350, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -2487449162152911812}
|
||||||
|
m_Position: {x: -210, y: 350, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -1032254959699123210}
|
||||||
|
m_Position: {x: -450, y: 270, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: 1111345123456789012}
|
||||||
|
m_Position: {x: -700, y: 140, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: 1111345123456789013}
|
||||||
|
m_Position: {x: -980, y: 140, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: 1111345123456789014}
|
||||||
|
m_Position: {x: -1260, y: 140, z: 0}
|
||||||
|
- serializedVersion: 1
|
||||||
|
m_State: {fileID: -7325123755187262477}
|
||||||
|
m_Position: {x: -450, y: 60, z: 0}
|
||||||
|
m_ChildStateMachines: []
|
||||||
|
m_AnyStateTransitions:
|
||||||
|
- {fileID: -754003289131015157}
|
||||||
|
- {fileID: 469741948129995159}
|
||||||
|
- {fileID: 6228136561094308872}
|
||||||
|
- {fileID: 1111345123456789021}
|
||||||
|
- {fileID: -4832749926410887626}
|
||||||
|
m_EntryTransitions: []
|
||||||
|
m_StateMachineTransitions: {}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_AnyStatePosition: {x: -190, y: 270, z: 0}
|
||||||
|
m_EntryPosition: {x: 50, y: 120, z: 0}
|
||||||
|
m_ExitPosition: {x: 280, y: 270, z: 0}
|
||||||
|
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||||
|
m_DefaultState: {fileID: -7908033645098541312}
|
||||||
|
--- !u!1101 &-4832749926410887626
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Hit
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7325123755187262477}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.75
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1102 &-4652545120162758660
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Move
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: 8997152603305261974}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: -1886843759694807048}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1101 &-4328548395604843749
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions: []
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7908033645098541312}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.95
|
||||||
|
m_HasExitTime: 1
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!114 &-2635712880128095960
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
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: 372818b6c3ad2c3028f7411ec532d127, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Player.PlayerDownRecoverExitBehaviour
|
||||||
|
--- !u!1102 &-2487449162152911812
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Skill
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions: []
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 0a0bccbcb0672f948a287f14df7b9494, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!206 &-1886843759694807048
|
||||||
|
BlendTree:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Blend Tree
|
||||||
|
m_Childs:
|
||||||
|
- serializedVersion: 2
|
||||||
|
m_Motion: {fileID: 4441030841997727119, guid: 005ddab128d7eb141b25099c0eb1ed39, type: 3}
|
||||||
|
m_Threshold: 0
|
||||||
|
m_Position: {x: 0, y: 0}
|
||||||
|
m_TimeScale: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_DirectBlendParameter: Speed
|
||||||
|
m_Mirror: 0
|
||||||
|
- serializedVersion: 2
|
||||||
|
m_Motion: {fileID: 2571081563578608591, guid: e6a2aa1552aac6f46b40192ec605d57e, type: 3}
|
||||||
|
m_Threshold: 0.5
|
||||||
|
m_Position: {x: 0, y: 0}
|
||||||
|
m_TimeScale: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_DirectBlendParameter: Speed
|
||||||
|
m_Mirror: 0
|
||||||
|
- serializedVersion: 2
|
||||||
|
m_Motion: {fileID: 1827226128182048838, guid: 60fb511bc6259b745b432aea6a222303, type: 3}
|
||||||
|
m_Threshold: 1
|
||||||
|
m_Position: {x: 0, y: 0}
|
||||||
|
m_TimeScale: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_DirectBlendParameter: Speed
|
||||||
|
m_Mirror: 0
|
||||||
|
m_BlendParameter: Speed
|
||||||
|
m_BlendParameterY: Speed
|
||||||
|
m_MinThreshold: 0
|
||||||
|
m_MaxThreshold: 1
|
||||||
|
m_UseAutomaticThresholds: 1
|
||||||
|
m_NormalizedBlendValues: 0
|
||||||
|
m_BlendType: 0
|
||||||
|
--- !u!1102 &-1032254959699123210
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Die
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions: []
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 0063c4809c39f4a4fab4118d94af905a, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1101 &-754003289131015157
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Jump
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -585817098472771744}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.25
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.75
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1101 &-711300537235094109
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions: []
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: 580927713284550422}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.25
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.423077
|
||||||
|
m_HasExitTime: 1
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1102 &-585817098472771744
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Jump
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: -711300537235094109}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 1ec316f7bc59114438737162c529e859, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!91 &9100000
|
||||||
|
AnimatorController:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: AC_Player_Default
|
||||||
|
serializedVersion: 5
|
||||||
|
m_AnimatorParameters:
|
||||||
|
- m_Name: Speed
|
||||||
|
m_Type: 1
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: IsGrounded
|
||||||
|
m_Type: 4
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Jump
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Land
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Die
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Down
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Recover
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: Hit
|
||||||
|
m_Type: 9
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
- m_Name: HitSpeedMultiplier
|
||||||
|
m_Type: 1
|
||||||
|
m_DefaultFloat: 0
|
||||||
|
m_DefaultInt: 0
|
||||||
|
m_DefaultBool: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
m_AnimatorLayers:
|
||||||
|
- serializedVersion: 5
|
||||||
|
m_Name: Base Layer
|
||||||
|
m_StateMachine: {fileID: -5279407469294999195}
|
||||||
|
m_Mask: {fileID: 0}
|
||||||
|
m_Motions: []
|
||||||
|
m_Behaviours: []
|
||||||
|
m_BlendingMode: 0
|
||||||
|
m_SyncedLayerIndex: -1
|
||||||
|
m_DefaultWeight: 0
|
||||||
|
m_IKPass: 0
|
||||||
|
m_SyncedLayerAffectsTiming: 0
|
||||||
|
m_Controller: {fileID: 9100000}
|
||||||
|
--- !u!1101 &469741948129995159
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Land
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: 7693173606830535998}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.25
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.75
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1102 &580927713284550422
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: InAir
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions: []
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 92048c8715663824db12edf9e8f37b1a, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &1111345123456789012
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: DownBegin
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: 1111345123456789022}
|
||||||
|
m_StateMachineBehaviours:
|
||||||
|
- {fileID: 2761124885249802742}
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: ca8cea0da5fabb74d9e4f0d4b31262a1, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &1111345123456789013
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: DownLoop
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: 1111345123456789023}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 1a78e440e35d67c4bb4cf734a52e003a, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1102 &1111345123456789014
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Recover
|
||||||
|
m_Speed: 1
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: 1111345123456789024}
|
||||||
|
m_StateMachineBehaviours:
|
||||||
|
- {fileID: -2635712880128095960}
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: fce016eeacf5d20478d6d1a799f93c8f, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1101 &1111345123456789021
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Down
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: 1111345123456789012}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1101 &1111345123456789022
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions: []
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: 1111345123456789013}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.95
|
||||||
|
m_HasExitTime: 1
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1101 &1111345123456789023
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Recover
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: 1111345123456789014}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.05
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1101 &1111345123456789024
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions: []
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7908033645098541312}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.1
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.95
|
||||||
|
m_HasExitTime: 1
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!114 &2761124885249802742
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
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: 05c1f0fd1467993a7992e73162aebccc, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Player.PlayerDownBeginExitBehaviour
|
||||||
|
--- !u!1101 &3552691702041008167
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 3
|
||||||
|
m_ConditionEvent: Speed
|
||||||
|
m_EventTreshold: 0.01
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -4652545120162758660}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.25
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.75
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1101 &6228136561094308872
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 1
|
||||||
|
m_ConditionEvent: Die
|
||||||
|
m_EventTreshold: 0
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -1032254959699123210}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.25
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.75
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 1
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
|
--- !u!1102 &7693173606830535998
|
||||||
|
AnimatorState:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: Land
|
||||||
|
m_Speed: 3
|
||||||
|
m_CycleOffset: 0
|
||||||
|
m_Transitions:
|
||||||
|
- {fileID: -5485275494767118128}
|
||||||
|
m_StateMachineBehaviours: []
|
||||||
|
m_Position: {x: 50, y: 50, z: 0}
|
||||||
|
m_IKOnFeet: 0
|
||||||
|
m_WriteDefaultValues: 1
|
||||||
|
m_Mirror: 0
|
||||||
|
m_SpeedParameterActive: 0
|
||||||
|
m_MirrorParameterActive: 0
|
||||||
|
m_CycleOffsetParameterActive: 0
|
||||||
|
m_TimeParameterActive: 0
|
||||||
|
m_Motion: {fileID: 7400000, guid: 1ec316f7bc59114438737162c529e859, type: 2}
|
||||||
|
m_Tag:
|
||||||
|
m_SpeedParameter:
|
||||||
|
m_MirrorParameter:
|
||||||
|
m_CycleOffsetParameter:
|
||||||
|
m_TimeParameter:
|
||||||
|
--- !u!1101 &8997152603305261974
|
||||||
|
AnimatorStateTransition:
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name:
|
||||||
|
m_Conditions:
|
||||||
|
- m_ConditionMode: 4
|
||||||
|
m_ConditionEvent: Speed
|
||||||
|
m_EventTreshold: 0.03
|
||||||
|
m_DstStateMachine: {fileID: 0}
|
||||||
|
m_DstState: {fileID: -7908033645098541312}
|
||||||
|
m_Solo: 0
|
||||||
|
m_Mute: 0
|
||||||
|
m_IsExit: 0
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransitionDuration: 0.1
|
||||||
|
m_TransitionOffset: 0
|
||||||
|
m_ExitTime: 0.9977373
|
||||||
|
m_HasExitTime: 0
|
||||||
|
m_HasFixedDuration: 0
|
||||||
|
m_InterruptionSource: 0
|
||||||
|
m_OrderedInterruption: 1
|
||||||
|
m_CanTransitionToSelf: 1
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b6700e3b25d1cc5fc83baea2207cb152
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user