Merge pull request #2 from SepComet/2.8

添加对话系统
This commit is contained in:
SepComet 2026-02-09 13:54:18 +08:00 committed by GitHub
commit c011c48bfe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
116 changed files with 3223 additions and 170 deletions

10
.gitignore vendored
View File

@ -84,4 +84,12 @@ crashlytics-build.properties
/Assets/RawResources /Assets/RawResources
/.vscode /.vscode
# Excel temporary lock files
~$*.xls
~$*.xlsx
~$*.xlsm
~$*.xlsb
/数据表/__pycache__

View File

@ -0,0 +1,7 @@
# 对话标识表 筛选用数据
# Id Title UIMode ChapterId
# int string DialogUIMode int
# 对话编号 策划备注 对话标识 对话形式 章节编号
1001 第一章介绍 Chapter1_Intro Mask 1.001
1002 第一章主流程 Chapter1_Main BottomBox 1.002
1003 第一章玩法开始前闲聊 Chapter1_SmallTalk1 Bubble 1.003

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 788b17ff3aef4cd4fb6c808826c875e5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,13 @@
# 对话内容表 筛选用数据
# Id SpeakerId Expression SpeakerName Direction Text Emphasis ChapterId DialogId
# int string ExpressionType string int string EmphasisType int int
# 对话行编号 策划备注 说话人Id 表情 显示人名 说话朝向 说话内容 演出效果 章节Id 对话Id
100100001 Id规则为 Null None Null 0 相传。 None 1.00100001 1001.00001
100100002 第1位数为章节Id Null None Null 0 Mask。 None 1.00100002 1001.00002
100100003 第2-4位数为对话Id Null None Null 0 很好。 None 1.00100003 1001.00003
100200001 第5-9位数为对话行Id Xu Normal 徐晟壹 0 你好,王。 None 1.00200001 1002.00001
100200002 Wang Normal 王可嘉 1 你好,徐。 None 1.00200002 1002.00002
100200003 Master Normal 李诫 1 你们好。 None 1.00200003 1002.00003
100300001 Npc1 None Null 0 这人谁啊? None 1.00300001 1003.00001
100300002 Npc2 None Null 0 不知道啊? None 1.00300002 1003.00002
100300003 Npc1 None Null 0 不知道你在这干嘛。 None 1.00300003 1003.00003

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 378604b840f56ae49831978cf0e0a6ea
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -5,4 +5,4 @@
1 菜单场景 Menu 1 1 菜单场景 Menu 1
2 战斗场景 Main 2 2 战斗场景 Main 2
3 压力测试场景 StressTest 0 3 压力测试场景 StressTest 0
4 玩法A测试场景 GameplayA 0 4 GameplayA 0

View File

@ -6,4 +6,7 @@
100 主菜单 MenuForm Default False True 100 主菜单 MenuForm Default False True
101 设置 SettingForm Default False True 101 设置 SettingForm Default False True
102 关于 AboutForm Default False True 102 关于 AboutForm Default False True
103 <09><><EFBFBD><EFBFBD><EFBFBD>淨A MVC<56><43><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD> CombineForm Default False True 103 组装玩法UI CombineForm Default False False
104 Mask对话UI MaskDialogForm Default False False
105 Bottom对话UI BottomBoxDialogForm Default False False
106 Bubble对话UI BubbleDialogForm Default True False

View File

@ -15,10 +15,12 @@ public partial class GameEntry : MonoBehaviour
{ {
public static BuiltinDataComponent BuiltinData { get; private set; } public static BuiltinDataComponent BuiltinData { get; private set; }
public static CombineComponent Combine { get; private set; } public static CombineComponent Combine { get; private set; }
public static DialogComponent Dialog { get; private set; }
private static void InitCustomComponents() private static void InitCustomComponents()
{ {
BuiltinData = UnityGameFramework.Runtime.GameEntry.GetComponent<BuiltinDataComponent>(); BuiltinData = UnityGameFramework.Runtime.GameEntry.GetComponent<BuiltinDataComponent>();
Combine = UnityGameFramework.Runtime.GameEntry.GetComponent<CombineComponent>(); Combine = UnityGameFramework.Runtime.GameEntry.GetComponent<CombineComponent>();
Dialog = UnityGameFramework.Runtime.GameEntry.GetComponent<DialogComponent>();
} }
} }

View File

