规范对话数据

This commit is contained in:
2026-04-20 19:49:18 +08:00
parent 0f928f6167
commit ef68ccc9e9
43 changed files with 1574 additions and 1092 deletions
@@ -346,12 +346,13 @@ namespace CustomComponent
_currentLineIndex = -1;
_formController.OnDialogEnded(_formContext);
_formController.CloseUI();
if (dialogId > 0)
_formController.CloseUI(() =>
{
GameEntry.Event.Fire(this, DialogCompletedEventArgs.Create(chapterId, dialogId, lineId));
}
if (dialogId > 0)
{
GameEntry.Event.Fire(this, DialogCompletedEventArgs.Create(chapterId, dialogId, lineId));
}
});
}
private void ApplyLineToContext(DRDialogLine lineRow, int lineIndex, int totalLines)
@@ -359,7 +360,6 @@ namespace CustomComponent
_formContext.CurrentLineId = lineRow.Id;
_formContext.SpeakerId = lineRow.SpeakerId;
_formContext.SpeakerName = lineRow.SpeakerName;
_formContext.Expression = lineRow.Expression;
_formContext.Direction = lineRow.Direction;
_formContext.Text = lineRow.Text;
_formContext.Emphasis = lineRow.Emphasis;
@@ -9,6 +9,8 @@ namespace CustomComponent
public override string ActionName => "ChangeBackground";
public override bool RequiresCompletion => true;
public override void Execute(StoryDirectorComponent director)
{
if (director == null)
@@ -19,6 +19,8 @@ namespace CustomComponent
public virtual string ActionName => GetType().Name;
public virtual bool RequiresCompletion => false;
public bool IsMatch(StoryTriggerType triggerType, int triggerId)
{
if (!_enabled || _triggerType != triggerType)
@@ -1,3 +1,4 @@
using System.Collections;
using System.Collections.Generic;
using Definition.Enum;
using Event;
@@ -20,21 +21,42 @@ namespace CustomComponent
[SerializeField] private string _backgroundAssetNamePrefix = string.Empty;
private readonly HashSet<string> _consumedDirectiveTokens = new HashSet<string>();
private readonly HashSet<string> _queuedDirectiveTokens = new HashSet<string>();
private readonly Queue<PendingDirectiveInvocation> _pendingDirectives =
new Queue<PendingDirectiveInvocation>();
private BgFormController _bgFormController;
private int _bgRequestVersion;
private bool _isExecuting;
private Coroutine _directiveExecutionCoroutine;
private int _nextBackgroundRequestId = 1;
private int _lastBackgroundRequestId;
private int _completedBackgroundRequestId;
private struct PendingDirectiveInvocation
{
public StoryDirectiveAsset Directive;
public StoryTriggerType TriggerType;
public int TriggerId;
public string DirectiveToken;
}
private void Start()
{
GameEntry.Event.Subscribe(DialogCompletedEventArgs.EventId, OnDialogCompleted);
GameEntry.Event.Subscribe(CombineCompletedEventArgs.EventId, OnCombineCompleted);
GameEntry.Event.Subscribe(BgTransitionCompletedEventArgs.EventId, OnBgTransitionCompleted);
}
private void OnDestroy()
{
GameEntry.Event.Unsubscribe(DialogCompletedEventArgs.EventId, OnDialogCompleted);
GameEntry.Event.Unsubscribe(CombineCompletedEventArgs.EventId, OnCombineCompleted);
GameEntry.Event.Unsubscribe(BgTransitionCompletedEventArgs.EventId, OnBgTransitionCompleted);
if (_directiveExecutionCoroutine != null)
{
StopCoroutine(_directiveExecutionCoroutine);
_directiveExecutionCoroutine = null;
}
_bgFormController?.CloseUI();
_bgFormController = null;
@@ -43,6 +65,8 @@ namespace CustomComponent
public void ResetConsumedDirectives()
{
_consumedDirectiveTokens.Clear();
_queuedDirectiveTokens.Clear();
_pendingDirectives.Clear();
}
private void OnDialogCompleted(object sender, GameFramework.Event.GameEventArgs e)
@@ -67,40 +91,43 @@ namespace CustomComponent
private void ExecuteDirectives(StoryTriggerType triggerType, int triggerId)
{
if (_isExecuting)
bool hasEnqueuedDirective = false;
for (int i = 0; i < _directives.Count; i++)
{
StoryDirectiveAsset directive = _directives[i];
if (directive == null || !directive.IsMatch(triggerType, triggerId))
{
continue;
}
string directiveToken = BuildDirectiveToken(directive, i);
if (!_allowRepeatTrigger &&
(_consumedDirectiveTokens.Contains(directiveToken) || _queuedDirectiveTokens.Contains(directiveToken)))
{
continue;
}
_pendingDirectives.Enqueue(new PendingDirectiveInvocation
{
Directive = directive,
TriggerType = triggerType,
TriggerId = triggerId,
DirectiveToken = directiveToken
});
hasEnqueuedDirective = true;
if (!_allowRepeatTrigger)
{
_queuedDirectiveTokens.Add(directiveToken);
}
}
if (!hasEnqueuedDirective || _directiveExecutionCoroutine != null)
{
return;
}
_isExecuting = true;
try
{
for (int i = 0; i < _directives.Count; i++)
{
StoryDirectiveAsset directive = _directives[i];
if (directive == null || !directive.IsMatch(triggerType, triggerId))
{
continue;
}
string directiveToken = BuildDirectiveToken(directive, i);
if (!_allowRepeatTrigger && _consumedDirectiveTokens.Contains(directiveToken))
{
continue;
}
ExecuteDirective(directive, triggerType, triggerId);
if (!_allowRepeatTrigger)
{
_consumedDirectiveTokens.Add(directiveToken);
}
}
}
finally
{
_isExecuting = false;
}
_directiveExecutionCoroutine = StartCoroutine(ProcessDirectiveQueue());
}
private static string BuildDirectiveToken(StoryDirectiveAsset directive, int directiveIndex)
@@ -119,6 +146,60 @@ namespace CustomComponent
}
}
private IEnumerator ProcessDirectiveQueue()
{
while (_pendingDirectives.Count > 0)
{
PendingDirectiveInvocation invocation = _pendingDirectives.Dequeue();
if (!_allowRepeatTrigger)
{
_queuedDirectiveTokens.Remove(invocation.DirectiveToken);
}
ExecuteDirective(invocation.Directive, invocation.TriggerType, invocation.TriggerId);
if (invocation.Directive.RequiresCompletion)
{
yield return WaitForDirectiveCompletion(invocation.Directive);
}
if (!_allowRepeatTrigger)
{
_consumedDirectiveTokens.Add(invocation.DirectiveToken);
}
}
_directiveExecutionCoroutine = null;
}
private IEnumerator WaitForDirectiveCompletion(StoryDirectiveAsset directive)
{
if (!(directive is StoryChangeBackgroundDirectiveAsset))
{
yield break;
}
int requestId = _lastBackgroundRequestId;
if (requestId <= 0)
{
yield break;
}
const float timeoutSeconds = 10f;
float elapsed = 0f;
while (_completedBackgroundRequestId < requestId)
{
elapsed += Time.unscaledDeltaTime;
if (elapsed >= timeoutSeconds)
{
Log.Warning("StoryDirector wait background transition timeout. requestId={0}", requestId.ToString());
break;
}
yield return null;
}
}
public void ExecuteStartDialog(int dialogId)
{
if (dialogId <= 0)
@@ -155,6 +236,8 @@ namespace CustomComponent
public void ExecuteChangeBackground(string backgroundAssetName)
{
_lastBackgroundRequestId = 0;
string assetName = string.IsNullOrWhiteSpace(backgroundAssetName)
? string.Empty
: backgroundAssetName.Trim();
@@ -164,39 +247,24 @@ namespace CustomComponent
return;
}
if (GameEntry.SpriteCache == null)
{
Log.Warning("StoryDirector change background failed. SpriteCache component is missing.");
return;
}
int requestVersion = ++_bgRequestVersion;
GameEntry.SpriteCache.GetSprite(_backgroundAssetNamePrefix + assetName,
sprite => { OnBackgroundLoaded(requestVersion, assetName, sprite); });
}
private void OnBackgroundLoaded(int requestVersion, string assetName, Sprite sprite)
{
if (requestVersion != _bgRequestVersion)
{
return;
}
if (sprite == null)
{
Log.Warning("StoryDirector change background failed. Loaded sprite is null for '{0}'.", assetName);
return;
}
if (_bgFormController == null)
{
_bgFormController = new BgFormController();
}
_bgFormController.OpenUI(new BgFormContext
int requestId = _nextBackgroundRequestId++;
_lastBackgroundRequestId = requestId;
int? formSerialId = _bgFormController.OpenUI(new BgFormContext
{
Sprite = sprite
BackgroundAssetName = _backgroundAssetNamePrefix + assetName,
TransitionRequestId = requestId
});
if (!formSerialId.HasValue)
{
Log.Warning("StoryDirector change background failed. BgForm open returned null.");
_completedBackgroundRequestId = Mathf.Max(_completedBackgroundRequestId, requestId);
}
}
public void ExecuteEndChapter(int chapterId)
@@ -208,6 +276,21 @@ namespace CustomComponent
GameEntry.Event.Fire(this, StoryChapterEndedEventArgs.Create(finalChapterId));
}
private void OnBgTransitionCompleted(object sender, GameFramework.Event.GameEventArgs e)
{
if (!(e is BgTransitionCompletedEventArgs args))
{
return;
}
if (args.RequestId <= 0)
{
return;
}
_completedBackgroundRequestId = Mathf.Max(_completedBackgroundRequestId, args.RequestId);
}
private static CombineFormContext BuildCombineFormContext(StoryCombineConfig config)
{
if (config != null && config.Slots != null && config.Slots.Count > 0)
@@ -355,4 +438,4 @@ namespace CustomComponent
};
}
}
}
}