Files
zeling_v2/Assets/_Game/Scripts/Editor/Combat/WeaponHitBoxWizard.cs

182 lines
7.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.IO;
using UnityEditor;
using UnityEngine;
using BaseGames.Combat;
using BaseGames.Player;
namespace BaseGames.Editor.Combat
{
/// <summary>
/// 向导:一键生成武器 HitBox PrefabW-10
/// 菜单BaseGames / Create / Weapon HitBox Prefab
///
/// 生成路径规范Assets/_Game/Prefabs/Weapons/WPN_{weaponId}_HitBox.prefab
/// Prefab 结构:
/// [WPN_{weaponId}_HitBox] ← WeaponHitBoxInstance
/// ├── [HitBox_Ground] ← Collider2D(IsTrigger, 形状可选) + HitBox, Layer=PlayerHitBox
/// ├── [HitBox_Up]
/// ├── [HitBox_Down]
/// └── [HitBox_Air]
/// </summary>
public class WeaponHitBoxWizard : ScriptableWizard
{
private const string OutputFolder = "Assets/_Game/Prefabs/Weapons";
/// <summary>每个方向可选的 Collider 形状。</summary>
public enum ColliderShape
{
[Tooltip("BoxCollider2D — 矩形,适合水平/垂直扫击")]
Box,
[Tooltip("CapsuleCollider2D — 胶囊体,适合刺击或弧形")]
Capsule,
[Tooltip("PolygonCollider2D菱形默认点— 适合不规则斩击")]
Polygon,
}
[MenuItem("BaseGames/Create/Weapon HitBox Prefab", priority = 200)]
public static void Open() =>
DisplayWizard<WeaponHitBoxWizard>("Weapon HitBox Prefab 向导", "创建");
[Tooltip("武器唯一 ID如 SkyBlade。Prefab 将命名为 WPN_{weaponId}_HitBox")]
public string weaponId = "";
[Header("包含哪些攻击方向")]
public bool includeGround = true;
public bool includeUp = true;
public bool includeDown = true;
public bool includeAir = true;
[Header("每个方向的 Collider 形状")]
[Tooltip("Ground / 落地攻击的碰撞体形状")]
public ColliderShape groundShape = ColliderShape.Box;
[Tooltip("Up / 上挑攻击的碰撞体形状")]
public ColliderShape upShape = ColliderShape.Capsule;
[Tooltip("Down / 下砸攻击的碰撞体形状")]
public ColliderShape downShape = ColliderShape.Box;
[Tooltip("Air / 空中攻击的碰撞体形状")]
public ColliderShape airShape = ColliderShape.Capsule;
// ── 向导回调 ──────────────────────────────────────────────────────────
private void OnWizardUpdate()
{
isValid = !string.IsNullOrWhiteSpace(weaponId);
helpString = isValid
? $"将创建:{OutputFolder}/WPN_{weaponId}_HitBox.prefab"
: "请输入 weaponId武器唯一 ID如 SkyBlade。";
}
private void OnWizardCreate()
{
if (string.IsNullOrWhiteSpace(weaponId))
{
EditorUtility.DisplayDialog("错误", "weaponId 不能为空。", "确认");
return;
}
string prefabName = $"WPN_{weaponId}_HitBox";
string assetPath = $"{OutputFolder}/{prefabName}.prefab";
string fullPath = Path.Combine(
Path.GetDirectoryName(Application.dataPath)!,
assetPath.Replace('/', Path.DirectorySeparatorChar));
if (File.Exists(fullPath))
{
if (!EditorUtility.DisplayDialog("已存在",
$"{assetPath}\n\n该 Prefab 已存在,是否覆盖?",
"覆盖", "取消"))
return;
}
EditorScaffoldUtils.EnsureFolder(OutputFolder);
int hitBoxLayer = LayerMask.NameToLayer("PlayerHitBox");
if (hitBoxLayer < 0)
{
Debug.LogWarning("[WeaponHitBoxWizard] 未找到 Physics Layer 'PlayerHitBox',子节点 Layer 将设为 Default。");
hitBoxLayer = 0;
}
// ── 构建 Prefab ────────────────────────────────────────────────
var root = new GameObject(prefabName);
var instance = root.AddComponent<WeaponHitBoxInstance>();
var so = new SerializedObject(instance);
void AddDirection(bool enabled, string nodeName, string fieldName, ColliderShape shape)
{
if (!enabled) return;
var child = new GameObject(nodeName);
child.transform.SetParent(root.transform, false);
child.layer = hitBoxLayer;
AddCollider(child, shape);
var hb = child.AddComponent<HitBox>();
var prop = so.FindProperty(fieldName);
if (prop != null)
prop.objectReferenceValue = hb;
}
AddDirection(includeGround, "HitBox_Ground", "_hitBoxGround", groundShape);
AddDirection(includeUp, "HitBox_Up", "_hitBoxUp", upShape);
AddDirection(includeDown, "HitBox_Down", "_hitBoxDown", downShape);
AddDirection(includeAir, "HitBox_Air", "_hitBoxAir", airShape);
so.ApplyModifiedPropertiesWithoutUndo();
var prefab = PrefabUtility.SaveAsPrefabAsset(root, assetPath);
Object.DestroyImmediate(root);
AssetDatabase.Refresh();
if (prefab != null)
{
EditorScaffoldUtils.PingAndSelect(prefab);
Debug.Log($"[WeaponHitBoxWizard] 已创建:{assetPath}");
}
else
{
Debug.LogError($"[WeaponHitBoxWizard] Prefab 保存失败:{assetPath}");
}
}
// ── 辅助:按形状添加 2D 碰撞体 ────────────────────────────────────────
private static void AddCollider(GameObject go, ColliderShape shape)
{
switch (shape)
{
case ColliderShape.Box:
{
var c = go.AddComponent<BoxCollider2D>();
c.isTrigger = true;
c.size = new Vector2(1f, 0.5f);
break;
}
case ColliderShape.Capsule:
{
var c = go.AddComponent<CapsuleCollider2D>();
c.isTrigger = true;
c.size = new Vector2(0.5f, 1f);
break;
}
case ColliderShape.Polygon:
{
var c = go.AddComponent<PolygonCollider2D>();
c.isTrigger = true;
// 默认菱形点0.5 × 0.5 单位)
c.SetPath(0, new Vector2[]
{
new( 0f, 0.3f),
new( 0.5f, 0f ),
new( 0f, -0.3f),
new(-0.5f, 0f ),
});
break;
}
}
}
}
}