Files
zeling_v2/Assets/_Game/Scripts/Dialogue/DialogueActorSO.cs
Joywayer 446fd5dcd0 feat: Add WorldStateFlagAttribute and custom property drawer for enhanced dialogue management
- Implemented WorldStateFlagAttribute to mark string fields as world state flags.
- Created NarrativeNPCEditor for custom inspector to visualize dialogue version activation states.
- Developed WorldStateFlagDrawer to provide dropdown menu for known flags in the inspector.
- Introduced ActorModule for managing DialogueActorSO assets, including viewing, creating, and deleting actors.
- Added DialogueModule for managing DialogueSequenceSO assets with detailed previews and action bars.
- Established QuestModule for managing QuestSO assets, including objectives and branches.
- Implemented QuestManagerPostprocessor to automatically refresh QuestManager's quest list on asset changes.
2026-05-24 00:36:11 +08:00

82 lines
3.4 KiB
C#
Raw 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 UnityEngine;
namespace BaseGames.Dialogue
{
/// <summary>
/// 对话角色定义 SO架构 14_NarrativeModule §3
/// 将 NPC 的显示名、头像、对话气泡颜色集中在一处管理。
/// DialogueLine.actor 引用此 SO修改头像/名称只需改一个资产,
/// 无需批量编辑所有对话行。
///
/// 资产路径Assets/_Game/Data/Dialogue/Actors/Actor_{actorId}.asset
/// </summary>
[CreateAssetMenu(menuName = "BaseGames/Dialogue/DialogueActor")]
public class DialogueActorSO : ScriptableObject
{
[Header("标识")]
[Tooltip("唯一 ID如 \"NPC_Elder\",供 DialogueLine 引用")]
public string actorId;
[Header("显示")]
[Tooltip("本地化 Key格式如 \"NPC_Elder_Name\"")]
public string nameKey;
[Tooltip("对话 UI 中显示的头像")]
public Sprite portrait;
[Tooltip("对话气泡/说话人名称的主题颜色(可选)")]
public Color accentColor = Color.white;
[Tooltip("是否为玩家角色(影响对话 UI 排版方向)")]
public bool isPlayer;
#if UNITY_EDITOR
// actorId → 资产路径5 秒 TTL跨所有 DialogueActorSO.OnValidate 共用。
// 与 QuestSO / DialogueSequenceSO 保持一致的 O(1) 重复检测策略。
private static System.Collections.Generic.Dictionary<string, string> s_actorIdToPath;
private static double s_actorIdsCacheTime = -10.0;
private static System.Collections.Generic.Dictionary<string, string> GetActorIdCache()
{
double now = UnityEditor.EditorApplication.timeSinceStartup;
if (s_actorIdToPath != null && now - s_actorIdsCacheTime < 5.0)
return s_actorIdToPath;
s_actorIdToPath = new System.Collections.Generic.Dictionary<string, string>(System.StringComparer.Ordinal);
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:DialogueActorSO");
foreach (var guid in guids)
{
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
var actor = UnityEditor.AssetDatabase.LoadAssetAtPath<DialogueActorSO>(path);
if (actor != null && !string.IsNullOrEmpty(actor.actorId) && !s_actorIdToPath.ContainsKey(actor.actorId))
s_actorIdToPath[actor.actorId] = path;
}
s_actorIdsCacheTime = now;
return s_actorIdToPath;
}
private void OnValidate()
{
if (string.IsNullOrWhiteSpace(actorId))
{
Debug.LogWarning($"[DialogueActorSO] '{name}' 缺少 actorId保存前请填写。", this);
return;
}
// 检测重复 actorId缓存路径 vs 自身路径比对O(1)5 秒内无需重扫。
var cache = GetActorIdCache();
string myPath = UnityEditor.AssetDatabase.GetAssetPath(this);
if (!string.IsNullOrEmpty(myPath) &&
cache.TryGetValue(actorId, out var existingPath) &&
existingPath != myPath)
{
Debug.LogError(
$"[DialogueActorSO] actorId '{actorId}' 与 " +
$"'{System.IO.Path.GetFileNameWithoutExtension(existingPath)}' 重复!请修改其中一个。", this);
s_actorIdsCacheTime = -10.0;
}
}
#endif
}
}