Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 带动画的天花板跌落能力:播放 Fall 动画 + 切换物理体为 Dynamic 自由下落,落地后启用接触伤害并恢复巡逻。
|
||||
/// 取代 sealed 的 CeilingDropAbility,动画所有权完整封装在本能力中。
|
||||
/// 可复用于任何需要从天花板落下并造成接触伤害的敌人。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
public class AnimatedCeilingDropAbility : EnemyAbilityBase
|
||||
{
|
||||
[Header("动画")]
|
||||
[Tooltip("下落循环动画(旋转下落姿态,循环播放直到落地)")]
|
||||
[SerializeField] private ClipTransition _fallLoopClip;
|
||||
|
||||
[Header("物理下落")]
|
||||
[Tooltip("切换 Dynamic 后使用的重力倍率")]
|
||||
[SerializeField] private float _fallGravityScale = 3.5f;
|
||||
[Tooltip("下落超时保护(秒),超时后强制继续执行")]
|
||||
[SerializeField] private float _maxFallTime = 3f;
|
||||
[SerializeField] private LayerMask _groundMask;
|
||||
|
||||
[Header("落地后")]
|
||||
[Tooltip("落地后恢复帧延迟(秒),之后切换为 Patrol 阶段")]
|
||||
[SerializeField] private float _recoveryTime = 0.1f;
|
||||
[SerializeField] private BodyContactDamage _contactDamage;
|
||||
|
||||
private Rigidbody2D _rb;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_rb = GetComponentInParent<Rigidbody2D>();
|
||||
}
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
|
||||
// 播放下落动画(能力脚本负责动画所有权)
|
||||
if (_fallLoopClip.Clip != null)
|
||||
_animancer.Play(_fallLoopClip);
|
||||
|
||||
// 切换物理:Kinematic → Dynamic + 重力
|
||||
var origBodyType = _rb.bodyType;
|
||||
var origGravScale = _rb.gravityScale;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_rb.gravityScale = _fallGravityScale;
|
||||
_rb.velocity = Vector2.zero;
|
||||
|
||||
// 等待落地(超时保护)
|
||||
float elapsed = 0f;
|
||||
while (elapsed < _maxFallTime)
|
||||
{
|
||||
elapsed += Time.fixedDeltaTime;
|
||||
yield return new WaitForFixedUpdate();
|
||||
if (elapsed > 0.05f && IsGrounded()) break;
|
||||
}
|
||||
_rb.velocity = Vector2.zero;
|
||||
|
||||
// 落地后启用接触伤害
|
||||
if (_contactDamage != null)
|
||||
_contactDamage.enabled = true;
|
||||
|
||||
yield return EnemyAbilityWaits.Get(_recoveryTime);
|
||||
|
||||
// SetAiPhase(Patrol) 自动播放 AnimConfig.Walk(地面移动动画)
|
||||
_enemy.SetAiPhase(AiPhase.Patrol);
|
||||
}
|
||||
|
||||
private bool IsGrounded()
|
||||
{
|
||||
var hit = Physics2D.Raycast(_rb.position, Vector2.down, 0.6f, _groundMask);
|
||||
return hit.collider != null;
|
||||
}
|
||||
|
||||
protected override void OnInterrupted(InterruptReason reason)
|
||||
{
|
||||
if (_rb != null)
|
||||
_rb.velocity = Vector2.zero;
|
||||
if (_contactDamage != null)
|
||||
_contactDamage.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76c9c3969851d084396edd617bac8ef0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
25
Assets/_Game/Scripts/Enemies/Abilities/AppearAbility.cs
Normal file
25
Assets/_Game/Scripts/Enemies/Abilities/AppearAbility.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 出场演出能力:播放出场动画后切换到 Combat 阶段(适用于小Boss或需出场动画的精英怪)。
|
||||
/// 可复用于任何"播出场动画→进入战斗"的敌人。
|
||||
/// </summary>
|
||||
public class AppearAbility : EnemyAbilityBase
|
||||
{
|
||||
[SerializeField] private ClipTransition _appearClip;
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
if (_appearClip.Clip == null) yield break;
|
||||
|
||||
_animancer.Play(_appearClip);
|
||||
yield return EnemyAbilityWaits.Get(_appearClip.Clip.length);
|
||||
_enemy.SetAiPhase(AiPhase.Combat);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/_Game/Scripts/Enemies/Abilities/AppearAbility.cs.meta
Normal file
11
Assets/_Game/Scripts/Enemies/Abilities/AppearAbility.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 419edb00543abc047a8e7601cf0f3ac4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using BaseGames.Combat;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 天花板三段攻击能力:出击 → 脆弱悬挂窗口 → 收回。
|
||||
/// 悬挂阶段(_loopClip)为脆弱窗口:HurtBox 激活,等待 _hangDuration 后结束。
|
||||
/// 可复用于任何固定位置的天花板攻击型敌人。
|
||||
/// </summary>
|
||||
public class CeilingHangStrikeAbility : EnemyAbilityBase
|
||||
{
|
||||
[Header("动画")]
|
||||
[SerializeField] private ClipTransition _strikeClip;
|
||||
[SerializeField] private ClipTransition _loopClip;
|
||||
[SerializeField] private ClipTransition _endClip;
|
||||
|
||||
[Header("碰撞")]
|
||||
[SerializeField] private HitBox _attackHitBox;
|
||||
[SerializeField] private HurtBox _hurtBox;
|
||||
|
||||
[Header("行为")]
|
||||
[Tooltip("脆弱悬挂窗口持续时间(秒)")]
|
||||
[SerializeField] private float _hangDuration = 2f;
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
|
||||
// 出击阶段:播放攻击动画并激活 HitBox
|
||||
if (_strikeClip.Clip != null)
|
||||
{
|
||||
_animancer.Play(_strikeClip);
|
||||
var dmgSrc = _config?.attackSequence?.Length > 0 ? _config.attackSequence[0].damageSource : null;
|
||||
_attackHitBox?.Activate(dmgSrc, _transform);
|
||||
yield return EnemyAbilityWaits.Get(_strikeClip.Clip.length);
|
||||
}
|
||||
_attackHitBox?.Deactivate();
|
||||
|
||||
// 脆弱悬挂阶段:HurtBox 激活为玩家反击窗口
|
||||
if (_loopClip.Clip != null)
|
||||
_animancer.Play(_loopClip);
|
||||
|
||||
if (_hurtBox != null)
|
||||
_hurtBox.enabled = true;
|
||||
|
||||
yield return EnemyAbilityWaits.Get(_hangDuration);
|
||||
|
||||
if (_hurtBox != null)
|
||||
_hurtBox.enabled = false;
|
||||
|
||||
// 收回阶段
|
||||
if (_endClip.Clip != null)
|
||||
{
|
||||
_animancer.Play(_endClip);
|
||||
yield return EnemyAbilityWaits.Get(_endClip.Clip.length);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInterrupted(InterruptReason reason)
|
||||
{
|
||||
_attackHitBox?.Deactivate();
|
||||
if (_hurtBox != null)
|
||||
_hurtBox.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5615d1d3eb70f414fb137428a3f7f962
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using UnityEngine;
|
||||
using BaseGames.Enemies.Perception;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 循环追击 + 体接触伤害能力。
|
||||
/// 追击期间每帧更新 MoveTo,失去感知后收招退出并恢复巡逻状态。
|
||||
/// 可复用于任何需要"追击+接触伤害循环"的敌人。
|
||||
/// </summary>
|
||||
public class ContactChaseAbility : EnemyAbilityBase
|
||||
{
|
||||
[Header("动画")]
|
||||
[SerializeField] private ClipTransition _loopClip;
|
||||
[SerializeField] private ClipTransition _endClip;
|
||||
|
||||
[Header("感知与接触伤害")]
|
||||
[SerializeField] private BodyContactDamage _contactDamage;
|
||||
[SerializeField] private EnemySensorHub _sensorHub;
|
||||
|
||||
[Tooltip("用于追击感知判断的传感器槽位名,通常为 \"aggro\"")]
|
||||
[SerializeField] private string _aggroSlotName = "aggro";
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
|
||||
if (_loopClip.Clip != null)
|
||||
_animancer.Play(_loopClip);
|
||||
|
||||
if (_contactDamage != null)
|
||||
_contactDamage.enabled = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (_enemy.PlayerTransform == null) break;
|
||||
if (_sensorHub != null && !_sensorHub.IsDetecting(_aggroSlotName, _enemy.PlayerTransform.gameObject))
|
||||
break;
|
||||
_enemy.MoveTo(_enemy.PlayerTransform.position);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (_contactDamage != null)
|
||||
_contactDamage.enabled = false;
|
||||
|
||||
_enemy.StopMovement();
|
||||
|
||||
if (_endClip.Clip != null)
|
||||
{
|
||||
_animancer.Play(_endClip);
|
||||
yield return EnemyAbilityWaits.Get(_endClip.Clip.length);
|
||||
}
|
||||
|
||||
_enemy.SetAiPhase(AiPhase.Patrol);
|
||||
}
|
||||
|
||||
protected override void OnInterrupted(InterruptReason reason)
|
||||
{
|
||||
if (_contactDamage != null)
|
||||
_contactDamage.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bfd6f44ebdb5bf489ab6703b1ee429b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/_Game/Scripts/Enemies/Abilities/FacePlayerAbility.cs
Normal file
42
Assets/_Game/Scripts/Enemies/Abilities/FacePlayerAbility.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using Animancer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 面向玩家能力:朝向玩家后播放转身/翻转动画并等待完成。
|
||||
/// CanUse 重写:仅在无其他技能运行且玩家在背后时可用。
|
||||
/// 可复用于任何需要"检测背后玩家并翻转"的敌人。
|
||||
/// </summary>
|
||||
public class FacePlayerAbility : EnemyAbilityBase
|
||||
{
|
||||
[SerializeField] private ClipTransition _faceClip;
|
||||
|
||||
public override bool CanUse =>
|
||||
base.CanUse
|
||||
&& !_enemy.Abilities.All.Any(a => a != this && a.IsRunning)
|
||||
&& IsPlayerBehind();
|
||||
|
||||
private bool IsPlayerBehind()
|
||||
{
|
||||
if (_enemy.PlayerTransform == null) return false;
|
||||
float dx = _enemy.PlayerTransform.position.x - _enemy.transform.position.x;
|
||||
int facing = _enemy.Movement?.FacingDirection ?? 1;
|
||||
return (facing > 0 && dx < 0) || (facing < 0 && dx > 0);
|
||||
}
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
|
||||
_enemy.Movement?.FaceTarget(_enemy.PlayerTransform.position);
|
||||
|
||||
if (_faceClip.Clip == null) yield break;
|
||||
|
||||
_animancer.Play(_faceClip);
|
||||
yield return EnemyAbilityWaits.Get(_faceClip.Clip.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c97df5c477ad0b488171b2b39530b08
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using BaseGames.Combat;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 近战攻击带后摇脆弱窗口能力:攻击动画期间按时间比例激活 HitBox,
|
||||
/// 攻击完成后开放 HurtBox(脆弱窗口),窗口结束后恢复正常。
|
||||
/// 可复用于任何"攻击后有反击窗口"的敌人技能。
|
||||
/// </summary>
|
||||
public class MeleeVulnerabilityAbility : EnemyAbilityBase
|
||||
{
|
||||
[Header("动画")]
|
||||
[SerializeField] private ClipTransition _attackClip;
|
||||
|
||||
[Header("碰撞")]
|
||||
[SerializeField] private HitBox _hitBox;
|
||||
[SerializeField] private HurtBox _hurtBox;
|
||||
|
||||
[Header("打击时间(0~1 归一化,基于 Clip 时长)")]
|
||||
[SerializeField, Range(0f, 1f)] private float _hitEnterT = 0.30f;
|
||||
[SerializeField, Range(0f, 1f)] private float _hitExitT = 0.60f;
|
||||
|
||||
[Header("后摇脆弱窗口")]
|
||||
[Tooltip("HurtBox 激活时间(秒)")]
|
||||
[SerializeField] private float _staggerDuration = 1.0f;
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
if (_attackClip.Clip == null) yield break;
|
||||
|
||||
float len = _attackClip.Clip.length;
|
||||
float t = 0f;
|
||||
bool active = false;
|
||||
|
||||
var dmgSrc = _config?.attackSequence?.Length > 0 ? _config.attackSequence[0].damageSource : null;
|
||||
|
||||
_animancer.Play(_attackClip);
|
||||
|
||||
while (t < len)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
|
||||
if (!active && t >= len * _hitEnterT)
|
||||
{
|
||||
_hitBox?.Activate(dmgSrc, _transform);
|
||||
active = true;
|
||||
}
|
||||
if (active && t >= len * _hitExitT)
|
||||
{
|
||||
_hitBox?.Deactivate();
|
||||
active = false;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (active)
|
||||
_hitBox?.Deactivate();
|
||||
|
||||
// 后摇脆弱窗口
|
||||
if (_hurtBox != null)
|
||||
_hurtBox.enabled = true;
|
||||
|
||||
yield return EnemyAbilityWaits.Get(_staggerDuration);
|
||||
|
||||
if (_hurtBox != null)
|
||||
_hurtBox.enabled = false;
|
||||
}
|
||||
|
||||
protected override void OnInterrupted(InterruptReason reason)
|
||||
{
|
||||
_hitBox?.Deactivate();
|
||||
if (_hurtBox != null)
|
||||
_hurtBox.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5fc3af69bdd62a418fe6e2ce136c9a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Assets/_Game/Scripts/Enemies/Abilities/PlayClipAbility.cs
Normal file
24
Assets/_Game/Scripts/Enemies/Abilities/PlayClipAbility.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 播放单个动画 Clip 并等待完成后退出(无副作用)。
|
||||
/// 可复用于任何需要"播一段动画即完成"的能力(如出场激活、台词演出等)。
|
||||
/// </summary>
|
||||
public class PlayClipAbility : EnemyAbilityBase
|
||||
{
|
||||
[SerializeField] private ClipTransition _clip;
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
if (_clip.Clip == null) yield break;
|
||||
|
||||
_animancer.Play(_clip);
|
||||
yield return EnemyAbilityWaits.Get(_clip.Clip.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a26fca0fa72894a4da1a5a58ee023154
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
75
Assets/_Game/Scripts/Enemies/Abilities/RepeatSlamAbility.cs
Normal file
75
Assets/_Game/Scripts/Enemies/Abilities/RepeatSlamAbility.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using BaseGames.Combat;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies.Abilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 多段砸地能力:起手 → 循环砸地(N次,带 HitBox 激活)→ 收招。
|
||||
/// 支持霸体(ABL SO 配置 interruptOnHurt=false),后摇时间可配置。
|
||||
/// 可复用于任何多段地面攻击型敌人。
|
||||
/// </summary>
|
||||
public class RepeatSlamAbility : EnemyAbilityBase
|
||||
{
|
||||
[Header("动画")]
|
||||
[SerializeField] private ClipTransition _startClip;
|
||||
[SerializeField] private ClipTransition _loopClip;
|
||||
[SerializeField] private ClipTransition _endClip;
|
||||
|
||||
[Header("打击")]
|
||||
[SerializeField] private HitBox _hitBox;
|
||||
|
||||
[Header("行为配置")]
|
||||
[Tooltip("每次砸地时 HitBox 激活时长(秒)")]
|
||||
[SerializeField] private float _hitActiveTime = 0.15f;
|
||||
[Tooltip("砸地次数")]
|
||||
[SerializeField] private int _slamCount = 2;
|
||||
[Tooltip("最后一次砸地收招后额外等待时间(秒)")]
|
||||
[SerializeField] private float _staggerDuration = 1.2f;
|
||||
|
||||
protected override IEnumerator ExecuteCoroutine()
|
||||
{
|
||||
Phase = AbilityRunState.Active;
|
||||
|
||||
if (_startClip.Clip != null)
|
||||
{
|
||||
_animancer.Play(_startClip);
|
||||
yield return EnemyAbilityWaits.Get(_startClip.Clip.length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _slamCount; i++)
|
||||
{
|
||||
if (_loopClip.Clip != null)
|
||||
{
|
||||
_animancer.Play(_loopClip);
|
||||
float preHit = Mathf.Max(0f, _loopClip.Clip.length - _hitActiveTime - 0.05f);
|
||||
yield return EnemyAbilityWaits.Get(preHit);
|
||||
}
|
||||
|
||||
var dmgSrc = _config?.attackSequence?.Length > 0 ? _config.attackSequence[0].damageSource : null;
|
||||
_hitBox?.Activate(dmgSrc, _transform);
|
||||
yield return EnemyAbilityWaits.Get(_hitActiveTime);
|
||||
_hitBox?.Deactivate();
|
||||
|
||||
if (i < _slamCount - 1)
|
||||
yield return EnemyAbilityWaits.Get(0.1f);
|
||||
}
|
||||
|
||||
if (_endClip.Clip != null)
|
||||
{
|
||||
_animancer.Play(_endClip);
|
||||
yield return EnemyAbilityWaits.Get(_endClip.Clip.length + _staggerDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return EnemyAbilityWaits.Get(_staggerDuration);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInterrupted(InterruptReason reason)
|
||||
{
|
||||
_hitBox?.Deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff71de2a91f535d488c76df6395f1d78
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user