using AibisDream.Utility; using DG.Tweening; using UnityEngine; namespace AibisDream { public class Shaft : MonoBehaviour { [SerializeField] private int id; [SerializeField] public ShaftType shaftType; // 初始齿轮 [SerializeField] private float initRadius; [SerializeField] private Sprite initSprite; [SerializeField] private bool hasGear; [SerializeField] private GameObject childGear; // 初始角速度 [SerializeField] private float initialSpeed; // 目标角速度 [SerializeField] private float targetSpeed; // 当前角速度 public float speed; /// /// 当前齿轮半径 /// public float GearRadius { get { if (!childGear) { return 0; } if (shaftType == ShaftType.Pluggable) { Gear gear = childGear.GetComponent(); return gear.radius; } else { return initRadius; } } } private GearController gearController; private void Awake() { gearController = transform.parent.parent.GetComponent(); } /// /// 初始化当前轴位置 /// public void InitShaft() { // 如果不带齿轮 if (!hasGear) return; // 如果带齿轮,要根据齿轮类型生成 childGear = shaftType == ShaftType.Pluggable ? InitPluggableGear() : InitStaticGear(); speed = initialSpeed; UpdateSpeed(); } private GameObject InitStaticGear() { GameObject staticGear = transform.GetChild(0).gameObject; // 添加齿轮图片 staticGear.SetActive(true); var staticGearRenderer = staticGear.GetComponent(); staticGearRenderer.sprite = initSprite; staticGearRenderer.size = new Vector2(initRadius * 2, initRadius * 2); // 如果有初速,就要开始转动了 if (!CommonUtil.IsZero(initialSpeed)) { staticGear.transform.DORotate(new Vector3(0, 0, 360), 1 / initialSpeed, RotateMode.LocalAxisAdd) .SetEase(Ease.Linear).SetLoops(-1, LoopType.Incremental); } return staticGear; } private GameObject InitPluggableGear() { var gear = gearController.InitGear(transform.position, initRadius, initSprite, initialSpeed); gear.GetComponent().targetShaft = this; return gear; } public void PlugInGear(Gear gear) { childGear = gear.gameObject; gearController.ChangeGraphVertex(GetInstanceID()); } public void PlugOutGear() { childGear = null; gearController.ChangeGraphVertex(GetInstanceID()); } public void UpdateSpeed() { UpdateSpeedAnima(); CheckGameState(); } /// /// 速度修改后改变动画 /// private void UpdateSpeedAnima() { // 没有齿轮的不需要旋转 if (!HasChildGear()) { return; } if (CommonUtil.IsZero(speed)) { childGear.transform.DOPause(); return; } // 更新动画 childGear.transform.DOKill(); if (speed > 0) { childGear.transform.DORotate(new Vector3(0, 0, 360), 1 / speed, RotateMode.LocalAxisAdd) .SetEase(Ease.Linear).SetLoops(-1, LoopType.Incremental); } else { childGear.transform.DORotate(new Vector3(0, 0, -360), 1 / -speed, RotateMode.LocalAxisAdd) .SetEase(Ease.Linear).SetLoops(-1, LoopType.Incremental); } } private void CheckGameState() { if (shaftType == ShaftType.Target) { if (targetSpeed <= Mathf.Abs(speed)) { gearController.Succeed(); } } } /// /// 判断是否带齿轮 /// /// 是否带齿轮 public bool HasChildGear() { return childGear; } /// /// 判断两个轴是否齿轮相接 /// /// 轴1 /// 轴2 /// 是否相接 public static bool IsShaftConnected(Shaft shaft1, Shaft shaft2) { // 如果轴上无齿轮就不计算 if (!shaft1 || !shaft2) { return false; } if (!shaft1.childGear || !shaft2.childGear) { return false; } // 如果两个都有齿轮,就判断是否相邻 float distance = (shaft1.transform.position - shaft2.transform.position).magnitude; float radiusSum = shaft1.GearRadius + shaft2.GearRadius; return distance < radiusSum; } /// /// 获取可以安装齿轮的最大尺寸 /// /// 源位置 /// 目标轴 /// 可用距离 public static float CalcShaftAvailableDis(Vector3 sourcePos, Shaft shaft) { if (!shaft.hasGear) { return (sourcePos - shaft.transform.position).magnitude; } else { return (sourcePos - shaft.transform.position).magnitude - shaft.GearRadius; } } /// /// 求两个轴角速度之比 /// /// 轴1 /// 轴2 /// 角速度之比 public static float CalcAngularVelocityRatio(Shaft shaft1, Shaft shaft2) { return shaft1.GearRadius / shaft2.GearRadius; } public void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, initRadius); } } public enum ShaftType { Driver, // 拥有初始速度,没有目标速度,全局仅有一个 Target, // 没有初始速度,有目标速度,全局有多个 Constant, // 没有初始速度,没有目标速度,不可拖动 Pluggable, // 没有初始速度,没有目标速度,可拔插 Outside // 放在身体外面的轴,仅用于放置齿轮 } }