Merge branch 'develop' into feature/open

This commit is contained in:
2025-05-14 13:06:40 +08:00
38 changed files with 6841 additions and 55 deletions
@@ -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)
@@ -393,7 +393,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);
}
public IEnumerator Exit()
@@ -272,6 +272,7 @@ namespace AibisDream.Framework
Engine,
Gear,
EyeDeep,
Op
Op,
ExpressionDeep
}
}
@@ -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: