343 lines
10 KiB
C#
343 lines
10 KiB
C#
using System;
|
|
using AibisDream.FixSystem;
|
|
using AibisDream.Framework;
|
|
using DG.Tweening;
|
|
using Newtonsoft.Json;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public class Shaft : MonoBehaviour
|
|
{
|
|
[SerializeField] private int id;
|
|
|
|
[SerializeField] public ShaftType shaftType;
|
|
|
|
// 初始齿轮
|
|
[SerializeField] private bool hasGear;
|
|
[SerializeField] private string gearProp;
|
|
[SerializeField] private bool isInitGearBroken;
|
|
[SerializeField] private bool isInitGearDisc;
|
|
[SerializeField] private float initRadius;
|
|
[SerializeField] private Sprite initSprite;
|
|
[SerializeField] private int discIdx;
|
|
|
|
[SerializeField] public Gear childGear;
|
|
|
|
// 目标角速度
|
|
[SerializeField] private float targetSpeed;
|
|
|
|
// 当前角速度
|
|
public float speed;
|
|
private float _speedScale = 1;
|
|
|
|
public bool IsBroken => childGear != null && childGear.isBroken;
|
|
public bool IsDisc => childGear != null && childGear.isDisc;
|
|
|
|
/// <summary>
|
|
/// 当前齿轮半径
|
|
/// </summary>
|
|
public float GearRadius
|
|
{
|
|
get
|
|
{
|
|
if (!childGear)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return childGear.radius;
|
|
}
|
|
}
|
|
|
|
private GearSystem GearSystem => FixSystemCenter.SystemDic.Get<GearSystem>();
|
|
|
|
/// <summary>
|
|
/// 初始化当前轴位置
|
|
/// </summary>
|
|
public void InitShaft()
|
|
{
|
|
// 如果不带齿轮
|
|
if (!hasGear) return;
|
|
|
|
// 如果带齿轮,要根据齿轮类型生成
|
|
childGear = InitGear(initRadius, initSprite, isInitGearBroken, isInitGearDisc);
|
|
|
|
childGear.UpdateRotation(speed, _speedScale);
|
|
}
|
|
|
|
private Gear InitGear(float radius, Sprite sprite, bool isBroken = false, bool isDisc = false)
|
|
{
|
|
var gear = Instantiate(GearSystem.gearPrefab, transform).GetComponent<Gear>();
|
|
gear.radius = radius;
|
|
gear.gearSprite = sprite;
|
|
gear.gearProp = gearProp;
|
|
gear.isBroken = isBroken;
|
|
gear.targetShaft = this;
|
|
gear.isDisc = isDisc;
|
|
gear.isConstant = shaftType != ShaftType.Pluggable; // TODO 驱动齿轮和目标齿轮暂时也不给动
|
|
return gear;
|
|
}
|
|
|
|
public void PlugInGear(Gear gear)
|
|
{
|
|
childGear = gear;
|
|
gear.transform.parent = transform;
|
|
GearSystem.ChangeGraphVertex(GetInstanceID());
|
|
|
|
// 面板里的齿轮才能触发
|
|
if (GearSystem.IsShaftInBox(transform))
|
|
{
|
|
OnGearPlugIn();
|
|
GearSystem.CheckGearSystemState();
|
|
}
|
|
}
|
|
|
|
private void OnGearPlugIn()
|
|
{
|
|
// 破损齿轮插进来就发一次事件,交给yarn处理
|
|
if (IsBroken)
|
|
{
|
|
DialogController.Instance?.StartDialogNode("破损齿轮插入");
|
|
}
|
|
|
|
if (IsDisc)
|
|
{
|
|
StorageSystem.Instance?.SetValue("$discIdx", discIdx);
|
|
}
|
|
|
|
// 传当前插入齿轮的Prop
|
|
StorageSystem.Instance?.SetValue("$curGearProp", childGear.gearProp);
|
|
}
|
|
|
|
public void PlugOutGear()
|
|
{
|
|
// 拔出时齿轮停转
|
|
childGear.UpdateRotation(0, _speedScale);
|
|
|
|
childGear.transform.parent = null;
|
|
childGear = null;
|
|
GearSystem.ChangeGraphVertex(GetInstanceID());
|
|
}
|
|
|
|
public void ChangeRotateState()
|
|
{
|
|
UpdateSpeedAnima();
|
|
CheckGameState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 速度修改后改变动画(可能改变方向)
|
|
/// </summary>
|
|
private void UpdateSpeedAnima()
|
|
{
|
|
// 没有齿轮的不需要旋转
|
|
if (!HasChildGear())
|
|
{
|
|
return;
|
|
}
|
|
|
|
childGear.UpdateRotation(speed, _speedScale);
|
|
}
|
|
|
|
public void UpdateSpeedScale(float newSpeedScale)
|
|
{
|
|
_speedScale = newSpeedScale;
|
|
if (!HasChildGear()) return;
|
|
childGear.UpdateSpeedScale(_speedScale);
|
|
CheckGameState();
|
|
}
|
|
|
|
private void CheckGameState()
|
|
{
|
|
// 只有目标轴判断
|
|
if (shaftType != ShaftType.Target) return;
|
|
|
|
if (targetSpeed <= Mathf.Abs(speed * _speedScale))
|
|
{
|
|
GearSystem.ReachTargetSpeed();
|
|
}
|
|
else
|
|
{
|
|
GearSystem.ResetTargetState();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 判断是否带齿轮
|
|
/// </summary>
|
|
/// <returns>是否带齿轮</returns>
|
|
public bool HasChildGear()
|
|
{
|
|
return childGear;
|
|
}
|
|
|
|
public void PopupGear()
|
|
{
|
|
// Constant无法弹出
|
|
// if (shaftType != ShaftType.Pluggable) return;
|
|
// 没有齿轮无法弹出
|
|
if (!childGear) return;
|
|
|
|
// 播放齿轮移除动画并更新速度
|
|
var gear = childGear;
|
|
|
|
PlugOutGear();
|
|
|
|
gear.Popup();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 判断两个轴是否齿轮相接
|
|
/// </summary>
|
|
/// <param name="shaft1">轴1</param>
|
|
/// <param name="shaft2">轴2</param>
|
|
/// <returns>是否相接</returns>
|
|
public static bool IsShaftConnected(Shaft shaft1, Shaft shaft2)
|
|
{
|
|
// 如果轴上无齿轮就不计算
|
|
if (!shaft1 || !shaft2)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!shaft1.HasChildGear() || !shaft2.HasChildGear())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 如果两个都有齿轮,就判断是否相邻
|
|
float distance = (shaft1.transform.position - shaft2.transform.position).magnitude;
|
|
float radiusSum = shaft1.GearRadius + shaft2.GearRadius;
|
|
|
|
return distance < radiusSum;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取可以安装齿轮的最大尺寸
|
|
/// </summary>
|
|
/// <param name="sourcePos">源位置</param>
|
|
/// <param name="shaft">目标轴</param>
|
|
/// <returns>可用距离</returns>
|
|
public static float CalcShaftAvailableDis(Vector3 sourcePos, Shaft shaft)
|
|
{
|
|
if (!shaft.HasChildGear())
|
|
{
|
|
return (sourcePos - shaft.transform.position).magnitude;
|
|
}
|
|
else
|
|
{
|
|
return (sourcePos - shaft.transform.position).magnitude - shaft.GearRadius;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 求两个轴角速度之比
|
|
/// </summary>
|
|
/// <param name="shaft1">轴1</param>
|
|
/// <param name="shaft2">轴2</param>
|
|
/// <returns>角速度之比</returns>
|
|
public static float CalcAngularVelocityRatio(Shaft shaft1, Shaft shaft2)
|
|
{
|
|
return shaft1.GearRadius / shaft2.GearRadius;
|
|
}
|
|
|
|
public void OnDestroy()
|
|
{
|
|
if (childGear != null)
|
|
{
|
|
childGear.transform.DOKill();
|
|
}
|
|
Destroy(childGear);
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
public void OnDrawGizmos()
|
|
{
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawWireSphere(transform.position, initRadius);
|
|
}
|
|
|
|
#region 保存与加载
|
|
|
|
public void Load(ShaftLevelData levelData)
|
|
{
|
|
// 加载数据
|
|
gameObject.name = levelData.shaftName;
|
|
transform.localPosition = levelData.ShaftPos;
|
|
initSprite = levelData.GearPic;
|
|
|
|
shaftType = levelData.shaftType;
|
|
hasGear = levelData.hasChildGear;
|
|
gearProp = levelData.gearProp;
|
|
isInitGearBroken = levelData.isGearBroken;
|
|
isInitGearDisc = levelData.isDisc;
|
|
discIdx = levelData.discIdx;
|
|
targetSpeed = levelData.targetSpeed;
|
|
initRadius = levelData.radius;
|
|
}
|
|
|
|
public ShaftLevelData Save()
|
|
{
|
|
return new ShaftLevelData
|
|
{
|
|
shaftName = gameObject.name,
|
|
ShaftPos = transform.localPosition,
|
|
GearPic = initSprite,
|
|
shaftType = shaftType,
|
|
hasChildGear = hasGear,
|
|
gearProp = gearProp,
|
|
isGearBroken = isInitGearBroken,
|
|
isDisc = isInitGearDisc,
|
|
discIdx = discIdx,
|
|
targetSpeed = targetSpeed,
|
|
radius = initRadius
|
|
};
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public enum ShaftType
|
|
{
|
|
Driver, // 拥有初始速度,没有目标速度,全局仅有一个
|
|
Target, // 没有初始速度,有目标速度,全局有多个
|
|
Pluggable, // 没有初始速度,没有目标速度,可拔插
|
|
Constant // 固定齿轮不可插拔
|
|
}
|
|
|
|
[Serializable]
|
|
public struct ShaftLevelData
|
|
{
|
|
public string shaftName;
|
|
|
|
// 关卡数据
|
|
public ShaftType shaftType;
|
|
public float targetSpeed;
|
|
public bool hasChildGear;
|
|
public float radius;
|
|
public string gearProp;
|
|
public bool isGearBroken;
|
|
public bool isDisc;
|
|
public int discIdx;
|
|
|
|
// 外形数据
|
|
public SerializableVector3 shaftPos;
|
|
public string gearPicPath;
|
|
|
|
// 类型转换
|
|
[JsonIgnore]
|
|
public Sprite GearPic
|
|
{
|
|
get => !string.IsNullOrEmpty(gearPicPath) ? ResourceKit.LoadSpriteFromPsd(gearPicPath) : null;
|
|
set => gearPicPath = ResourceKit.SaveSprite(value);
|
|
}
|
|
|
|
[JsonIgnore]
|
|
public Vector3 ShaftPos
|
|
{
|
|
get => shaftPos.ToVector3();
|
|
set => shaftPos = new SerializableVector3(value);
|
|
}
|
|
}
|
|
} |