using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace AibisDream { public class ShaftGraph { // 顶点数量 int vertexSize; // 顶点Map Shaft[] vertexArray; // 邻接表 float[,] edgeTable; // 遍历记录 bool[] vertexRecordArray; // 动力轴序号 int rootIdx; public ShaftGraph(Shaft[] shafts) { // 为轴赋值 vertexSize = shafts.Length; vertexRecordArray = new bool[vertexSize]; vertexArray = shafts; foreach (var shaft in vertexArray) { shaft.InitShaft(); } // 寻找唯一的驱动轴序号 rootIdx = FindDriverIdx(); // 生成边邻接表 GeneEdgeTable(); UpdateSpeed(); } private int FindDriverIdx() { for (int i = 0; i < vertexSize; i++) { if (vertexArray[i].shaftType == ShaftType.Driver) { return i; } } return -1; } /// /// 生成边邻接表 /// private void GeneEdgeTable() { edgeTable = new float[vertexSize, vertexSize]; for (int i = 0; i < vertexSize - 1; i++) { for (int j = i + 1; j < vertexSize; j++) { // 判断两个Shaft是否临接 if (Shaft.IsShaftConnected(vertexArray[i], vertexArray[j])) { edgeTable[i, j] = Shaft.CalcAngularVelocityRatio(vertexArray[i], vertexArray[j]); edgeTable[j, i] = Shaft.CalcAngularVelocityRatio(vertexArray[j], vertexArray[i]); } else { edgeTable[i, j] = 0; edgeTable[j, i] = 0; } } } } /// /// 某个轴上齿轮发生变化时更新临接关系 /// /// 轴ID public void ChangeVertex(int instanceID) { // 找到对应idx int idx = TranInstanceIDToIdx(instanceID); // 更新该节点对应的邻接表 for (int i = 0; i < vertexSize; i++) { // 遇到自身跳过 if (i == idx) { continue; } // 判断两个Shaft是否临接 if (Shaft.IsShaftConnected(vertexArray[idx], vertexArray[i])) { edgeTable[idx, i] = Shaft.CalcAngularVelocityRatio(vertexArray[idx], vertexArray[i]); edgeTable[i, idx] = Shaft.CalcAngularVelocityRatio(vertexArray[i], vertexArray[idx]); } else { edgeTable[idx, i] = 0; edgeTable[i, idx] = 0; } } UpdateSpeed(); } private int TranInstanceIDToIdx(int instanceID) { // 查找对应的序号 int idx = -1; for (int i = 0; i < vertexSize; i++) { if (instanceID == vertexArray[i].GetInstanceID()) { idx = i; break; } } return idx; } /// /// 更新当前所有轴的速度 /// public void UpdateSpeed() { // 清除遍历记录 Array.Clear(vertexRecordArray, 0, vertexSize); // 从驱动轴开始计算速度 vertexRecordArray[rootIdx] = true; UpdateShaftSpeedByIdx(rootIdx); // 更新完速度后统一更新动画 foreach (var shaft in vertexArray) { shaft.UpdateSpeed(); } } private void UpdateShaftSpeedByIdx(int idx) { // 已知当前齿轮速度 float currentSpeed = vertexArray[idx].speed; for (int i = 0; i < vertexSize; i++) { // 遍历临接齿轮 if (i != idx && edgeTable[idx, i] > 0) { // 已遍历过就跳过 if (vertexRecordArray[i]) { continue; } // 更新速度 vertexArray[i].speed = currentSpeed * edgeTable[idx, i]; // 已遍历的轴加上标记 vertexRecordArray[i] = true; // 继续寻找相邻齿轮 UpdateShaftSpeedByIdx(i); } } } /// /// 查询可吸附的轴 /// /// 齿轮位置 /// 齿轮半径 /// 吸附轴 public Shaft QuerySnapShaft(Vector3 pos, float gearRadius) { if (vertexArray == null || vertexArray.Length == 0) { return null; } // 查询距离最近的,可吸附的Shaft Shaft closestShaft = null; float minDistance = -1; foreach (var vertex in vertexArray) { if (vertex.shaftType == ShaftType.Pluggable && !vertex.HasChildGear()) { float tempDis = Vector3.Distance(vertex.transform.position, pos); if (minDistance < 0 || tempDis < minDistance) { closestShaft = vertex; minDistance = tempDis; } } } // 没查到就返回空 if (!closestShaft) { return null; } // 查到了就返回是否吸附 return minDistance < gearRadius ? closestShaft : null; } } }