307 lines
8.8 KiB
C#
307 lines
8.8 KiB
C#
using System;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Utility;
|
|
using DG.Tweening;
|
|
using Newtonsoft.Json;
|
|
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 bool IsPluggable => shaftType is ShaftType.Pluggable or ShaftType.Driver or ShaftType.Target;
|
|
|
|
/// <summary>
|
|
/// 当前齿轮半径
|
|
/// </summary>
|
|
public float GearRadius
|
|
{
|
|
get
|
|
{
|
|
if (!childGear)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (IsPluggable)
|
|
{
|
|
Gear gear = childGear.GetComponent<Gear>();
|
|
return gear.radius;
|
|
}
|
|
|
|
return initRadius;
|
|
}
|
|
}
|
|
|
|
private GearSystem _gearSystem;
|
|
|
|
private void Awake()
|
|
{
|
|
_gearSystem = transform.parent.parent.GetComponent<GearSystem>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化当前轴位置
|
|
/// </summary>
|
|
public void InitShaft()
|
|
{
|
|
// 如果不带齿轮
|
|
if (!hasGear) return;
|
|
|
|
// 如果带齿轮,要根据齿轮类型生成
|
|
childGear = IsPluggable ? InitPluggableGear() : InitStaticGear();
|
|
|
|
speed = initialSpeed;
|
|
UpdateSpeed();
|
|
}
|
|
|
|
private GameObject InitStaticGear()
|
|
{
|
|
GameObject staticGear = transform.GetChild(0).gameObject;
|
|
|
|
// 添加齿轮图片
|
|
staticGear.SetActive(true);
|
|
var staticGearRenderer = staticGear.GetComponent<SpriteRenderer>();
|
|
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 = _gearSystem.InitGear(transform.position, initRadius, initSprite);
|
|
gear.GetComponent<Gear>().targetShaft = this;
|
|
return gear;
|
|
}
|
|
|
|
public void PlugInGear(Gear gear)
|
|
{
|
|
childGear = gear.gameObject;
|
|
_gearSystem.ChangeGraphVertex(GetInstanceID());
|
|
}
|
|
|
|
public void PlugOutGear()
|
|
{
|
|
childGear = null;
|
|
_gearSystem.ChangeGraphVertex(GetInstanceID());
|
|
}
|
|
|
|
public void UpdateSpeed()
|
|
{
|
|
UpdateSpeedAnima();
|
|
CheckGameState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 速度修改后改变动画
|
|
/// </summary>
|
|
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))
|
|
{
|
|
_gearSystem.Succeed();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 判断是否带齿轮
|
|
/// </summary>
|
|
/// <returns>是否带齿轮</returns>
|
|
public bool HasChildGear()
|
|
{
|
|
return childGear;
|
|
}
|
|
|
|
/// <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 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;
|
|
initialSpeed = levelData.initialSpeed;
|
|
targetSpeed = levelData.targetSpeed;
|
|
initRadius = levelData.radius;
|
|
}
|
|
|
|
public ShaftLevelData Save()
|
|
{
|
|
return new ShaftLevelData
|
|
{
|
|
shaftName = gameObject.name,
|
|
ShaftPos = transform.localPosition,
|
|
GearPic = initSprite,
|
|
shaftType = shaftType,
|
|
hasChildGear = hasGear,
|
|
initialSpeed = initialSpeed,
|
|
targetSpeed = targetSpeed,
|
|
radius = initRadius
|
|
};
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public enum ShaftType
|
|
{
|
|
Driver, // 拥有初始速度,没有目标速度,全局仅有一个
|
|
Target, // 没有初始速度,有目标速度,全局有多个
|
|
Constant, // 没有初始速度,没有目标速度,不可拖动
|
|
Pluggable // 没有初始速度,没有目标速度,可拔插
|
|
}
|
|
|
|
[Serializable]
|
|
public struct ShaftLevelData
|
|
{
|
|
public string shaftName;
|
|
// 关卡数据
|
|
public ShaftType shaftType;
|
|
public float initialSpeed;
|
|
public float targetSpeed;
|
|
public bool hasChildGear;
|
|
public float radius;
|
|
|
|
// 外形数据
|
|
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);
|
|
}
|
|
}
|
|
} |