feat(enemy): AbilityRef——AI 层能力引用资产化,字符串仅作定制脚本兜底
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using UnityEngine;
|
||||||
|
using BaseGames.Enemies.Abilities;
|
||||||
|
|
||||||
|
namespace BaseGames.Tests.EditMode.AI
|
||||||
|
{
|
||||||
|
public class AbilityRefTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void ImplicitFromString_ExposesLiteralId()
|
||||||
|
{
|
||||||
|
AbilityRef r = "e001_chase";
|
||||||
|
Assert.AreEqual("e001_chase", r.Id);
|
||||||
|
Assert.IsFalse(r.IsEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FromAsset_ExposesAssetAbilityId()
|
||||||
|
{
|
||||||
|
var so = ScriptableObject.CreateInstance<EnemyAbilitySO>();
|
||||||
|
so.abilityId = "from_asset";
|
||||||
|
AbilityRef r = so;
|
||||||
|
Assert.AreEqual("from_asset", r.Id);
|
||||||
|
Object.DestroyImmediate(so);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Default_IsEmpty()
|
||||||
|
{
|
||||||
|
var r = default(AbilityRef);
|
||||||
|
Assert.IsTrue(r.IsEmpty);
|
||||||
|
Assert.IsNull(r.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AssetWins_WhenBothSet()
|
||||||
|
{
|
||||||
|
var so = ScriptableObject.CreateInstance<EnemyAbilitySO>();
|
||||||
|
so.abilityId = "asset_id";
|
||||||
|
var r = new AbilityRef(so, "literal_id");
|
||||||
|
Assert.AreEqual("asset_id", r.Id);
|
||||||
|
Assert.IsTrue(r.HasConflict); // 供校验器报警告
|
||||||
|
Object.DestroyImmediate(so);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 30c3cfb4f5ff62f4691343a1ab594f7a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BaseGames.Enemies.Abilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 能力引用。配方资产侧引用 EnemyAbilitySO(Unity 引用系统保证拼不错、改名不断链);
|
||||||
|
/// 定制 AiScript 侧仍可直接写字符串 id。资产优先。
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public struct AbilityRef
|
||||||
|
{
|
||||||
|
[Tooltip("能力配置资产;配方路径用这个")]
|
||||||
|
[SerializeField] EnemyAbilitySO _asset;
|
||||||
|
|
||||||
|
[NonSerialized] string _literal; // 定制脚本路径用;不参与序列化
|
||||||
|
|
||||||
|
public AbilityRef(EnemyAbilitySO asset) { _asset = asset; _literal = null; }
|
||||||
|
public AbilityRef(string id) { _asset = null; _literal = id; }
|
||||||
|
public AbilityRef(EnemyAbilitySO asset, string id) { _asset = asset; _literal = id; }
|
||||||
|
|
||||||
|
/// <summary>解析出的能力 id;资产优先,都没有则 null。</summary>
|
||||||
|
public string Id => _asset != null ? _asset.abilityId : _literal;
|
||||||
|
|
||||||
|
public bool IsEmpty => string.IsNullOrEmpty(Id);
|
||||||
|
|
||||||
|
/// <summary>资产与字符串同时非空——歧义配置,供校验器报警告。</summary>
|
||||||
|
public bool HasConflict => _asset != null && !string.IsNullOrEmpty(_literal);
|
||||||
|
|
||||||
|
public static implicit operator AbilityRef(string id) => new AbilityRef(id);
|
||||||
|
public static implicit operator AbilityRef(EnemyAbilitySO asset) => new AbilityRef(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 00a0a0d1f0e127a47ad01ea9423bbc0d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user