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); // 从驱动轴开始计算速度 UpdateShaftSpeedByIdx(rootIdx); } 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[idx]) { continue; } Debug.Log(idx); // 更新速度 vertexArray[i].Speed = currentSpeed * edgeTable[idx, i]; // 继续寻找相邻齿轮 //UpdateShaftSpeedByIdx(i); // 已遍历的轴加上标记 vertexRecordArray[i] = true; } } } /// /// 查询可吸附的轴 /// /// 齿轮位置 /// 齿轮半径 /// 吸附轴 public Shaft QuerySnapShaft(Vector3 pos, float gearRadius) { if (vertexArray == null || vertexArray.Length == 0) { return null; } // 查询距离最近的,可吸附的Shaft Shaft closestShaft = null; float minDistence = -1; foreach (var vertex in vertexArray) { if (vertex.shaftType == ShaftType.Pluggable && !vertex.HasChildGear()) { float tempDis = Vector3.Distance(vertex.transform.position, pos); if (minDistence < 0 || tempDis < minDistence) { closestShaft = vertex; minDistence = tempDis; } } } // 没查到就返回空 if (closestShaft == null) { return null; } // 查到了就返回是否吸附 if (minDistence < gearRadius) { return closestShaft; } else { return null; } } } }