2026-05-21 보스 특수스킬1

This commit is contained in:
2026-05-21 15:22:07 +09:00
parent 0f35455ad7
commit a4a9316e9c
23 changed files with 533 additions and 39 deletions

Binary file not shown.

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Collider2D))]
public class HazardHitbox : MonoBehaviour
{
[SerializeField] private LayerMask _targetLayer;
[SerializeField] private LayerMask _blockLayer; // 피해를 줄 레이어 (보통 Player)
private int _damage = 0;
private Collider2D _collider;
private void Awake()
{
_collider = GetComponent<Collider2D>();
_collider.isTrigger = true;
_collider.enabled = false;
}
private void OnTriggerStay2D(Collider2D other)
{
TryDamage(other);
}
private void TryDamage(Collider2D other)
{
if ((_targetLayer.value & (1 << other.gameObject.layer)) == 0) return;
if (!other.TryGetComponent<IDamageable>(out var target))
target = other.GetComponentInParent<IDamageable>();
if (target == null) return;
target.TakeDamage(_damage);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 906fae86c8ab8ea4faa1855e18a573d0

View File

@@ -1,11 +1,7 @@
using System;
using UnityEngine;
// ============================================================================
// BossAttack
// ----------------------------------------------------------------------------
// 보스 공격 하나의 설정. 별도 .asset 없이 BossAI 인스펙터에서 배열로 편집.
// ============================================================================
[Serializable]
public class BossAttack
{
@@ -14,7 +10,7 @@ public class BossAttack
public float Range = 1.5f; // 타겟이 이 X거리 안일 때만 사용
public float Windup = 0.4f; // 공격 시작 ~ 데미지 발생 (선딜)
public float Duration = 0.9f; // 공격 동작 전체 길이 (이 동안 이동 정지)
public float Cooldown = 2f; // 이 공격 자체의 재사용 대기
public float Cooldown = 10f; // 이 공격 자체의 재사용 대기
public int Damage = 15;
public Vector2 HitVelocity = new Vector2(5f, 2f); // 피격자 넉백 (X는 보스 facing 방향으로 부호 적용)
public string AnimationState = "BossAttack";
@@ -23,10 +19,10 @@ public class BossAttack
// ============================================================================
// BossAI
// ----------------------------------------------------------------------------
// 보스의 두뇌. EnemyAI와 골격(감지→추격→공격)은 같지만:
// - 여러 공격(BossAttack 배열)을 보유하고, 사거리·쿨다운·페이즈 조건
// 만족하는 것 중 무작위로 골라 사용
// - 각 공격의 MinPhase로 페이즈 잠금 → Boss.CurrentPhase가 오르면 신규 공격 해금
// 보스의 두뇌. 감지 → 추격 → 공격 상태머신.
// - 단순 공격: BossAttack 데이터 배열 (사거리·쿨다운·페이즈 조건)
// - 특별 스킬: BossSkill 프리팹 배열. 시전 시 Instantiate → 끝나면 스스로 파괴
// - 행동 결정: 특별 스킬 → 단순 공격 → 추격 순으로 시도
// 같은 GameObject의 Enemy(몸)·Boss(페이즈)와 함께 동작.
// ============================================================================
[RequireComponent(typeof(Enemy))]
@@ -47,8 +43,9 @@ private enum AIState { Idle, Chase, Attack }
[Header("Attacks")]
[SerializeField] private BossAttack[] _attacks;
[SerializeField] private float _attackVerticalTolerance = 1.5f; // 공격 적중 인정 세로 오차
[SerializeField] private float _globalAttackCooldown = 0.6f; // 공격 종료 후 다음 공격까지 최소 간격
[SerializeField] private BossSkill[] _skillPrefabs; // 특별 스킬 프리팹 (시전 시 Instantiate)
[SerializeField] private float _attackVerticalTolerance = 1.5f; // 공격 적중 인정 세로 오차
[SerializeField] private float _globalAttackCooldown = 0.6f; // 공격/스킬 종료 후 다음 행동까지 최소 간격
[Header("Animation")]
[SerializeField] private string _idleAnimationState = "Idle";
@@ -65,13 +62,18 @@ private enum AIState { Idle, Chase, Attack }
private AIState _state = AIState.Idle;
private bool _hasAggro;
private float[] _attackCooldownTimers; // _attacks와 1:1 — 각 공격의 남은 쿨다운
private int[] _attackPickBuffer; // PickAttackIndex 후보 수집용 (GC 회피)
private float _globalCooldownTimer; // 공격 사이 전역 대기
private float[] _attackCooldownTimers; // _attacks와 1:1 — 각 공격의 남은 쿨다운
private int[] _attackPickBuffer; // PickAttackIndex 후보 수집용 (GC 회피)
private float[] _skillCooldownTimers; // _skillPrefabs와 1:1 — 보스별 스킬 쿨다운
private int[] _skillPickBuffer; // PickSkillIndex 후보 수집용 (GC 회피)
private float _globalCooldownTimer; // 공격/스킬 사이 전역 대기
private BossAttack _currentAttack; // 진행 중인 공격
private BossSkill _runningSkillInstance; // 진행 중인 스킬 인스턴스 (없거나 끝나면 null)
private bool _skillInProgress; // 스킬 시전 중 (인스턴스 생성 ~ 파괴)
private BossAttack _currentAttack; // 진행 중인 단순 공격
private bool _isAttacking;
private bool _attackDamageApplied; // 이번 공격에서 데미지를 이미 줬는지
private bool _attackDamageApplied; // 이번 공격에서 데미지를 이미 줬는지
private float _attackTimer;
private float _facingDirection = 1f;
@@ -86,9 +88,13 @@ private void Awake()
_anim = GetComponentInChildren<Animator>();
_spriteRenderer = GetComponentInChildren<SpriteRenderer>();
int count = _attacks != null ? _attacks.Length : 0;
_attackCooldownTimers = new float[count];
_attackPickBuffer = new int[count];
int attackCount = _attacks != null ? _attacks.Length : 0;
_attackCooldownTimers = new float[attackCount];
_attackPickBuffer = new int[attackCount];
int skillCount = _skillPrefabs != null ? _skillPrefabs.Length : 0;
_skillCooldownTimers = new float[skillCount];
_skillPickBuffer = new int[skillCount];
}
private void Update()
@@ -96,16 +102,29 @@ private void Update()
TickCooldowns();
ResolveTarget();
// 사망 / 행동 불가(피격 경직·잡힘) / 페이즈 전환 중 / 타겟 없음 → 정지.
// 사망 / 행동 불가(피격 경직·잡힘) / 페이즈 전환 중 / 타겟 없음 → 정지 + 진행 중 행동 취소.
if (_health.IsDead || !_enemy.CanUseAI
|| (_boss != null && _boss.IsTransitioning) || _target == null)
{
if (_isAttacking) CancelAttack();
CancelRunningSkill();
StopMoving();
SetState(AIState.Idle);
return;
}
// 특별 스킬 진행 중이면 스킬에 전부 맡기고 대기. 인스턴스가 사라지면(종료) 후딜 부여.
if (_skillInProgress)
{
if (_runningSkillInstance != null)
{
StopMoving();
return;
}
_skillInProgress = false;
_globalCooldownTimer = _globalAttackCooldown;
}
RefreshAggro();
// 공격 중이면 facing을 고정한 채 공격 진행만 처리.
@@ -124,12 +143,25 @@ private void Update()
return;
}
// 사용 가능한 공격이 있으면 공격 시작, 없으면 추격.
int attackIndex = _globalCooldownTimer <= 0f ? PickAttackIndex() : -1;
if (attackIndex >= 0)
BeginAttack(attackIndex);
else
SetState(AIState.Chase);
// 전역 쿨다운이 끝났으면 특별 스킬 → 단순 공격 순으로 시도. 둘 다 안 되면 추격.
if (_globalCooldownTimer <= 0f)
{
int skillIndex = PickSkillIndex();
if (skillIndex >= 0)
{
BeginSkill(skillIndex);
return;
}
int attackIndex = PickAttackIndex();
if (attackIndex >= 0)
{
BeginAttack(attackIndex);
return;
}
}
SetState(AIState.Chase);
}
private void FixedUpdate()
@@ -146,7 +178,7 @@ private void FixedUpdate()
_rb.linearVelocity = v;
}
// ─── 공격 ────────────────────────────────────────────────────────────
// ─── 단순 공격 ────────────────────────────────────────────────────────
// 현재 사용 가능한 공격 후보 중 무작위 1개의 인덱스 반환. 없으면 -1.
// 조건: 페이즈 해금 + 쿨다운 종료 + 사거리 안.
@@ -181,7 +213,7 @@ private void BeginAttack(int index)
_attackDamageApplied = false;
_attackTimer = 0f;
_attackCooldownTimers[index] = _currentAttack.Cooldown;
// 공격 동작 길이 + 후딜만큼 다음 공격을 막는다.
// 공격 동작 길이 + 후딜만큼 다음 행동을 막는다.
_globalCooldownTimer = _currentAttack.Duration + _globalAttackCooldown;
_state = AIState.Attack;
@@ -234,16 +266,80 @@ private void ApplyAttackDamage()
_targetDamageable.TakeDamage(_currentAttack.Damage, knockback);
}
// ─── 특별 스킬 ───────────────────────────────────────────────────────
// 사용 가능한 스킬 프리팹 후보 중 무작위 1개의 인덱스 반환. 없으면 -1.
// 조건은 프리팹에서 직접 읽는다 (MinPhase/Range). 쿨다운은 보스별 타이머로.
private int PickSkillIndex()
{
if (_skillPrefabs == null || _skillPrefabs.Length == 0 || _target == null) return -1;
float distanceX = Mathf.Abs(_target.position.x - transform.position.x);
int phase = _boss != null ? _boss.CurrentPhase : 0;
int candidateCount = 0;
for (int i = 0; i < _skillPrefabs.Length; i++)
{
BossSkill prefab = _skillPrefabs[i];
if (prefab == null) continue;
if (phase < prefab.MinPhase) continue; // 페이즈 미해금
if (_skillCooldownTimers[i] > 0f) continue; // 쿨다운 중
if (distanceX > prefab.Range) continue; // 사거리 밖
_skillPickBuffer[candidateCount++] = i;
}
if (candidateCount == 0) return -1;
return _skillPickBuffer[UnityEngine.Random.Range(0, candidateCount)];
}
private void BeginSkill(int index)
{
BossSkill prefab = _skillPrefabs[index];
_skillCooldownTimers[index] = prefab.Cooldown;
_state = AIState.Idle;
StopMoving();
UpdateFacing(); // _facingDirection을 타겟 방향으로 갱신
// 스킬 프리팹을 보스 위치에 생성하고 보스의 자식으로 둔다 (보스 파괴 시 함께 정리).
BossSkill instance = Instantiate(prefab, transform.position, Quaternion.identity, transform);
// 보스가 왼쪽을 보면 스킬도 X 반전 (콜라이더 패턴이 시전 방향을 따르게).
if (_facingDirection < 0f)
{
Vector3 scale = instance.transform.localScale;
scale.x = -Mathf.Abs(scale.x);
instance.transform.localScale = scale;
}
_runningSkillInstance = instance;
_skillInProgress = true;
PlayAnim(prefab.CasterAnimationState); // 보스는 시전 애니메이션 재생
instance.Begin();
}
// 진행 중인 스킬 인스턴스를 파괴해 즉시 중단 (콜라이더도 함께 사라짐).
private void CancelRunningSkill()
{
if (_runningSkillInstance != null)
Destroy(_runningSkillInstance.gameObject);
_runningSkillInstance = null;
_skillInProgress = false;
}
private void TickCooldowns()
{
if (_globalCooldownTimer > 0f)
_globalCooldownTimer -= Time.deltaTime;
for (int i = 0; i < _attackCooldownTimers.Length; i++)
{
if (_attackCooldownTimers[i] > 0f)
_attackCooldownTimers[i] -= Time.deltaTime;
}
for (int i = 0; i < _skillCooldownTimers.Length; i++)
if (_skillCooldownTimers[i] > 0f)
_skillCooldownTimers[i] -= Time.deltaTime;
}
// ─── 타겟 / 인지 / 방향 ──────────────────────────────────────────────
@@ -306,7 +402,7 @@ private void SetState(AIState state)
_state = state;
if (state == AIState.Idle) PlayAnim(_idleAnimationState);
else if (state == AIState.Chase) PlayAnim(_runAnimationState);
// Attack 상태 애니메이션은 BeginAttack에서 직접 재생.
// Attack 상태 애니메이션은 BeginAttack, 스킬 시전 애니메이션은 BeginSkill에서 재생.
}
// 같은 State 중복 재생 방지 (Play를 매 프레임 호출하면 애니가 처음으로 리셋됨).
@@ -324,10 +420,16 @@ private void OnDrawGizmosSelected()
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, _detectRange);
if (_attacks == null) return;
Gizmos.color = Color.red;
for (int i = 0; i < _attacks.Length; i++)
if (_attacks[i] != null)
Gizmos.DrawWireSphere(transform.position, _attacks[i].Range);
if (_attacks != null)
for (int i = 0; i < _attacks.Length; i++)
if (_attacks[i] != null)
Gizmos.DrawWireSphere(transform.position, _attacks[i].Range);
Gizmos.color = new Color(1f, 0.4f, 1f); // 스킬 사거리 = 보라색
if (_skillPrefabs != null)
for (int i = 0; i < _skillPrefabs.Length; i++)
if (_skillPrefabs[i] != null)
Gizmos.DrawWireSphere(transform.position, _skillPrefabs[i].Range);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: daba49596fb3b8249b974bfbcb13e8a6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
using System;
using System.Threading;
using UnityEngine;
// ============================================================================
// BossSkill
// ----------------------------------------------------------------------------
// 보스 "특별 스킬"의 베이스 클래스. 스킬 하나 = 자기완결적 프리팹 하나.
//
// [스킬 프리팹] = BossSkill(상속) 컴포넌트 + 자체 Animator + HazardHitbox 자식들
//
// 동작 흐름:
// - BossAI._skillPrefabs에 프리팹을 등록 (씬 인스턴스가 아닌 에셋 참조)
// - 시전 시 BossAI가 프리팹을 Instantiate → Begin() 호출
// - 스킬은 시퀀스가 끝나면 스스로 Destroy
// - 취소(페이즈 전환·사망)는 BossAI가 인스턴스를 Destroy → 콜라이더도 함께 사라짐
//
// MinPhase/Range/Cooldown은 BossAI가 프리팹에서 직접 읽어 사용 가능 여부를 판단.
// 쿨다운 "타이머"는 보스별 상태라 BossAI가 추적한다.
//
// 새 스킬 추가: BossSkill을 상속한 컴포넌트로 프리팹을 만들고 RunSkill만 구현.
// ============================================================================
public abstract class BossSkill : MonoBehaviour
{
[Header("BossSkill")]
[SerializeField] private int _minPhase; // 이 페이즈(0부터) 이상에서만 사용 가능
[SerializeField] private float _range = 4f; // 타겟이 이 X거리 안일 때만 사용
[SerializeField] private float _cooldown = 8f; // 재사용 대기 (타이머는 BossAI가 보스별로 추적)
[SerializeField] private string _casterAnimationState = "BossCast"; // 시전 중 보스가 재생할 애니메이션
public int MinPhase => _minPhase;
public float Range => _range;
public float Cooldown => _cooldown;
public string CasterAnimationState => _casterAnimationState;
// BossAI가 인스턴스를 만든 직후 호출. 시퀀스를 끝까지 실행하고 스스로 파괴한다.
// destroyCancellationToken: BossAI가 이 인스턴스를 Destroy하면 시퀀스가 취소된다.
public async void Begin()
{
try
{
await RunSkill(destroyCancellationToken);
}
catch (OperationCanceledException)
{
return; // 외부에서 Destroy됨 → GameObject 이미 파괴 중이므로 그대로 종료
}
catch (Exception e)
{
Debug.LogException(e, this); // 스킬 버그가 나도 아래 Destroy로 정리는 보장
}
Destroy(gameObject);
}
// 서브클래스가 실제 스킬 시퀀스를 구현. token이 취소되면 finally에서 정리할 것.
protected abstract Awaitable RunSkill(CancellationToken token);
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b8622c72961cf4d4a83c6a904e3cedea

View File

@@ -0,0 +1,84 @@
using System.Threading;
using Unity.VisualScripting;
using UnityEngine;
// ============================================================================
// HazardSkill
// ----------------------------------------------------------------------------
// 보스 특별 스킬의 한 종류 (BossSkill 상속). 스킬 프리팹의 루트에 부착.
//
// 시퀀스: 자체 애니메이션 재생 → 선딜 → 피해 판정 ON → 유지 → OFF → 후딜 → 자동 파괴
//
// 콜라이더의 "움직임"은 이 프리팹의 자체 Animator/클립이 담당한다 (보스와 무관).
// 이 스크립트는 타이밍에 맞춰 HazardHitbox들의 피해 판정만 ON/OFF 한다.
// ============================================================================
public class HazardSkill : BossSkill
{
[Header("HazardSkill")]
[SerializeField] private Animator _animator; // 이 프리팹의 Animator (콜라이더 이동 담당)
[SerializeField] private string _downAnimationState = "HazardSkillDown";
[SerializeField] private string _rightAnimationState = "HazardSkillRight";
[SerializeField] private float _windup = 0.5f; // 애니 시작 ~ 피해 판정 ON
[SerializeField] private float _activeDuration = 1.5f; // 피해 판정 유지 시간
[SerializeField] private float _recovery = 0.6f; // 판정 OFF 후 후딜
[SerializeField] private Transform[] _downHazardFirePos; // 위에서 아래로 포격
[SerializeField] private Transform[] _rightHazardFirePos; // 왼쪽에서 오른쪽으로 포격
[SerializeField] private GameObject _hazardHitboxOrigin;
private void Awake()
{
if (_animator == null)
_animator = GetComponentInChildren<Animator>();
}
protected override async Awaitable RunSkill(CancellationToken token)
{
try
{
int dirChoice = Random.Range(0,2); //0,1
if(dirChoice == 0) // Down 포격
{
if (_animator != null && !string.IsNullOrEmpty(_downAnimationState))
_animator.Play(_downAnimationState);
}
else if(dirChoice == 1) //Right 포격
{
if (_animator != null && !string.IsNullOrEmpty(_rightAnimationState))
_animator.Play(_rightAnimationState);
}
// 선딜
await Awaitable.WaitForSecondsAsync(_windup, token);
FireHazards(dirChoice);
// 후딜
await Awaitable.WaitForSecondsAsync(_recovery, token);
}
finally
{
}
}
private void FireHazards(int dirChoice)
{
Transform[] _hazardPoss = dirChoice switch { 0 => _downHazardFirePos, 1=>_rightHazardFirePos, _=> null};
Vector2 attackDir = dirChoice switch {0 => Vector2.down,1=>Vector2.right,_=>Vector2.left};
if (_hazardPoss == null) return;
for (int i = 0; i < _hazardPoss.Length; i++)
{
GameObject hitbox = Instantiate(_hazardHitboxOrigin,_hazardPoss[i].transform);
Rigidbody2D hitbox_rb = hitbox.GetComponent<Rigidbody2D>();
if(hitbox_rb != null)
{
hitbox_rb.linearVelocity = attackDir*5.0f;
}
Destroy(hitbox,5f);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e20ef4137f5c87f4ca4500445779b574

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7af62a125d51a0f4f98439dc6b587479
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2661c3fd528b72b46b2236fd0f53c4a6
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 74a8f5678f5d2734997ee7ad66d3ff6e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fe26ef5211fb5ab4e8b55cec6420947d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-2043269259346761627
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: New State
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: 0}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &-1748260263048877923
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: -2043269259346761627}
m_Position: {x: 60, y: 270, z: 0}
- serializedVersion: 1
m_State: {fileID: 943741232334775837}
m_Position: {x: 60, y: 360, z: 0}
- serializedVersion: 1
m_State: {fileID: 8862701103019185420}
m_Position: {x: 60, y: 440, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: -170, y: 180, z: 0}
m_EntryPosition: {x: -170, y: 250, z: 0}
m_ExitPosition: {x: 80, y: 180, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -2043269259346761627}
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: HazardSkillAnimController
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -1748260263048877923}
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!1102 &943741232334775837
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: HazardSkillDown
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: 10b9535854db9a946a94fec5a86a31e2, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &8862701103019185420
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: HazardSkillRight
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: 23c9b965b45afa4419d45e40dac523a5, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f811209764ecbdc469cb01175e73343e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 10b9535854db9a946a94fec5a86a31e2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 23c9b965b45afa4419d45e40dac523a5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 80c778713f233a2469e08d15655cbb7f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: