Merge branch 'develop' into 情绪分支测试

This commit is contained in:
2025-05-13 18:35:24 +08:00
116 changed files with 11596 additions and 7129 deletions
@@ -73,6 +73,11 @@ namespace AibisDream
_dialogueRunner.StartDialogue("Start");
}
public string GetCurLocalizedTableName()
{
return _lineProvider.GetStringTableName();
}
public void StopDialog()
{
_dialogueRunner.Stop();
+1 -1
View File
@@ -23,7 +23,7 @@ namespace AibisDream
private void HandleLineOutput(LocalizedLine dialogueLine, Action onDialogueLineFinished)
{
DialogCanvasManager.Instance.ShowLine(dialogueLine.TextWithoutCharacterName.Text,
dialogueLine.GetCharacterVo(), onDialogueLineFinished, dialogueLine.IsAutoSkipLine());
dialogueLine.GetCharacterVo(), onDialogueLineFinished, dialogueLine.TextID, dialogueLine.IsAutoSkipLine());
}
public override void RunOptions(DialogueOption[] dialogueOptions, Action<int> onOptionSelected)
@@ -66,5 +66,10 @@ namespace AibisDream
// 加载
_localizationTable = new LocalizationTable(tableName);
}
public string GetStringTableName()
{
return _localizationTable.TableName;
}
}
}
@@ -10,7 +10,7 @@ public class PhysicCable : MonoBehaviour
// Start is called before the first frame update
void Start()
{
physicLine = transform.GetChild(0).GetComponent<PhysicLineSegment>();
physicLine = transform.GetComponent<PhysicLineSegment>();
}
public void Init(Vector3 endPos)
@@ -389,7 +389,10 @@ namespace AibisDream.FixSystem
}
// 切换相机
yield return CameraKit.Instance.SwitchCamera(CameraEnum.Expression);
expressionManager.OpenView();
yield return UIManager.Instance.GetPanel<PlayToolPanel>().FadeInAsync(0.5f);
//expressionManager.OpenView();
yield return CameraKit.Instance.SwitchCamera(CameraEnum.ExpressionDeep);
yield return UIManager.Instance.GetPanel<PlayToolPanel>().FadeOutAsync(0.5f);
}
@@ -16,6 +16,7 @@ namespace AibisDream.FixSystem
public float rotateDuration = 0.5f;
public float typeSpeed = 0.05f;
public int maxTextLine;
#endregion
@@ -26,9 +27,12 @@ namespace AibisDream.FixSystem
[SerializeField] private TMP_Text text;
[SerializeField] private SpriteRenderer screenImage;
private Material _imageMaterial;
private Action _nextStep;
private TextGenerator _generator;
private TextGenerationSettings _generationSettings;
private IUnRegister _plugOutRmv;
private Action _nextStep;
#endregion
@@ -42,6 +46,18 @@ namespace AibisDream.FixSystem
{
_textScreen = transform.Find("旋转屏幕");
_imageMaterial = screenImage.material;
_generator = new TextGenerator();
_generationSettings = new TextGenerationSettings
{
font = text.font.sourceFontFile,
fontSize = Mathf.RoundToInt(text.fontSize),
lineSpacing = text.lineSpacing,
horizontalOverflow = HorizontalWrapMode.Wrap,
verticalOverflow = VerticalWrapMode.Truncate,
generationExtents = new Vector2(text.rectTransform.rect.width, Mathf.Infinity),
resizeTextForBestFit = false
};
}
private void Register()
@@ -76,18 +92,43 @@ namespace AibisDream.FixSystem
{
text.text += "\n";
}
// 先估算新增行数
var targetLineNum = EstimateLineNum(targetText);
// 截断超出屏幕的部分
var oldText = "";
if (targetLineNum + text.textInfo.lineCount > maxTextLine)
{
var cutLineNum = targetLineNum + text.textInfo.lineCount - maxTextLine;
if (cutLineNum <= text.textInfo.lineCount)
{
var lastCharIndex = text.textInfo.lineInfo[cutLineNum - 1].lastCharacterIndex;
oldText = text.text[lastCharIndex..];
}
}
else
{
oldText = text.text;
}
var oldText = text.text;
var targetLength = text.text.Length + targetText.Length;
var targetLength = oldText.Length + targetText.Length;
// 逐个字符添加
yield return DOTween.To(() => text.text.Length, x => UpdateText(x, targetText, oldText), targetLength,
yield return DOTween.To(() => oldText.Length, x => UpdateText(x, targetText, oldText), targetLength,
targetText.Length * typeSpeed).WaitForCompletion();
EnumEventSystem.Global.Send(DialogEventEnum.LineShown);
yield return new WaitForSeconds(0.5f);
EnumEventSystem.Global.Send(DialogEventEnum.LineEnd);
_nextStep.Invoke();
}
private int EstimateLineNum(string str)
{
var height = _generator.GetPreferredHeight(str, _generationSettings);
var lineHeight = text.fontSize * 1.2f; // 简单估算行高
return Mathf.CeilToInt(height / lineHeight);
}
private void UpdateText(int currentLength, string nextText, string oldText)
{
@@ -170,7 +211,7 @@ namespace AibisDream.FixSystem
#region
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId ,bool isAutoSkip = false)
{
ShowTitle(character.GetActorName());
StartCoroutine(ShowText(dialogLine));
@@ -272,5 +272,6 @@ namespace AibisDream.Framework
Engine,
Gear,
EyeDeep,
ExpressionDeep,
}
}
@@ -29,17 +29,17 @@ namespace AibisDream.Framework
public class LocalizationTable
{
private readonly string _tableName;
public string TableName { get; }
private StringTable _stringTable;
public LocalizationTable(string tableName)
{
_tableName = tableName;
_stringTable = LocalizationSettings.StringDatabase.GetTable(_tableName);
TableName = tableName;
_stringTable = LocalizationSettings.StringDatabase.GetTable(TableName);
LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged;
Debug.Log($"表格{_tableName}已加载");
Debug.Log($"表格{TableName}已加载");
}
public void Dispose()
@@ -50,7 +50,7 @@ namespace AibisDream.Framework
private void OnLocaleChanged(Locale locale)
{
_stringTable = LocalizationSettings.StringDatabase.GetTable(_tableName);
_stringTable = LocalizationSettings.StringDatabase.GetTable(TableName);
}
public StringTableEntry this[string key] => _stringTable[key];
@@ -13,7 +13,7 @@ namespace AibisDream.Framework
{
#if UNITY_EDITOR
if (!sprite) return "";
// 先读Psd的路径
string psdPath = AssetDatabase.GetAssetPath(sprite);
var psdResPath = GetResourcePath(psdPath);
@@ -28,13 +28,12 @@ namespace AibisDream.Framework
// 提取文件名(不包括扩展名)
var purePath = psdResPath.Substring(0, lastDotIndex);
// 添加后缀
return purePath + "/" + sprite.name;
#else
return null;
#endif
}
private static string GetResourcePath(string absolutePath)
@@ -42,15 +41,7 @@ namespace AibisDream.Framework
const string resourcesFolderName = "Resources/";
int index = absolutePath.IndexOf(resourcesFolderName, StringComparison.Ordinal);
if (index >= 0)
{
// 获取 "Resources/" 之后的部分
return absolutePath.Substring(index + resourcesFolderName.Length);
}
else
{
return absolutePath;
}
return index >= 0 ? absolutePath[(index + resourcesFolderName.Length)..] : absolutePath;
}
public static Sprite LoadSpriteFromPsd(string path)
@@ -58,7 +49,7 @@ namespace AibisDream.Framework
int lastIndex = path.LastIndexOf('/');
string spriteName = path.Substring(lastIndex + 1);
string resPath = path.Substring(0, lastIndex);
// 加载
var sprites = Resources.LoadAll<Sprite>(resPath);
@@ -72,39 +63,14 @@ namespace AibisDream.Framework
return null;
}
public static T LoadAddressableSync<T>(string key)
public static T LoadAssetSync<T>(string key) where T : UnityEngine.Object
{
T result = default;
var operation = Addressables.LoadAssetAsync<T>(key);
// 运行协程等待加载完成
GameManager.Instance.StartCoroutine(LoadCoroutine(operation, loadedObject => result = loadedObject));
// 等待协程完成(阻塞主线程)
while (!operation.IsDone)
{
// 主动让出一帧
System.Threading.Thread.Sleep(1);
}
operation.WaitForCompletion();
return result;
}
public static IEnumerator LoadCoroutine<T>(AsyncOperationHandle<T> operation, Action<T> onComplete)
{
yield return operation;
if (operation.Status == AsyncOperationStatus.Succeeded)
{
onComplete?.Invoke(operation.Result);
}
else
{
Debug.LogError("Failed to load addressable");
}
Addressables.Release(operation);
return operation.Result;
}
}
}
@@ -0,0 +1,115 @@
using UnityEngine;
using DG.Tweening;
using System;
namespace AibisDream
{
[RequireComponent(typeof(LineRenderer))]
public class ExpressionCable : MonoBehaviour
{
private Transform _start;
private Transform _end;
private LineRenderer _lineRenderer;
private Vector3[] _points;
private ExpressionCableSystem _cableSystem;
[SerializeField]
private CableConfig config = CableConfig.GeneDefaultConfig();
public void Initialize(Transform start, Transform end)
{
_start = start;
_end = end;
_lineRenderer = GetComponent<LineRenderer>();
_lineRenderer.positionCount = config.resolution;
InitPoints();
}
private void InitPoints()
{
_points = new Vector3[config.resolution];
for (int i = 0; i < config.resolution; i++)
{
float t = i / (float)(config.resolution - 1);
_points[i] = Vector3.Lerp(_start.position, _end.position, t);
}
}
private void FixedUpdate()
{
DrawLine();
}
void DrawLine()
{
var points = UpdateRope();
for (int i = 0; i < config.resolution; i++)
{
_lineRenderer.SetPosition(i, points[i] + Vector3.forward * -.3f);
}
}
Vector3[] UpdateRope()
{
float t = Mathf.InverseLerp(config.dstMin, config.dstMax, (_start.position - _end.position).magnitude);
float F = Mathf.Lerp(config.forceMin, config.forceMax, t);
_points[0] = _start.position;
_points[^1] = _end.position;
for (int ik = 0; ik < config.k; ik++)
{
for (int i = 1; i < _points.Length - 1; i++)
{
Vector3 offsetPrev = _points[i - 1] - _points[i];
Vector3 offsetNext = _points[i + 1] - _points[i];
Vector3 velocity = offsetPrev.normalized * (offsetPrev.magnitude * F) +
offsetNext.normalized * (offsetNext.magnitude * F);
_points[i] += velocity * Time.deltaTime / config.k;
}
for (int i = 1; i < _points.Length - 1; i++)
{
_points[i] += Vector3.down * (9.8f * Time.deltaTime) / config.k;
}
}
return _points;
}
public void SetEndPos(Transform endPos)
{
_end = endPos;
}
public void UpdateEndPosition(Vector3 position)
{
if (_end != null)
{
_end.position = position;
}
}
}
[Serializable]
public struct CableConfig
{
public int resolution;
public float dstMin;
public float dstMax;
public float forceMin;
public float forceMax;
public int k;
public static CableConfig GeneDefaultConfig()
{
return new CableConfig
{
resolution = 10,
dstMin = 0.1f,
dstMax = 1.0f,
forceMin = 0.1f,
forceMax = 150f,
k = 10
};
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c72154e06027eb4698fc7da159c2d6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,83 @@
using UnityEngine;
using AibisDream.FixSystem;
using System.Collections.Generic;
namespace AibisDream
{
public class ExpressionCableSystem : MonoBehaviour
{
[Header("电源子模块")]
public ExpressionPowerSource powerSource;
private ExpressionManager _expressionManager;
private ExpressionSubSystem[] _expressionSubSystems;
private const float MAX_DISTANCE = 1f; // 最大检测距离
private void Awake()
{
// 自动查找所有子物体中的表达子模块
_expressionSubSystems = GetComponentsInChildren<ExpressionSubSystem>();
}
private void Start()
{
_expressionManager = transform.parent.GetComponent<ExpressionManager>();
InitializeSystem();
}
private void InitializeSystem()
{
// 初始化表达子模块
foreach (var subSystem in _expressionSubSystems)
{
subSystem.Initialize(this);
}
}
// 当插头插入插槽时调用
public void OnPlugInserted(int subSystemIndex, int socketIndex)
{
_expressionManager.AdjustValue(subSystemIndex, 1);
}
// 当插头拔出插槽时调用
public void OnPlugRemoved(int subSystemIndex, int socketIndex)
{
_expressionManager.AdjustValue(subSystemIndex, -1);
}
public void Reset()
{
powerSource.Reset();
foreach (var subSystem in _expressionSubSystems)
{
subSystem.Reset();
}
}
public bool TryFindClosestSocket(Vector3 sourcePos, out ISocket targetSocket)
{
targetSocket = null;
float minDistance = MAX_DISTANCE;
// 遍历所有子模块
foreach (var subSystem in _expressionSubSystems)
{
// 遍历子模块中的所有插槽
foreach (var socket in subSystem.GetSockets())
{
if (!socket.IsAvailable()) continue;
float distance = Vector3.Distance(sourcePos, socket.GetSocketPos());
if (distance < minDistance)
{
minDistance = distance;
targetSocket = socket;
}
}
}
return targetSocket != null;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b20aec8808a25c4b9607bbe72858b7a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -14,7 +14,6 @@ namespace AibisDream
public class ExpressionManager : MonoBehaviour
{
public GameObject expressView;
public Slider[] sliders; // A, P, R, E, T
public TMP_Text totalPointsText;
public int totalPoints = 10;
@@ -31,35 +30,24 @@ namespace AibisDream
private DriverDatabase db = new DriverDatabase();
private List<GameObject> currentResultButtons = new List<GameObject>();
void Start()
{
CloseView();
//CloseView();
FixSystemCenter.SystemDic.Register(this);
var virtualCam = transform.Find("Expression Camera").GetComponent<ICinemachineCamera>();
var virtualCam2 = transform.Find("Expression Deep Camera").GetComponent<ICinemachineCamera>();
CameraKit.Instance.RegisterCamera(CameraEnum.Expression, virtualCam);
CameraKit.Instance.RegisterCamera(CameraEnum.ExpressionDeep, virtualCam2);
db.LoadFromCSV(Path.Combine(Application.streamingAssetsPath, "drivers.csv"));
for (int i = 0; i < sliders.Length; i++)
{
int index = i;
Transform plus = sliders[i].transform.Find("Plus");
if (plus != null && plus.TryGetComponent(out Button plusBtn))
plusBtn.onClick.AddListener(() => AdjustValue(index, 1));
Transform minus = sliders[i].transform.Find("Minus");
if (minus != null && minus.TryGetComponent(out Button minusBtn))
minusBtn.onClick.AddListener(() => AdjustValue(index, -1));
}
matchButton.onClick.AddListener(MatchDriver);
applyAndTestButton.onClick.AddListener(ApplyAndTestDriver);
UpdateUI();
}
public void OpenView()
{
expressView.SetActive(true);
@@ -70,7 +58,7 @@ namespace AibisDream
expressView.SetActive(false);
}
void AdjustValue(int index, int delta)
public void AdjustValue(int index, int delta)
{
if (delta > 0 && totalPoints <= 0) return;
if (delta < 0 && valuesCurrent[index] <= 0) return;
@@ -84,13 +72,6 @@ namespace AibisDream
void UpdateUI()
{
for (int i = 0; i < sliders.Length; i++)
{
sliders[i].value = valuesCurrent[i];
Transform valueTextTransform = sliders[i].transform.Find("Value");
if (valueTextTransform != null && valueTextTransform.TryGetComponent(out TMP_Text valueText))
valueText.text = valuesCurrent[i].ToString();
}
totalPointsText.text = $"剩余点数: {totalPoints}";
}
@@ -132,7 +113,6 @@ namespace AibisDream
currentDriver = driver;
driverSlotText.text = $"Driver: {driver.Name}";
logOutput.text = $"已选中驱动:{driver.Name},请点击应用并测试以运行。";
// 保留面板,不关闭 matchResultsPanel
}
void ApplyAndTestDriver()
@@ -166,4 +146,4 @@ namespace AibisDream
currentUser=userName;
}
}
}
}
@@ -0,0 +1,163 @@
using UnityEngine;
using AibisDream.FixSystem;
using UnityEngine.EventSystems;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using DG.Tweening;
namespace AibisDream
{
[RequireComponent(typeof(EventTriggerEx))]
public class ExpressionPlug : MonoBehaviour, IInteraction
{
private static readonly int ShineFade = Shader.PropertyToID("_ShineFade");
private Vector3 _startPos;
private readonly Vector3 _pickupOffset = new(0, 0, 0);
private readonly Quaternion _pickupRotationOffset = Quaternion.Euler(0, 0, 150);
private readonly Quaternion _initRotation = Quaternion.Euler(0, 0, 180);
private ExpressionCableSystem _cableSystem;
private SpriteRenderer _sprite;
private Transform _plugRootPos;
private EventTriggerEx _trigger;
private ISocket _currentSocket;
private ExpressionCable _cable; // 对应的线缆
private bool _isDragging;
private bool _isPhysicCableActive;
[Header("调试设置")]
public float detectRadius = 1f; // 增加检测半径
public LayerMask socketLayer; // 设置插槽层级
private void Awake()
{
InitComponentRef();
EventRegister();
_startPos = transform.position;
}
private void InitComponentRef()
{
_cableSystem = GetComponentInParent<ExpressionCableSystem>();
_sprite = GetComponent<SpriteRenderer>();
_plugRootPos = transform.GetChild(0);
_trigger = GetComponent<EventTriggerEx>();
}
private void EventRegister()
{
_trigger.Register(EventTriggerType.Drag, OnDrag);
_trigger.Register(EventTriggerType.PointerDown, OnPointerDown);
_trigger.Register(EventTriggerType.PointerUp, OnPointerUp);
}
private void OnDrag(BaseEventData eventData)
{
if (!IsAvailable) return;
if (!_isDragging) return;
if (eventData is PointerEventData pointerData)
{
transform.position = CommonUtil.GetMouseWorldPos(pointerData.position, transform);
UpdateCable();
}
}
private void OnPointerDown(BaseEventData eventData)
{
if (!IsAvailable) return;
_isDragging = true;
if (_currentSocket != null)
{
PullUpSocket();
}
AdjustPlugPos();
_sprite.enabled = true;
}
private void OnPointerUp(BaseEventData eventData)
{
_isDragging = false;
// 寻找最近的可用插槽
if (_cableSystem.TryFindClosestSocket(transform.position, out var socket))
{
InsertSocket(socket);
}
else
{
ReturnToStartPosition();
}
}
private void InsertSocket(ISocket targetSocket)
{
// 修改插头位置
transform.position = targetSocket.GetSocketPos();
_cable.SetEndPos(transform);
// 处理插槽插入
_currentSocket = targetSocket;
targetSocket.PlugIn();
_sprite.enabled = false;
}
public void PullUpSocket()
{
// 修改线缆终点
_cable.SetEndPos(_plugRootPos);
// 处理插槽拔出
_currentSocket?.PlugOut();
_sprite.enabled = true;
_currentSocket = null;
}
public void ReturnToStartPosition()
{
transform.DOMove(_startPos, 0.1f);
transform.rotation = _initRotation;
_cable.SetEndPos(_plugRootPos);
}
private void AdjustPlugPos()
{
transform.position += _pickupOffset;
transform.rotation = _pickupRotationOffset;
}
public void SetCable(ExpressionCable cable)
{
_cable = cable;
}
private void UpdateCable()
{
if (_cable != null)
{
_cable.UpdateEndPosition(_plugRootPos.position);
}
}
public bool IsActive => true;
public bool IsAvailable => true;
public GameObject GetGameObject()
{
return gameObject;
}
// 用于调试
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, detectRadius);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e7a3d02c9c5f764fa1bc93f109a3447
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,45 @@
using UnityEngine;
using AibisDream.FixSystem;
namespace AibisDream
{
public class ExpressionPowerSource : MonoBehaviour
{
[Header("插头设置")]
public Transform[] plugGroups; // 在编辑器中直接拖拽设置插头组
private void Start()
{
// 初始化每个插头组
foreach (var group in plugGroups)
{
var plug = group.GetComponentInChildren<ExpressionPlug>();
var cable = group.GetComponentInChildren<ExpressionCable>();
var rootPos = group.Find("CableRoot");
if (plug != null && cable != null && rootPos != null)
{
cable.Initialize(rootPos, plug.transform.GetChild(0));
plug.SetCable(cable);
}
else
{
Debug.LogWarning($"插头组 {group.name} 缺少必要组件");
}
}
}
public void Reset()
{
// 重置所有插头
foreach (var group in plugGroups)
{
var plug = group.GetComponentInChildren<ExpressionPlug>();
if (plug != null)
{
plug.ReturnToStartPosition();
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fda4de3e06bfb5044ac87fd4e5c9f5e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,48 @@
using UnityEngine;
using AibisDream.FixSystem;
namespace AibisDream
{
public class ExpressionSocket : MonoBehaviour, ISocket
{
private int _subSystemIndex; // 所属表达子模块的索引
private int _socketIndex; // 插槽在子模块中的索引
private bool _isOccupied;
private ExpressionCableSystem _cableSystem;
public void Initialize(int subSystemIndex, int socketIndex)
{
_subSystemIndex = subSystemIndex;
_socketIndex = socketIndex;
_cableSystem = GetComponentInParent<ExpressionCableSystem>();
}
public void PlugIn()
{
if (!_isOccupied)
{
_isOccupied = true;
_cableSystem.OnPlugInserted(_subSystemIndex, _socketIndex);
}
}
public void PlugOut()
{
if (_isOccupied)
{
_isOccupied = false;
_cableSystem.OnPlugRemoved(_subSystemIndex, _socketIndex);
}
}
public Vector3 GetSocketPos()
{
return transform.position;
}
public bool IsAvailable()
{
return !_isOccupied;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 400d314e97bc045419d11ac25d78f61d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,47 @@
using UnityEngine;
using AibisDream.FixSystem;
using System.Collections.Generic;
namespace AibisDream
{
public class ExpressionSubSystem : MonoBehaviour
{
[Header("子模块设置")]
public string expressionName; // 表达名称
public int subSystemIndex; // 子模块索引
private ExpressionCableSystem _cableSystem;
private ExpressionSocket[] _sockets;
private void Awake()
{
// 自动查找所有子物体中的插槽
_sockets = GetComponentsInChildren<ExpressionSocket>();
}
public void Initialize(ExpressionCableSystem cableSystem)
{
_cableSystem = cableSystem;
// 初始化所有插槽
for (int i = 0; i < _sockets.Length; i++)
{
_sockets[i].Initialize(subSystemIndex, i);
}
}
public void Reset()
{
// 重置所有插槽状态
foreach (var socket in _sockets)
{
socket.PlugOut();
}
}
public IEnumerable<ExpressionSocket> GetSockets()
{
return _sockets;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a589bca4a2e605d4caf6b56c5d86610f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+4 -4
View File
@@ -36,7 +36,7 @@ public class TaskManager : MonoBehaviour
}
[YarnCommand("task_moveIn")]
// [YarnCommand("task_moveIn")]
public void Task_moveIn()
{
AudioManager.Instance.PlaySfx("event:/Scriptal/taskmanager");
@@ -44,7 +44,7 @@ public class TaskManager : MonoBehaviour
}
[YarnCommand("task_moveOut")]
// [YarnCommand("task_moveOut")]
public void Task_moveOut()
{
AudioManager.Instance.PlaySfx("event:/Scriptal/taskmanager");
@@ -81,7 +81,7 @@ public class TaskManager : MonoBehaviour
UpdateTaskUI();
}
[YarnCommand("complete_task")]
// [YarnCommand("complete_task")]
public void CompleteTask(string taskText)
{
TaskEntry task = FindTaskByText(tasks, taskText);
@@ -96,7 +96,7 @@ public class TaskManager : MonoBehaviour
}
}
[YarnCommand("clear_tasks")]
// [YarnCommand("clear_tasks")]
public void ClearTasks()
{
tasks.Clear(); // 清空任务列表
+1 -1
View File
@@ -21,7 +21,7 @@ namespace AibisDream
_ => HideDialog());
}
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
Debug.Log("CenterOption只显示选项");
}
+1 -1
View File
@@ -44,7 +44,7 @@ namespace AibisDream
});
}
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
// 把原有对话清掉
ClearBox();
+2 -1
View File
@@ -85,8 +85,9 @@ namespace AibisDream
/// <param name="dialogLine">对话内容</param>
/// <param name="character">角色内容</param>
/// <param name="nextStep">下一步</param>
/// <param name="lineId">行号</param>
/// <param name="isAutoSkip">是否自动跳过,默认为false</param>
public virtual void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public virtual void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
gameObject.SetActive(true);
@@ -38,7 +38,7 @@ namespace AibisDream
_dialogViews.ForEach(item => item.HideDialog());
}
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
gameObject.SetActive(true);
// 根据角色信息气泡
@@ -46,7 +46,7 @@ namespace AibisDream
// 处理其他泡泡
ProcessOtherBox();
// 显示对话
_currentView.ShowLine(dialogLine, character, nextStep, isAutoSkip);
_currentView.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip);
}
public void ShowOptions(DialogOption[] options)
@@ -22,7 +22,10 @@ namespace AibisDream
public override void OnSingletonInit()
{
InitEvent();
}
private void Start()
{
// 默认对话框直接加载
var box = transform.Find("Dialog Box").GetComponent<IDialogView>();
RegisterDialogView(DialogViewType.OldBox, box);
@@ -30,10 +33,8 @@ namespace AibisDream
RegisterDialogView(DialogViewType.CenterText, centerText);
var centerOption = transform.Find("Center Option").GetComponent<IDialogView>();
RegisterDialogView(DialogViewType.CenterOption, centerOption);
}
private void Start()
{
RegisterDialogView(DialogViewType.Task, UIManager.Instance.GetPanel<TaskPanel>());
_curView = _dialogViewDict[DialogViewType.OldBox];
}
@@ -93,7 +94,7 @@ namespace AibisDream
#region
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
// 根据DialogViewType确定在哪个对话框显示
if (character.dialogViewType == DialogViewType.Default)
@@ -105,7 +106,7 @@ namespace AibisDream
_lastShowView = _curView;
// 没有指定对话框,就用当前激活的
_curView.ShowLine(dialogLine, character, nextStep, isAutoSkip);
_curView.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip);
}
else if (_dialogViewDict.TryGetValue(character.dialogViewType, out var view))
{
@@ -116,7 +117,7 @@ namespace AibisDream
_lastShowView = view;
// 对于指定了对话框的,就在指定对话框显示
view.ShowLine(dialogLine, character, nextStep, isAutoSkip);
view.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip);
}
else
{
@@ -208,6 +209,7 @@ namespace AibisDream
OldBox,
Screen,
CenterText,
CenterOption
CenterOption,
Task
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ namespace AibisDream
{
public interface IDialogView
{
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false);
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId ,bool isAutoSkip = false);
public void ShowOptions(DialogOption[] dialogueOptions);
@@ -0,0 +1,31 @@
using TMPro;
using UnityEngine;
using UnityEngine.Localization.Components;
namespace AibisDream
{
[RequireComponent(typeof(TMP_Text))]
[RequireComponent(typeof(LocalizeStringEvent))]
public class LocalizedText : MonoBehaviour
{
private TMP_Text _text;
private LocalizeStringEvent _localizeEvent;
private void OnUpdateString(string text)
{
var textArr = text.Split(":");
_text.text = textArr.Length > 1 ? textArr[1].Trim() : text;
}
public void SetLocalizedText(string table, string entry)
{
_text = GetComponent<TMP_Text>();
_localizeEvent = GetComponent<LocalizeStringEvent>();
_localizeEvent.OnUpdateString.AddListener(OnUpdateString);
_localizeEvent.SetTable(table);
_localizeEvent.SetEntry(entry);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4c9c71a7e9c9455d955ff20b5db823a1
timeCreated: 1746702086
@@ -54,7 +54,7 @@ namespace AibisDream
#endregion
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
gameObject.SetActive(true);
+163
View File
@@ -0,0 +1,163 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using DG.Tweening;
using TMPro;
using UnityEngine;
using Yarn.Unity;
namespace AibisDream
{
public class TaskPanel : MonoBehaviour, IUIPanel, IDialogView
{
private RectTransform _rectTransform;
private Transform _taskListParent;
private GameObject _taskItemPrefab;
private GameObject TaskItemPrefab
{
get
{
if (_taskItemPrefab == null)
{
_taskItemPrefab = ResourceKit.LoadAssetSync<GameObject>(ConstRef.TaskItemName);
}
return _taskItemPrefab;
}
}
private readonly Dictionary<string, LocalizedText> _taskDict = new();
private void Awake()
{
_rectTransform = GetComponent<RectTransform>();
_taskListParent = transform.Find("Record");
EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, ClearTasks);
EnumEventSystem.Global.Register(EventEnum.NextYarn, ClearTasks);
}
#region
public void CompleteTask(string lineId)
{
if (_taskDict.TryGetValue(lineId, out var taskItem))
{
var taskText = taskItem.GetComponent<TMP_Text>();
taskText.fontStyle |= FontStyles.Strikethrough;
taskText.color = Color.gray;
}
}
public void ClearTasks()
{
foreach (var task in _taskDict)
{
Destroy(task.Value.gameObject);
}
_taskDict.Clear();
}
#endregion
#region
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
var taskItem = Instantiate(TaskItemPrefab, _taskListParent);
// 设置本地化数据
var localize = taskItem.GetComponent<LocalizedText>();
localize.SetLocalizedText(DialogController.Instance.GetCurLocalizedTableName(), lineId);
_taskDict[lineId] = localize;
EnumEventSystem.Global.Send(DialogEventEnum.LineShown);
EnumEventSystem.Global.Send(DialogEventEnum.LineEnd);
nextStep.Invoke();
}
public void ShowOptions(DialogOption[] dialogueOptions)
{
Debug.Log("Task 面板不能显示选项");
}
public void HideDialog()
{
// HideDialog应该由其他函数控制
}
public bool TrySkipLine(bool isForceSkip = false)
{
// 这里不能跳过对话
return true;
}
public void NextStep()
{
// 这里不能手动跳到下一行
}
#endregion
#region
public bool IsOpen { get; private set;}
public void Show()
{
gameObject.SetActive(true);
AudioManager.Instance.PlaySfx("event:/Scriptal/taskmanager");
// 下移
_rectTransform.DOAnchorPosY(-350, 1f).OnComplete(() =>
{
IsOpen = true;
});
}
public void Hide()
{
// 上移
AudioManager.Instance.PlaySfx("event:/Scriptal/taskmanager");
_rectTransform.DOAnchorPosY(0, 1f).OnComplete(() =>
{
gameObject.SetActive(false);
IsOpen = false;
});
}
#endregion
}
public static class TaskYarnCommand
{
private static TaskPanel TaskPanel => UIManager.Instance.GetPanel<TaskPanel>();
[YarnCommand("complete_task")]
public static void CompleteTask(string lineId)
{
TaskPanel.CompleteTask(lineId);
}
[YarnCommand("clear_tasks")]
public static void ClearTasks()
{
TaskPanel.ClearTasks();
}
[YarnCommand("task_moveIn")]
public static IEnumerator ShowTask()
{
UIManager.Instance.ShowPanel<TaskPanel>();
yield return new WaitForSeconds(1);
}
[YarnCommand("task_moveOut")]
public static IEnumerator HideTask()
{
UIManager.Instance.HidePanel<TaskPanel>();
yield return new WaitForSeconds(1);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 433304b79d7ad5344b1a0c3932187de2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8 -2
View File
@@ -95,8 +95,14 @@ namespace AibisDream
}
public T GetPanel<T>() where T : class, IUIPanel
{
return _panelPool.TryGetValue(typeof(T), out var ui) ? ui as T : null;
{
if (_panelPool.TryGetValue(typeof(T), out var panel))
{
return panel as T;
}
Debug.Log($"没有找到{typeof(T)}");
return null;
}
}
+14 -1
View File
@@ -193,7 +193,20 @@ namespace AibisDream.Utility
while (currentIndex < line.Length)
{
var length = Math.Min(maxCharsPerLine, line.Length - currentIndex);
result.Append(line.Substring(currentIndex, length));
var substring = line.Substring(currentIndex, length);
// 检查是否需要调整长度以避免在单词中间断开
if (currentIndex + length < line.Length && !char.IsWhiteSpace(line[currentIndex + length]) && !char.IsPunctuation(line[currentIndex + length]))
{
var lastSpace = substring.LastIndexOf(' ');
if (lastSpace > 0)
{
length = lastSpace;
substring = line.Substring(currentIndex, length);
}
}
result.Append(substring.TrimStart());
currentIndex += length;
if (currentIndex < line.Length)
+2
View File
@@ -19,5 +19,7 @@ namespace AibisDream.Utility
public const string UITextTable = "UIText";
#endregion
public const string TaskItemName = "Task Item";
}
}