@ -385,7 +385,7 @@ namespace CustomComponent
/// </summary> /// </summary>
private void RejectPlace(CombineDraggablePart part, string hint) private void RejectPlace(CombineDraggablePart part, string hint)
{ {
part.ReturnToSpawn(); part.ReturnToSpawnAnimated();
if (!string.IsNullOrEmpty(hint)) if (!string.IsNullOrEmpty(hint))
{ {

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 0103c893efce444d9c6fe671306746fe guid: cc0388c578bec9746813380eee9038d4
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,413 @@
using System.Collections.Generic;
using DataTable;
using Definition.Enum;
using Event;
using GameFramework.DataTable;
using GameFramework.Event;
using UI;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace CustomComponent
{
[DisallowMultipleComponent]
public class DialogComponent : GameFrameworkComponent
{
#region Property
[SerializeField] private float _playingSpeed = 1.0f;
private const int DialogChapterDivisor = 1000;
private const int LineChapterDivisor = 100000000;
private const int LineDialogDivisor = 100000;
private readonly Dictionary<int, DRDialog> _dialogMap = new();
private readonly Dictionary<int, List<DRDialogLine>> _dialogLinesMap = new();
private readonly Dictionary<int, int> _dialogFirstLineIdMap = new();
private IDataTable<DRDialog> _dtDialog;
private IDataTable<DRDialogLine> _dtDialogLine;
private DialogFormController _formController;
private DialogFormContext _formContext;
private int _currentChapterId;
private int _currentLineIndex = -1;
private bool _isInitialized;
private bool _isPlaying;
public float PlayingSpeed => _playingSpeed;
public bool IsInitialized => _isInitialized;
public bool IsPlaying => _isPlaying;
public int CurrentChapterId => _currentChapterId;
public int CurrentDialogId => _formContext != null ? _formContext.DialogId : 0;
public int CurrentLineId => _formContext != null ? _formContext.CurrentLineId : 0;
#endregion
private void Start()
{
GameEntry.Event.Subscribe(DialogNextLineRequestEventArgs.EventId, OnDialogNextLineRequest);
GameEntry.Event.Subscribe(DialogSkipRequestEventArgs.EventId, OnDialogSkipRequest);
GameEntry.Event.Subscribe(DialogStopRequestEventArgs.EventId, OnDialogStopRequest);
}
private void OnDestroy()
{
GameEntry.Event.Unsubscribe(DialogNextLineRequestEventArgs.EventId, OnDialogNextLineRequest);
GameEntry.Event.Unsubscribe(DialogSkipRequestEventArgs.EventId, OnDialogSkipRequest);
GameEntry.Event.Unsubscribe(DialogStopRequestEventArgs.EventId, OnDialogStopRequest);
}
public bool Init(int chapterId)
{
if (chapterId <= 0)
{
Log.Warning("Dialog init failed. chapterId must be positive.");
return false;
}
if (!EnsureDataTables())
{
return false;
}
StopDialog();
_dialogMap.Clear();
_dialogLinesMap.Clear();
_dialogFirstLineIdMap.Clear();
DRDialog[] dialogRows = _dtDialog.GetDataRows((a, b) => a.Id.CompareTo(b.Id));
for (int i = 0; i < dialogRows.Length; i++)
{
DRDialog dialogRow = dialogRows[i];
if (dialogRow == null)
{
continue;
}
if (ParseChapterIdFromDialogId(dialogRow.Id) != chapterId)
{
continue;
}
_dialogMap[dialogRow.Id] = dialogRow;
}
if (_dialogMap.Count == 0)
{
Log.Warning("Dialog init failed. No dialog rows found for chapter '{0}'.", chapterId.ToString());
return false;
}
DRDialogLine[] lineRows = _dtDialogLine.GetDataRows((a, b) => a.Id.CompareTo(b.Id));
for (int i = 0; i < lineRows.Length; i++)
{
DRDialogLine lineRow = lineRows[i];
if (lineRow == null)
{
continue;
}
if (ParseChapterIdFromLineId(lineRow.Id) != chapterId)
{
continue;
}
int dialogId = ParseDialogIdFromLineId(lineRow.Id);
if (!_dialogMap.ContainsKey(dialogId))
{
continue;
}
if (!_dialogLinesMap.TryGetValue(dialogId, out List<DRDialogLine> dialogLines))
{
dialogLines = new List<DRDialogLine>();
_dialogLinesMap.Add(dialogId, dialogLines);
}
dialogLines.Add(lineRow);
}
List<int> invalidDialogIds = new List<int>();
foreach (KeyValuePair<int, DRDialog> dialogPair in _dialogMap)
{
if (!_dialogLinesMap.TryGetValue(dialogPair.Key, out List<DRDialogLine> dialogLines) ||
dialogLines.Count == 0)
{
Log.Warning("Dialog init warning. Dialog '{0}' has no lines and will be ignored.",
dialogPair.Key.ToString());
invalidDialogIds.Add(dialogPair.Key);
continue;
}
dialogLines.Sort((a, b) => a.Id.CompareTo(b.Id));
_dialogFirstLineIdMap[dialogPair.Key] = dialogLines[0].Id;
}
for (int i = 0; i < invalidDialogIds.Count; i++)
{
_dialogMap.Remove(invalidDialogIds[i]);
}
if (_dialogMap.Count == 0)
{
Log.Warning("Dialog init failed. No valid dialog remains for chapter '{0}'.", chapterId.ToString());
return false;
}
EnsureFormController();
_formContext = null;
_currentChapterId = chapterId;
_currentLineIndex = -1;
_isInitialized = true;
_isPlaying = false;
return true;
}
public bool StartDialog(int dialogId)
{
if (!_isInitialized)
{
Log.Warning("Start dialog failed. Dialog component is not initialized.");
return false;
}
if (ParseChapterIdFromDialogId(dialogId) != _currentChapterId)
{
Log.Warning("Start dialog failed. Dialog '{0}' does not belong to chapter '{1}'.", dialogId.ToString(),
_currentChapterId.ToString());
return false;
}
if (!_dialogMap.TryGetValue(dialogId, out DRDialog dialogRow))
{
Log.Warning("Start dialog failed. Dialog '{0}' was not found in current chapter cache.",
dialogId.ToString());
return false;
}
if (!_dialogLinesMap.TryGetValue(dialogId, out List<DRDialogLine> dialogLines) || dialogLines.Count == 0)
{
Log.Warning("Start dialog failed. Dialog '{0}' has no playable lines.", dialogId.ToString());
return false;
}
if (_isPlaying)
{
StopDialog();
}
EnsureFormController();
if (_formContext == null)
{
_formContext = new DialogFormContext();
}
_formContext.ChapterId = _currentChapterId;
_formContext.DialogId = dialogRow.Id;
_formContext.DialogTitle = dialogRow.Title;
_formContext.DialogUIMode = dialogRow.UIMode;
_formContext.PlayingSpeed = Mathf.Max(0f, _playingSpeed);
_currentLineIndex = 0;
ApplyLineToContext(dialogLines[_currentLineIndex], _currentLineIndex, dialogLines.Count);
_isPlaying = true;
_formController.OpenUI(_formContext);
_formController.OnDialogStarted(_formContext);
_formController.OnDialogLineChanged(_formContext);
return true;
}
public bool NextLine()
{
if (!_isPlaying)
{
Log.Warning("Next line failed. No dialog is playing.");
return false;
}
if (!TryGetCurrentDialogLines(out List<DRDialogLine> dialogLines))
{
StopDialog();
return false;
}
int nextLineIndex = _currentLineIndex + 1;
if (nextLineIndex >= dialogLines.Count)
{
EndDialogInternal();
return true;
}
_currentLineIndex = nextLineIndex;
ApplyLineToContext(dialogLines[_currentLineIndex], _currentLineIndex, dialogLines.Count);
_formController.OnDialogLineChanged(_formContext);
return true;
}
public bool SkipDialog()
{
if (!_isPlaying)
{
Log.Warning("Skip dialog failed. No dialog is playing.");
return false;
}
EndDialogInternal();
return true;
}
public void StopDialog()
{
if (!_isPlaying)
{
return;
}
EndDialogInternal();
}
public void ClearRuntimeContext()
{
StopDialog();
_dialogMap.Clear();
_dialogLinesMap.Clear();
_dialogFirstLineIdMap.Clear();
_formContext = null;
_currentChapterId = 0;
_currentLineIndex = -1;
_isInitialized = false;
_isPlaying = false;
}
private bool EnsureDataTables()
{
_dtDialog = GameEntry.DataTable.GetDataTable<DRDialog>();
if (_dtDialog == null)
{
Log.Warning("Dialog init failed. Data table DRDialog is missing.");
return false;
}
_dtDialogLine = GameEntry.DataTable.GetDataTable<DRDialogLine>();
if (_dtDialogLine == null)
{
Log.Warning("Dialog init failed. Data table DRDialogLine is missing.");
return false;
}
return true;
}
private void EnsureFormController()
{
if (_formController == null)
{
_formController = new DialogFormController();
}
}
private bool TryGetCurrentDialogLines(out List<DRDialogLine> dialogLines)
{
dialogLines = null;
if (_formContext == null)
{
Log.Warning("Dialog state invalid. Form context is null.");
return false;
}
if (!_dialogLinesMap.TryGetValue(_formContext.DialogId, out dialogLines))
{
Log.Warning("Dialog state invalid. Dialog lines are missing for dialog '{0}'.",
_formContext.DialogId.ToString());
return false;
}
return true;
}
private void EndDialogInternal()
{
_isPlaying = false;
_currentLineIndex = -1;
_formController.OnDialogEnded(_formContext);
_formController.CloseUI();
}
private void ApplyLineToContext(DRDialogLine lineRow, int lineIndex, int totalLines)
{
_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;
_formContext.PlayingSpeed = Mathf.Max(0f, _playingSpeed);
_formContext.LineIndex = lineIndex;
_formContext.TotalLines = totalLines;
_formContext.IsLastLine = lineIndex >= totalLines - 1;
}
private static int ParseChapterIdFromDialogId(int dialogId)
{
return dialogId / DialogChapterDivisor;
}
private static int ParseChapterIdFromLineId(int lineId)
{
return lineId / LineChapterDivisor;
}
private static int ParseDialogIdFromLineId(int lineId)
{
return lineId / LineDialogDivisor;
}
#region Event Handlers
private void OnDialogNextLineRequest(object sender, GameEventArgs e)
{
if (!(e is DialogNextLineRequestEventArgs))
{
return;
}
NextLine();
}
private void OnDialogSkipRequest(object sender, GameEventArgs e)
{
if (!(e is DialogSkipRequestEventArgs))
{
return;
}
SkipDialog();
}
private void OnDialogStopRequest(object sender, GameEventArgs e)
{
if (!(e is DialogStopRequestEventArgs))
{
return;
}
StopDialog();
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d6174838c30e460429e5628757bbf015
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using CustomUtility;
using Definition;
using GameFramework.Resource;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace CustomComponent
{
public class SpriteCacheComponent : GameFrameworkComponent
{
[SerializeField] private float _pixelsPerUnit = 100f;
[SerializeField] private Vector2 _defaultPivot = new(0.5f, 0.5f);
private Dictionary<string, Sprite> _spriteCache;
private ResourceComponent _resource;
void Start()
{
_spriteCache = new Dictionary<string, Sprite>();
_resource = GameEntry.Resource;
}
public void GetSprite(string assetName, Action<Sprite> callback)
{
if (_spriteCache.TryGetValue(assetName, out var sprite))
{
callback?.Invoke(sprite);
return;
}
else
{
_resource.LoadAsset
(
AssetUtility.GetUIDialogAsset(assetName),
Constant.AssetPriority.UIFormAsset,
new LoadAssetCallbacks(
(resourcePath, asset, duration, userData) =>
{
Log.Debug(resourcePath);
Texture2D texture = asset as Texture2D;
if (texture != null)
{
Sprite newSprite = Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
_defaultPivot,
_pixelsPerUnit);
_spriteCache.Add(assetName, newSprite);
callback?.Invoke(newSprite);
}
},
(resourcePath, status, errorMessage, userData) =>
{
Log.Error("Can not load icon '{0}' from '{1}' with error message '{2}'.",
assetName,
resourcePath,
errorMessage);
}
)
);
}
}
private void OnDestroy()
{
_spriteCache.Clear();
_resource = null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42b4751aefa33c545a86f146a48536ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -9,7 +9,7 @@ using System;
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
namespace StarForce namespace DataTable
{ {
public static class BinaryReaderExtension public static class BinaryReaderExtension
{ {

View File

@ -0,0 +1,39 @@
using CustomUtility;
using Definition.Enum;
using UnityGameFramework.Runtime;
namespace DataTable
{
public class DRDialog : DataRowBase
{
private int m_Id;
/// <summary>
/// 获取对话编号。
/// </summary>
public override int Id => m_Id;
/// <summary>
/// 获取对话标识。
/// </summary>
public string Title { get; private set; }
/// <summary>
/// 获取对话形式。
/// </summary>
public DialogFormMode UIMode { get; private set; }
public override bool ParseDataRow(string dataRowString, object userData)
{
string[] fields = dataRowString.Split('\t');
int index = 1;
m_Id = int.Parse(fields[index++]);
index++;
Title = fields[index++];
UIMode = EnumUtility<DialogFormMode>.Get(fields[index++]);
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fb12692f2a7e6174eae3b0d28c769e55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
using CustomUtility;
using Definition.Enum;
using UnityGameFramework.Runtime;
namespace DataTable
{
public class DRDialogLine : DataRowBase
{
private int m_Id;
/// <summary>
/// 获取对话行编号
/// </summary>
public override int Id => m_Id;
/// <summary>
/// 获取说话人 Id。
/// </summary>
public string SpeakerId { get; private set; }
/// <summary>
/// 获取说话人表情。
/// </summary>
public ExpressionType Expression { get; private set; }
/// <summary>
/// 获取说话人显示名。
/// </summary>
public string SpeakerName { get; private set; }
/// <summary>
/// 获取说话人朝向。
/// </summary>
public int Direction { get; private set; }
/// <summary>
/// 获取对话内容。
/// </summary>
public string Text { get; private set; }
/// <summary>
/// 获取对话效果。
/// </summary>
public EmphasisType Emphasis { get; private set; }
public override bool ParseDataRow(string dataRowString, object userData)
{
string[] fields = dataRowString.Split('\t');
int index = 0;
index++;
m_Id = int.Parse(fields[index++]);
index++;
SpeakerId = fields[index++];
Expression = EnumUtility<ExpressionType>.Get(fields[index++]);
SpeakerName = fields[index++];
Direction = int.Parse(fields[index++]);
Text = fields[index++];
Emphasis = EnumUtility<EmphasisType>.Get(fields[index++]);
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc6d3e8e61ab627488e22bb5fc28f95d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -16,7 +16,7 @@ using System.Text;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
/// <summary> /// <summary>
/// 实体表。 /// 实体表。
@ -28,13 +28,7 @@ namespace StarForce
/// <summary> /// <summary>
/// 获取实体编号。 /// 获取实体编号。
/// </summary> /// </summary>
public override int Id public override int Id => m_Id;
{
get
{
return m_Id;
}
}
/// <summary> /// <summary>
/// 获取资源名称。 /// 获取资源名称。

View File

@ -16,7 +16,7 @@ using System.Text;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
/// <summary> /// <summary>
/// 音乐配置表。 /// 音乐配置表。

View File

@ -1,22 +1,8 @@
//------------------------------------------------------------ using System.IO;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
// 此文件由工具自动生成,请勿直接修改。
// 生成时间2021-06-16 21:54:35.610
//------------------------------------------------------------
using GameFramework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
/// <summary> /// <summary>
/// 场景配置表。 /// 场景配置表。

View File

@ -1,22 +1,8 @@
//------------------------------------------------------------ using System.IO;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
// 此文件由工具自动生成,请勿直接修改。
// 生成时间2021-06-16 21:54:35.625
//------------------------------------------------------------
using GameFramework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
/// <summary> /// <summary>
/// 声音配置表。 /// 声音配置表。

View File

@ -1,14 +1,4 @@
//------------------------------------------------------------ using GameFramework;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
// 此文件由工具自动生成,请勿直接修改。
// 生成时间2021-06-16 21:54:35.652
//------------------------------------------------------------
using GameFramework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -16,7 +6,7 @@ using System.Text;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
/// <summary> /// <summary>
/// 界面配置表。 /// 界面配置表。

View File

@ -1,14 +1,4 @@
//------------------------------------------------------------ using GameFramework;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
// 此文件由工具自动生成,请勿直接修改。
// 生成时间2021-06-16 21:54:35.666
//------------------------------------------------------------
using GameFramework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -16,7 +6,7 @@ using System.Text;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
/// <summary> /// <summary>
/// 声音配置表。 /// 声音配置表。

View File

@ -1,20 +1,14 @@
//------------------------------------------------------------ using GameFramework.DataTable;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework.DataTable;
using System; using System;
using Definition;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace StarForce namespace DataTable
{ {
public static class DataTableExtension public static class DataTableExtension
{ {
private const string DataRowClassPrefixName = "StarForce.DR"; private const string DataRowClassPrefixName = "DataTable.DR";
internal static readonly char[] DataSplitSeparators = new char[] { '\t' }; internal static readonly char[] DataSplitSeparators = new char[] { '\t' };
internal static readonly char[] DataTrimSeparators = new char[] { '\"' }; internal static readonly char[] DataTrimSeparators = new char[] { '\"' };

View File

@ -5,6 +5,7 @@
// Feedback: mailto:ellan@gameframework.cn // Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------ //------------------------------------------------------------
using Definition;
using GameFramework.Debugger; using GameFramework.Debugger;
using GameFramework.Localization; using GameFramework.Localization;
using UnityEngine; using UnityEngine;

View File

@ -5,7 +5,7 @@
// Feedback: mailto:ellan@gameframework.cn // Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------ //------------------------------------------------------------
namespace StarForce namespace Definition
{ {
public static partial class Constant public static partial class Constant
{ {

View File

@ -7,7 +7,7 @@
using UnityEngine; using UnityEngine;
namespace StarForce namespace Definition
{ {
public static partial class Constant public static partial class Constant
{ {

View File

@ -5,7 +5,7 @@
// Feedback: mailto:ellan@gameframework.cn // Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------ //------------------------------------------------------------
namespace StarForce namespace Definition
{ {
public static partial class Constant public static partial class Constant
{ {

View File

@ -0,0 +1,22 @@
namespace Definition.Enum
{
public enum DialogFormMode
{
None = 0,
/// <summary>
/// 黑屏白字
/// </summary>
Mask = 1,
/// <summary>
/// 底部对话框
/// </summary>
BottomBox = 2,
/// <summary>
/// 对话气泡
/// </summary>
Bubble = 3
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7a10763d137f413d828c534b0233f2a6
timeCreated: 1770600423

View File

@ -0,0 +1,13 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Definition.Enum
{
public enum EmphasisType
{
None,
Shake,
Blink,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96908bdc885697e4d9cb0f6627d13230
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Definition.Enum
{
public enum ExpressionType
{
None,
Normal,
Shock,
Happy,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 174e046d822a14d49843dc415067f13c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -38,5 +38,20 @@ namespace UI
/// 核心玩法A MVC测试界面。 /// 核心玩法A MVC测试界面。
/// </summary> /// </summary>
CombineForm = 103, CombineForm = 103,
/// <summary>
/// 蒙版剧情对话界面。
/// </summary>
MaskDialogForm = 104,
/// <summary>
/// 底部剧情对话界面。
/// </summary>
BottomBoxDialogForm = 105,
/// <summary>
/// 气泡剧情对话界面。
/// </summary>
BubbleDialogForm = 106,
} }
} }

View File

@ -7,6 +7,8 @@
using GameFramework.DataTable; using GameFramework.DataTable;
using System; using System;
using CustomUtility;
using DataTable;
using Entity; using Entity;
using Entity.EntityData; using Entity.EntityData;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;

View File

@ -0,0 +1,21 @@
using GameFramework;
using GameFramework.Event;
namespace Event
{
public class DialogNextLineRequestEventArgs : GameEventArgs
{
public static readonly int EventId = typeof(DialogNextLineRequestEventArgs).GetHashCode();
public override int Id => EventId;
public static DialogNextLineRequestEventArgs Create()
{
return ReferencePool.Acquire<DialogNextLineRequestEventArgs>();
}
public override void Clear()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de8ad9563f91a584da8c775e9fa916b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using GameFramework;
using GameFramework.Event;
namespace Event
{
public class DialogSkipRequestEventArgs : GameEventArgs
{
public static readonly int EventId = typeof(DialogSkipRequestEventArgs).GetHashCode();
public override int Id => EventId;
public static DialogSkipRequestEventArgs Create()
{
return ReferencePool.Acquire<DialogSkipRequestEventArgs>();
}
public override void Clear()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df023ccfed92923439c0f66ca1bd457c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using GameFramework;
using GameFramework.Event;
namespace Event
{
public class DialogStopRequestEventArgs : GameEventArgs
{
public static readonly int EventId = typeof(DialogStopRequestEventArgs).GetHashCode();
public override int Id => EventId;
public static DialogStopRequestEventArgs Create()
{
return ReferencePool.Acquire<DialogStopRequestEventArgs>();
}
public override void Clear()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d49a133afe91ef4e9bc7502e7adc71b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,10 +1,6 @@
//------------------------------------------------------------ using CustomUtility;
// Game Framework using DataTable;
// Copyright © 2013-2021 Jiang Yin. All rights reserved. using Definition;
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework.DataTable; using GameFramework.DataTable;
using GameFramework.Event; using GameFramework.Event;
using Scene; using Scene;

View File

@ -1,12 +1,6 @@
//------------------------------------------------------------ using GameFramework.Localization;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework.Localization;
using System; using System;
using Definition;
using StarForce; using StarForce;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>; using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

View File

@ -1,15 +1,10 @@
//------------------------------------------------------------ using GameFramework;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using GameFramework.Event; using GameFramework.Event;
using GameFramework.Resource; using GameFramework.Resource;
using System.Collections.Generic; using System.Collections.Generic;
using StarForce; using CustomUtility;
using DataTable;
using Definition;
using TMPro; using TMPro;
using UI; using UI;
using UnityEngine; using UnityEngine;
@ -28,6 +23,8 @@ namespace Procedure
"Sound", "Sound",
"UIForm", "UIForm",
"UISound", "UISound",
"Dialog",
"DialogLine"
}; };
private Dictionary<string, bool> _loadedFlag = new Dictionary<string, bool>(); private Dictionary<string, bool> _loadedFlag = new Dictionary<string, bool>();

View File

@ -87,7 +87,11 @@ namespace Procedure
{ {
base.OnEnter(procedureOwner); base.OnEnter(procedureOwner);
InitializeProcedureState(); //InitializeProcedureState();
GameEntry.Dialog.Init(1);
//GameEntry.Dialog.StartDialog(1001);
GameEntry.Dialog.StartDialog(1002);
} }
/// <summary> /// <summary>
@ -109,12 +113,16 @@ namespace Procedure
{ {
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (TryUpdateRound(realElapseSeconds)) if (GameEntry.Dialog.IsInitialized)
{ {
return;
} }
// if (TryUpdateRound(realElapseSeconds))
TryRestartScene(procedureOwner, realElapseSeconds); // {
// return;
// }
//
// TryRestartScene(procedureOwner, realElapseSeconds);
} }
#endregion #endregion

View File

@ -5,6 +5,9 @@
// Feedback: mailto:ellan@gameframework.cn // Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------ //------------------------------------------------------------
using CustomUtility;
using DataTable;
using Definition;
using Entity; using Entity;
using GameFramework; using GameFramework;
using GameFramework.DataTable; using GameFramework.DataTable;

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8cb383e8977814343a630c164eed6c51
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -340,7 +340,7 @@ namespace UI
.SetUpdate(true); .SetUpdate(true);
} }
private void ReturnToSpawnAnimated() public void ReturnToSpawnAnimated()
{ {
if (_spawnParent == null) if (_spawnParent == null)
{ {

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d81d2a322c2e93948b4d5aa7e36c99f2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ae5528a06773f5a45b75a99f619c2e22
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,26 @@
using Definition.Enum;
namespace UI
{
public class DialogFormContext : UIContext
{
public float PlayingSpeed = 1f;
public int ChapterId = 0;
public int DialogId = 0;
public string DialogTitle = string.Empty;
public DialogFormMode DialogUIMode = DialogFormMode.None;
public int CurrentLineId = 0;
public string SpeakerId = string.Empty;
public string SpeakerName = string.Empty;
public ExpressionType Expression = ExpressionType.None;
public int Direction = 0;
public string Text = string.Empty;
public EmphasisType Emphasis = EmphasisType.None;
public int LineIndex = -1;
public int TotalLines = 0;
public bool IsLastLine = false;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38341401b5804de47bb0a9a1c79d20d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3c721a41db518484e9a1771952725489
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,168 @@
using System;
using Definition.Enum;
using GameFramework.Event;
using UnityGameFramework.Runtime;
namespace UI
{
public class DialogFormController : IFormController<DialogFormContext>
{
private DialogFormContext _context;
private DialogFormBase _dialogForm;
private int? _formSerialId;
private bool _pendingRefresh;
public DialogFormController()
{
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OnOpenUIFormSuccess);
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, OnCloseUIFormComplete);
}
public int? OpenUI(DialogFormContext context)
{
if (context == null)
{
Log.Warning("DialogFormController open failed. context is null.");
return null;
}
_context = context;
UIFormId targetFormId = MapDialogFormId(context.DialogUIMode);
if (targetFormId == UIFormId.Undefined)
{
Log.Warning("DialogFormController open failed. Unsupported mode '{0}'.", context.DialogUIMode.ToString());
return null;
}
if (_dialogForm != null && _dialogForm.UIMode == context.DialogUIMode)
{
_dialogForm.StartDialog(context);
return _formSerialId;
}
CloseUI();
_pendingRefresh = true;
_formSerialId = GameEntry.UI.OpenUIForm(targetFormId, context);
return _formSerialId;
}
public void CloseUI()
{
_pendingRefresh = false;
if (_formSerialId.HasValue)
{
GameEntry.UI.CloseUIForm(_formSerialId.Value);
return;
}
if (_dialogForm != null)
{
_dialogForm.Close();
}
}
public void OnDialogStarted(DialogFormContext context)
{
_context = context;
TryRefreshUI();
}
public void OnDialogLineChanged(DialogFormContext context)
{
_context = context;
TryRefreshUI();
}
public void OnDialogEnded(DialogFormContext context)
{
_context = context;
}
~DialogFormController()
{
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OnOpenUIFormSuccess);
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, OnCloseUIFormComplete);
}
private void TryRefreshUI()
{
if (_context == null)
{
return;
}
if (_dialogForm == null)
{
_pendingRefresh = true;
return;
}
_dialogForm.StartDialog(_context);
_pendingRefresh = false;
}
private static UIFormId MapDialogFormId(DialogFormMode mode)
{
switch (mode)
{
case DialogFormMode.Mask:
return UIFormId.MaskDialogForm;
case DialogFormMode.BottomBox:
return UIFormId.BottomBoxDialogForm;
case DialogFormMode.Bubble:
throw new NotImplementedException("BubbleBox 对话框尚未实现");
default:
return UIFormId.Undefined;
}
}
private void OnOpenUIFormSuccess(object sender, GameEventArgs e)
{
if (!(e is OpenUIFormSuccessEventArgs args))
{
return;
}
if (!_formSerialId.HasValue)
{
return;
}
if (args.UIForm == null || args.UIForm.SerialId != _formSerialId.Value || args.UserData != _context)
{
return;
}
_dialogForm = args.UIForm.Logic as DialogFormBase;
if (_dialogForm == null)
{
Log.Warning("DialogFormController open success but form logic is invalid.");
return;
}
if (_pendingRefresh)
{
TryRefreshUI();
}
}
private void OnCloseUIFormComplete(object sender, GameEventArgs e)
{
if (!(e is CloseUIFormCompleteEventArgs args))
{
return;
}
if (args.SerialId != _formSerialId)
{
return;
}
_dialogForm = null;
_formSerialId = null;
_pendingRefresh = false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 52cc4e85f8030334689fdcff90748161
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c4b7102b2e334264398178de3d6325b4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,280 @@
using DG.Tweening;
using Definition.Enum;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
{
public class BottomDialogForm : DialogFormBase
{
public override DialogFormMode UIMode => DialogFormMode.BottomBox;
[SerializeField] private GameObject _speakerArea;
[SerializeField] private TMP_Text _speakerNameText;
[SerializeField] private TMP_Text _contentText;
[SerializeField] private Image _leftSprite;
[SerializeField] private Image _rightSprite;
[SerializeField] private int _leftSpritePosition = 450;
[SerializeField] private int _rightSpritePosition = -450;
[SerializeField] private float _moveDuration = 0.25f;
[SerializeField] private Ease _moveEase = Ease.OutCubic;
private readonly int _singleSpeakerCenterPosition = Screen.width / 2;
private string _leftSpeakerToken = string.Empty;
private string _rightSpeakerToken = string.Empty;
private Sequence _layoutSequence;
public override void StartDialog(DialogFormContext context)
{
if (context == null)
{
Log.Warning("BottomDialogForm start failed. context is null.");
return;
}
_context = context;
string speakerName = context.SpeakerName;
if (_speakerArea != null)
{
_speakerArea.SetActive(!string.IsNullOrEmpty(speakerName));
}
if (_speakerNameText != null)
{
_speakerNameText.text = speakerName;
}
PlayTypewriter(_contentText, context.Text, context.PlayingSpeed);
if (string.IsNullOrEmpty(speakerName))
{
ClearSpeakerState();
ApplySpeakerLayout(false, false, true);
return;
}
bool isRightSpeaker = context.Direction > 0;
if (isRightSpeaker)
{
_rightSpeakerToken = speakerName;
}
else
{
_leftSpeakerToken = speakerName;
}
bool hasLeftSpeaker = !string.IsNullOrEmpty(_leftSpeakerToken);
bool hasRightSpeaker = !string.IsNullOrEmpty(_rightSpeakerToken);
ApplySpeakerLayout(hasLeftSpeaker, hasRightSpeaker, false);
}
protected override void OnClose(bool isShutdown, object userData)
{
ClearSpeakerState();
KillLayoutTween();
ApplySpeakerLayout(false, false, true);
base.OnClose(isShutdown, userData);
}
private void ClearSpeakerState()
{
_leftSpeakerToken = string.Empty;
_rightSpeakerToken = string.Empty;
}
private void KillLayoutTween()
{
if (_layoutSequence != null)
{
_layoutSequence.Kill();
_layoutSequence = null;
}
}
private void ApplySpeakerLayout(bool hasLeftSpeaker, bool hasRightSpeaker, bool instant)
{
if (_leftSprite == null || _rightSprite == null)
{
return;
}
bool leftCurrentlyVisible = _leftSprite.gameObject.activeSelf;
bool rightCurrentlyVisible = _rightSprite.gameObject.activeSelf;
bool leftTargetVisible = hasLeftSpeaker;
bool rightTargetVisible = hasRightSpeaker;
float leftTargetX = GetTargetX(true, hasLeftSpeaker, hasRightSpeaker);
float rightTargetX = GetTargetX(false, hasLeftSpeaker, hasRightSpeaker);
KillLayoutTween();
PrepareStartState(
leftCurrentlyVisible,
rightCurrentlyVisible,
leftTargetVisible,
rightTargetVisible,
hasLeftSpeaker,
hasRightSpeaker);
if (instant || _moveDuration <= 0f)
{
SetSpritePosition(_leftSprite.rectTransform, leftTargetX);
SetSpritePosition(_rightSprite.rectTransform, rightTargetX);
SetSpriteVisible(_leftSprite, leftTargetVisible);
SetSpriteVisible(_rightSprite, rightTargetVisible);
return;
}
_layoutSequence = DOTween.Sequence();
Tween leftTween = CreateMoveTween(_leftSprite.rectTransform, leftTargetX);
if (leftTween != null)
{
_layoutSequence.Join(leftTween);
}
Tween rightTween = CreateMoveTween(_rightSprite.rectTransform, rightTargetX);
if (rightTween != null)
{
_layoutSequence.Join(rightTween);
}
if (_layoutSequence.active && _layoutSequence.Duration(false) > 0f)
{
_layoutSequence.OnComplete(() =>
{
SetSpriteVisible(_leftSprite, leftTargetVisible);
SetSpriteVisible(_rightSprite, rightTargetVisible);
_layoutSequence = null;
});
}
else
{
SetSpritePosition(_leftSprite.rectTransform, leftTargetX);
SetSpritePosition(_rightSprite.rectTransform, rightTargetX);
SetSpriteVisible(_leftSprite, leftTargetVisible);
SetSpriteVisible(_rightSprite, rightTargetVisible);
_layoutSequence.Kill();
_layoutSequence = null;
}
}
private void PrepareStartState(
bool leftCurrentlyVisible,
bool rightCurrentlyVisible,
bool leftTargetVisible,
bool rightTargetVisible,
bool hasLeftSpeaker,
bool hasRightSpeaker)
{
if (leftTargetVisible && !leftCurrentlyVisible)
{
float leftStartX = GetAppearStartX(true, rightCurrentlyVisible, hasLeftSpeaker, hasRightSpeaker);
SetSpritePosition(_leftSprite.rectTransform, leftStartX);
SetSpriteVisible(_leftSprite, true);
}
if (rightTargetVisible && !rightCurrentlyVisible)
{
float rightStartX = GetAppearStartX(false, leftCurrentlyVisible, hasLeftSpeaker, hasRightSpeaker);
SetSpritePosition(_rightSprite.rectTransform, rightStartX);
SetSpriteVisible(_rightSprite, true);
}
if (leftCurrentlyVisible && !leftTargetVisible)
{
SetSpriteVisible(_leftSprite, true);
}
if (rightCurrentlyVisible && !rightTargetVisible)
{
SetSpriteVisible(_rightSprite, true);
}
}
private float GetAppearStartX(bool isLeft, bool otherCurrentlyVisible, bool hasLeftSpeaker,
bool hasRightSpeaker)
{
if (hasLeftSpeaker && hasRightSpeaker)
{
// single -> multi: hidden side starts from center, then both move to side positions.
if (otherCurrentlyVisible)
{
return _singleSpeakerCenterPosition;
}
return isLeft ? _leftSpritePosition : _rightSpritePosition;
}
// single appears: active side starts from its side and moves to center.
return isLeft ? _leftSpritePosition : _rightSpritePosition;
}
private float GetTargetX(bool isLeft, bool hasLeftSpeaker, bool hasRightSpeaker)
{
if (hasLeftSpeaker && hasRightSpeaker)
{
return isLeft ? _leftSpritePosition : _rightSpritePosition;
}
if (hasLeftSpeaker || hasRightSpeaker)
{
// multi -> single: both move to center first, then inactive side hides.
return _singleSpeakerCenterPosition;
}
return isLeft ? _leftSpritePosition : _rightSpritePosition;
}
private Tween CreateMoveTween(RectTransform rectTransform, float targetX)
{
if (rectTransform == null)
{
return null;
}
if (Mathf.Abs(rectTransform.anchoredPosition.x - targetX) < 0.01f)
{
return null;
}
return rectTransform.DOAnchorPosX(targetX, _moveDuration).SetEase(_moveEase);
}
private static void SetSpriteVisible(Image spriteImage, bool visible)
{
if (spriteImage == null)
{
return;
}
spriteImage.gameObject.SetActive(visible);
}
private static void SetSpritePosition(RectTransform rectTransform, float xPosition)
{
if (rectTransform == null)
{
return;
}
Vector2 anchoredPosition = rectTransform.anchoredPosition;
anchoredPosition.x = xPosition;
rectTransform.anchoredPosition = anchoredPosition;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea6f55294a4cd2946a83649e7be82314
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,146 @@
using System.Collections;
using Definition.Enum;
using Event;
using TMPro;
using UnityEngine;
namespace UI
{
public abstract class DialogFormBase : UGuiForm
{
protected DialogFormContext _context;
private Coroutine _typingCoroutine;
private TMP_Text _typingTargetText;
private bool _isTypewriting;
public abstract DialogFormMode UIMode { get; }
public abstract void StartDialog(DialogFormContext context);
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (!(userData is DialogFormContext context))
{
return;
}
_context = context;
StartDialog(context);
}
protected override void OnClose(bool isShutdown, object userData)
{
StopTypewriter();
_context = null;
base.OnClose(isShutdown, userData);
}
public void OnClickNextLine()
{
if (CompleteTypewriterIfRunning())
{
return;
}
GameEntry.Event.Fire(this, DialogNextLineRequestEventArgs.Create());
}
public void OnClickSkipDialog()
{
GameEntry.Event.Fire(this, DialogSkipRequestEventArgs.Create());
}
public void OnClickStopDialog()
{
GameEntry.Event.Fire(this, DialogStopRequestEventArgs.Create());
}
protected void PlayTypewriter(TMP_Text targetText, string text, float charsPerSecond)
{
StopTypewriter();
if (targetText == null)
{
return;
}
string finalText = text ?? string.Empty;
_typingTargetText = targetText;
if (charsPerSecond <= 0f || string.IsNullOrEmpty(finalText))
{
targetText.text = finalText;
targetText.maxVisibleCharacters = int.MaxValue;
_isTypewriting = false;
return;
}
_isTypewriting = true;
_typingCoroutine = StartCoroutine(TypewriterRoutine(targetText, finalText, charsPerSecond));
}
protected void StopTypewriter()
{
if (_typingCoroutine != null)
{
StopCoroutine(_typingCoroutine);
_typingCoroutine = null;
}
_typingTargetText = null;
_isTypewriting = false;
}
private bool CompleteTypewriterIfRunning()
{
if (!_isTypewriting || _typingTargetText == null)
{
return false;
}
_typingTargetText.maxVisibleCharacters = int.MaxValue;
StopTypewriter();
return true;
}
private IEnumerator TypewriterRoutine(TMP_Text targetText, string finalText, float charsPerSecond)
{
targetText.text = finalText;
targetText.ForceMeshUpdate();
int totalCharacters = targetText.textInfo.characterCount;
if (totalCharacters <= 0)
{
targetText.maxVisibleCharacters = int.MaxValue;
_typingCoroutine = null;
_typingTargetText = null;
_isTypewriting = false;
yield break;
}
targetText.maxVisibleCharacters = 0;
float elapsed = 0f;
int visibleCharacters = 0;
while (visibleCharacters < totalCharacters)
{
elapsed += Time.unscaledDeltaTime;
int nextVisible = Mathf.Min(totalCharacters, Mathf.FloorToInt(elapsed * charsPerSecond));
if (nextVisible != visibleCharacters)
{
visibleCharacters = nextVisible;
targetText.maxVisibleCharacters = visibleCharacters;
}
yield return null;
}
targetText.maxVisibleCharacters = int.MaxValue;
_typingCoroutine = null;
_typingTargetText = null;
_isTypewriting = false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aafc42873758b514282b3a75e3ba4665
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
using Definition.Enum;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
{
public class MaskDialogForm : DialogFormBase
{
public override DialogFormMode UIMode => DialogFormMode.Mask;
[SerializeField] private Image _maskImage;
[SerializeField] private TMP_Text _text;
public override void StartDialog(DialogFormContext context)
{
if (context == null)
{
Log.Warning("MaskDialogForm start failed. context is null.");
return;
}
_context = context;
if (_maskImage != null)
{
_maskImage.gameObject.SetActive(true);
}
PlayTypewriter(_text, context.Text, context.PlayingSpeed);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a63462640e70af40972b9841beafe6c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,13 +1,9 @@
//------------------------------------------------------------ using GameFramework.DataTable;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework.DataTable;
using GameFramework.UI; using GameFramework.UI;
using System.Collections; using System.Collections;
using CustomUtility;
using DataTable;
using Definition;
using Procedure; using Procedure;
using StarForce; using StarForce;
using UnityEngine; using UnityEngine;

View File

@ -7,7 +7,7 @@
using GameFramework; using GameFramework;
namespace StarForce namespace CustomUtility
{ {
public static class AssetUtility public static class AssetUtility
{ {
@ -65,5 +65,10 @@ namespace StarForce
{ {
return Utility.Text.Format("Assets/GameMain/UI/UISounds/{0}.wav", assetName); return Utility.Text.Format("Assets/GameMain/UI/UISounds/{0}.wav", assetName);
} }
public static string GetUIDialogAsset(string assetName)
{
return Utility.Text.Format("Assets/GameMain/UI/Dialogs/{0}.prefab", assetName);
}
} }
} }

View File

@ -0,0 +1,27 @@
using System.Collections.Generic;
using UnityGameFramework.Runtime;
namespace CustomUtility
{
public static class EnumUtility<T> where T : struct, System.Enum
{
private static readonly Dictionary<string, T> _enumCache = new();
public static T Get(string value)
{
if (!_enumCache.TryGetValue(value, out T result))
{
if (System.Enum.TryParse(value, true, out result))
{
_enumCache[value] = result;
}
else
{
Log.Error($"Enum 解析失败:类型:{typeof(T).Name} 不包含值 {value}");
}
}
return result;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0591e8f95955014f8c2f8d9ba3c9247
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -9,7 +9,7 @@ using GameFramework;
using LitJson; using LitJson;
using System; using System;
namespace StarForce namespace CustomUtility
{ {
/// <summary> /// <summary>
/// LitJSON 函数集辅助器。 /// LitJSON 函数集辅助器。

View File

@ -1,13 +1,6 @@
//------------------------------------------------------------ using System;
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System; namespace CustomUtility
namespace StarForce
{ {
public static class WebUtility public static class WebUtility
{ {

View File

@ -0,0 +1,937 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &577377382380353288
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 478704929657922221}
- component: {fileID: 3708131469420921886}
- component: {fileID: 1177229253130277070}
- component: {fileID: 8970091190510382761}
m_Layer: 5
m_Name: NextLineButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &478704929657922221
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 577377382380353288}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4703471767818675053}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &3708131469420921886
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 577377382380353288}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1177229253130277070
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 577377382380353288}
m_CullTransparentMesh: 1
--- !u!114 &8970091190510382761
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 577377382380353288}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 0
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 3708131469420921886}
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 2327325990879817607}
m_TargetAssemblyTypeName: UI.DialogFormBase, Assembly-CSharp
m_MethodName: OnClickNextLine
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!1 &1001066407702705397
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3708143324325626536}
- component: {fileID: 6873615243070434848}
- component: {fileID: 6431296888118130931}
m_Layer: 5
m_Name: ContentText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3708143324325626536
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1001066407702705397}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7192457896265437741}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -200, y: -100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6873615243070434848
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1001066407702705397}
m_CullTransparentMesh: 1
--- !u!114 &6431296888118130931
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1001066407702705397}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: "\u674E\u8BEB"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 99d811b0183246646a2ce8df996f4bca, type: 2}
m_sharedMaterial: {fileID: -1106088975554028259, guid: 99d811b0183246646a2ce8df996f4bca,
type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4293980400
m_fontColor: {r: 0.9411765, g: 0.9411765, b: 0.9411765, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 70
m_fontSizeBase: 70
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &1966594047748998563
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7192457896265437741}
m_Layer: 5
m_Name: ContentArea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7192457896265437741
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1966594047748998563}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8762364413705962150}
- {fileID: 3708143324325626536}
m_Father: {fileID: 2330152971407905255}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: -50}
m_SizeDelta: {x: 0, y: -100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &2526382269717144677
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4594737505273760298}
- component: {fileID: 1858592913377441272}
- component: {fileID: 7945103967507868302}
m_Layer: 5
m_Name: LeftSpeaker
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &4594737505273760298
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2526382269717144677}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6089528910385973127}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 0, y: 0.5}
m_AnchoredPosition: {x: 450, y: -200}
m_SizeDelta: {x: 900, y: 1205.4878}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1858592913377441272
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2526382269717144677}
m_CullTransparentMesh: 1
--- !u!114 &7945103967507868302
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2526382269717144677}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3736358320082617150
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6089528910385973127}
m_Layer: 5
m_Name: SpeakerArea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6089528910385973127
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3736358320082617150}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4594737505273760298}
- {fileID: 1023330169278438415}
m_Father: {fileID: 4703471767818675053}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &3752068138017298928
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1792700702723432816}
- component: {fileID: 6515285980419930672}
- component: {fileID: 8566667250576683572}
m_Layer: 5
m_Name: bg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1792700702723432816
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3752068138017298928}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5100528644975002445}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6515285980419930672
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3752068138017298928}
m_CullTransparentMesh: 1
--- !u!114 &8566667250576683572
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3752068138017298928}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &4403804830056219076
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5100528644975002445}
m_Layer: 5
m_Name: NameArea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5100528644975002445
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4403804830056219076}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1792700702723432816}
- {fileID: 8619101080858191825}
m_Father: {fileID: 2330152971407905255}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 250, y: -50}
m_SizeDelta: {x: 500, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &4514918814497795030
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8762364413705962150}
- component: {fileID: 2347793963973952820}
- component: {fileID: 7254061520918156868}
m_Layer: 5
m_Name: bg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8762364413705962150
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4514918814497795030}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7192457896265437741}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2347793963973952820
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4514918814497795030}
m_CullTransparentMesh: 1
--- !u!114 &7254061520918156868
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4514918814497795030}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.39215687, g: 0.39215687, b: 0.39215687, a: 0.39215687}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &4995567450066526950
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4703471767818675053}
- component: {fileID: 4643264964412212504}
- component: {fileID: 2327325990879817607}
m_Layer: 5
m_Name: BottomBoxDialogForm
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4703471767818675053
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4995567450066526950}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6089528910385973127}
- {fileID: 2330152971407905255}
- {fileID: 478704929657922221}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!223 &4643264964412212504
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4995567450066526950}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 25
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!114 &2327325990879817607
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4995567450066526950}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ea6f55294a4cd2946a83649e7be82314, type: 3}
m_Name:
m_EditorClassIdentifier:
_playSpeed: 0
_speakerArea: {fileID: 3736358320082617150}
_speakerNameText: {fileID: 2470970474825277305}
_contentText: {fileID: 6431296888118130931}
_leftSprite: {fileID: 7945103967507868302}
_rightSprite: {fileID: 5385698520020721016}
_leftSpritePosition: 450
_rightSpritePosition: -450
_moveDuration: 0.25
_moveEase: 9
--- !u!1 &7381337123922490182
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8619101080858191825}
- component: {fileID: 5148587339817138371}
- component: {fileID: 2470970474825277305}
m_Layer: 5
m_Name: NameText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8619101080858191825
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7381337123922490182}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5100528644975002445}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 100, y: 0}
m_SizeDelta: {x: -200, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5148587339817138371
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7381337123922490182}
m_CullTransparentMesh: 1
--- !u!114 &2470970474825277305
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7381337123922490182}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: "\u674E\u8BEB"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 99d811b0183246646a2ce8df996f4bca, type: 2}
m_sharedMaterial: {fileID: -1106088975554028259, guid: 99d811b0183246646a2ce8df996f4bca,
type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4280163870
m_fontColor: {r: 0.11764706, g: 0.11764706, b: 0.11764706, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 50
m_fontSizeBase: 50
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &7436457223957886746
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1023330169278438415}
- component: {fileID: 23627497045646178}
- component: {fileID: 5385698520020721016}
m_Layer: 5
m_Name: RightSpeaker
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &1023330169278438415
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7436457223957886746}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6089528910385973127}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -450, y: -200}
m_SizeDelta: {x: 900, y: 1205.4878}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &23627497045646178
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7436457223957886746}
m_CullTransparentMesh: 1
--- !u!114 &5385698520020721016
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7436457223957886746}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7992201661324843749
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2330152971407905255}
m_Layer: 5
m_Name: DialogBox
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2330152971407905255
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7992201661324843749}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7192457896265437741}
- {fileID: 5100528644975002445}
m_Father: {fileID: 4703471767818675053}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: 0, y: 300}
m_SizeDelta: {x: 0, y: 600}
m_Pivot: {x: 0.5, y: 0.5}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 75da5a4ba56425747be081b9b396ba4e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More