451 lines
13 KiB
C#
451 lines
13 KiB
C#
using DG.Tweening;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using AdamThinkDevicesData;
|
||
using AdamSync;
|
||
|
||
/// <summary>
|
||
/// 单个无人机蜂群控制
|
||
/// </summary>
|
||
public class UnmannedAerialVehicleManage : MonoBehaviour
|
||
{
|
||
/// <summary>
|
||
/// 无人机状态
|
||
/// </summary>
|
||
public Pattern pattern = Pattern.待机;
|
||
public static List<UnmannedAerialVehicleManage> unmannedAerialVehicleManages = new List<UnmannedAerialVehicleManage>();
|
||
#region 启动暂停
|
||
private bool _isStartRehearsing = false;
|
||
/// <summary>
|
||
/// 是否正在预演
|
||
/// </summary>
|
||
public bool isStartRehearsing
|
||
{
|
||
get { return _isStartRehearsing; }
|
||
set
|
||
{
|
||
if (_isStartRehearsing != value)
|
||
{
|
||
_isStartRehearsing = value;
|
||
OnActivationChanged?.Invoke(_isStartRehearsing);
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 布尔值变化时触发的事件
|
||
/// </summary>
|
||
public event System.Action<bool> OnActivationChanged;
|
||
|
||
/// <summary>
|
||
/// 间隔时间
|
||
/// </summary>
|
||
public float interval = 5.0f;
|
||
#endregion
|
||
|
||
public EquipmentCommon equipmentCommon;
|
||
|
||
|
||
/// <summary>
|
||
/// 无人机预制体
|
||
/// </summary>
|
||
public GameObject UAVPrefab;
|
||
/// <summary>
|
||
/// 编队无人机数量
|
||
/// </summary>
|
||
public int totalObjects = 30; // 总共的物体数量
|
||
/// <summary>
|
||
/// 所有子物体无人机
|
||
/// </summary>
|
||
public List<UnmannedAerialVehicle> unmannedAerialVehicles = new List<UnmannedAerialVehicle>();
|
||
|
||
/// <summary>
|
||
/// 线预制体
|
||
/// </summary>
|
||
public GameObject LinePrefab;
|
||
/// <summary>
|
||
/// 航线
|
||
/// </summary>
|
||
public GameObject airRoute;
|
||
/// <summary>
|
||
/// 已有路径
|
||
/// </summary>
|
||
public Queue<Vector3> positions = new Queue<Vector3>();
|
||
public Vector3 endPosition = new Vector3();
|
||
/// <summary>
|
||
/// 飞行速度
|
||
/// </summary>
|
||
public float FireSpeed = 20.0f;
|
||
|
||
|
||
|
||
#region 无人机数据
|
||
/// <summary>
|
||
/// 续航时间
|
||
/// </summary>
|
||
public string batteryLife;
|
||
/// <summary>
|
||
/// 抗风等级
|
||
/// </summary>
|
||
public string classificationWindResistance;
|
||
/// <summary>
|
||
/// 最大飞行速度
|
||
/// </summary>
|
||
public string maximumFlyingSpeed;
|
||
/// <summary>
|
||
/// RCS
|
||
/// </summary>
|
||
public string RCS;
|
||
/// <summary>
|
||
/// 卫星定位频点
|
||
/// </summary>
|
||
public string satellitePositioningFrequency;
|
||
/// <summary>
|
||
/// 数据链通信频点
|
||
/// </summary>
|
||
public string dataLinkCommunicationFrequency;
|
||
/// <summary>
|
||
/// 电子侦察能力
|
||
/// </summary>
|
||
public string electronicReconnaissanceCapability;
|
||
/// <summary>
|
||
/// 光学侦察能力
|
||
/// </summary>
|
||
public string opticalReconnaissanceCapability;
|
||
|
||
#endregion
|
||
// Start is called before the first frame update
|
||
void Start()
|
||
{
|
||
for (int i = 0; i < unmannedAerialVehicles.Count; i++)
|
||
{
|
||
unmannedAerialVehicles[i].serialNumber = (i + 1).ToString();
|
||
}
|
||
unmannedAerialVehicleManages.Add(this);
|
||
equipmentCommon = GetComponent<EquipmentCommon>();
|
||
Formation(1);//默认阵型
|
||
// 订阅布尔值变化事件
|
||
OnActivationChanged += OnActivationChangedHandler;
|
||
|
||
}
|
||
|
||
// Update is called once per frame
|
||
void Update()
|
||
{
|
||
if (isStartRehearsing && equipmentCommon.isPlayer && pattern == Pattern.攻击)
|
||
{
|
||
if (airRoute)
|
||
{
|
||
StartMoveObjectAlongPath();
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 模式切换
|
||
/// </summary>
|
||
public void modeSwitch(int patternCut)
|
||
{
|
||
switch (patternCut)
|
||
{
|
||
case 0://待机
|
||
pattern = Pattern.待机;
|
||
break;
|
||
case 1:
|
||
pattern = Pattern.警戒;
|
||
break;
|
||
case 2:
|
||
pattern = Pattern.攻击;
|
||
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
#region 启动暂停
|
||
/// <summary>
|
||
/// 导条变化调用
|
||
/// </summary>
|
||
/// <param name="newValue"></param>
|
||
void OnActivationChangedHandler(bool newValue)
|
||
{
|
||
if (newValue)
|
||
{
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
#region 数据写入
|
||
/// <summary>
|
||
/// 数据写入
|
||
/// </summary>
|
||
/// <param name="weaponitemone"></param>
|
||
public void FillInTheData(List<List_paraItem> weaponitemone)
|
||
{
|
||
//if (equipmentCommon)
|
||
//{
|
||
// string msg = $"send2room {equipmentCommon.equipmentType}+{transform.position.ToString().Replace(" ", "").Replace("(", "").Replace(")", "")}+{transform.eulerAngles.ToString().Replace(" ", "").Replace("(", "").Replace(")", "")}";
|
||
// Debug.Log(msg);
|
||
// _ = SyncCreateRoom.SendMessageAsync(msg);
|
||
//}
|
||
for (int i = 0; i < weaponitemone.Count; i++)
|
||
{
|
||
switch (weaponitemone[i].para_name)
|
||
{
|
||
case "续航时间:":
|
||
batteryLife = weaponitemone[i].para_value;
|
||
break;
|
||
case "抗风等级:":
|
||
classificationWindResistance = weaponitemone[i].para_value;
|
||
break;
|
||
case "最大飞行速度:":
|
||
maximumFlyingSpeed = weaponitemone[i].para_value;
|
||
FireSpeed = float.Parse(maximumFlyingSpeed);
|
||
break;
|
||
case "RCS:":
|
||
RCS = weaponitemone[i].para_value;
|
||
break;
|
||
case "卫星定位频点:":
|
||
satellitePositioningFrequency = weaponitemone[i].para_value;
|
||
break;
|
||
case "数据链通信频点:":
|
||
dataLinkCommunicationFrequency = weaponitemone[i].para_value;
|
||
break;
|
||
case "电子侦察能力:":
|
||
electronicReconnaissanceCapability = weaponitemone[i].para_value;
|
||
break;
|
||
case "光学侦察能力:":
|
||
opticalReconnaissanceCapability = weaponitemone[i].para_value;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (i == (weaponitemone.Count - 1))
|
||
{
|
||
StartCoroutine(WeaponitemoneDataAddition());
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 单个无人机数据写入
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
IEnumerator WeaponitemoneDataAddition()
|
||
{
|
||
yield return new WaitForSeconds(0.1f);
|
||
for (int i = 0; i < unmannedAerialVehicles.Count; i++)
|
||
{
|
||
if (unmannedAerialVehicles[i] != null)
|
||
{
|
||
unmannedAerialVehicles[i].batteryLife = batteryLife;
|
||
unmannedAerialVehicles[i].classificationWindResistance = classificationWindResistance;
|
||
unmannedAerialVehicles[i].maximumFlyingSpeed = maximumFlyingSpeed;
|
||
unmannedAerialVehicles[i].RCS = RCS;
|
||
unmannedAerialVehicles[i].satellitePositioningFrequency = satellitePositioningFrequency;
|
||
unmannedAerialVehicles[i].dataLinkCommunicationFrequency = dataLinkCommunicationFrequency;
|
||
unmannedAerialVehicles[i].electronicReconnaissanceCapability = electronicReconnaissanceCapability;
|
||
unmannedAerialVehicles[i].opticalReconnaissanceCapability = opticalReconnaissanceCapability;
|
||
unmannedAerialVehicles[i].unmannedAerialVehicleManage = this;
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 阵型编队
|
||
/// <summary>
|
||
/// 阵型选择
|
||
/// </summary>
|
||
/// <param name="number"></param>
|
||
public void Formation(int number)
|
||
{
|
||
switch (number)
|
||
{
|
||
case 1:
|
||
GenerateFormation();
|
||
break;
|
||
case 2:
|
||
MatrixFormation(5);
|
||
break;
|
||
case 3:
|
||
MatrixFormation(30);
|
||
break;
|
||
case 4:
|
||
MatrixFormation(1);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无人机雁式阵型
|
||
/// </summary>
|
||
private void GenerateFormation()
|
||
{
|
||
int count = 1; // 每一排的物体数量
|
||
int currentCount = 0;
|
||
Vector3 startPos = new Vector3();
|
||
|
||
for (int i = 0; i < Mathf.Ceil(Mathf.Sqrt(totalObjects)); i++)
|
||
{
|
||
//Debug.Log("剩余。。。:" + (totalObjects - currentCount));
|
||
startPos = new Vector3(-i * 2, 0, -i * 2);
|
||
for (int j = 0; j < count; j++)//每排物体个数
|
||
{
|
||
|
||
if (currentCount < totalObjects)
|
||
{
|
||
Vector3 _vector3 = startPos + new Vector3(j * 2, 0, 0);
|
||
if (unmannedAerialVehicles[currentCount])
|
||
unmannedAerialVehicles[currentCount].transform.localPosition = _vector3;
|
||
currentCount++;
|
||
}
|
||
else
|
||
{
|
||
BoxCollider box = transform.GetComponent<BoxCollider>();
|
||
if (box)
|
||
{
|
||
box.center = new Vector3(0, 0, -i);
|
||
box.size = new Vector3(2 * count, 1, 2 * (i + 1));
|
||
}
|
||
}
|
||
}
|
||
count += 2; // 下一排增加两个物体
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 矩阵阵型
|
||
/// </summary>
|
||
private void MatrixFormation(int rows)
|
||
{
|
||
float offsetX = 2.0f; // 子物体之间的水平间距
|
||
float offsetY = 2.0f; // 子物体之间的垂直间距
|
||
float offsetZ = 2.0f; // 子物体之间的垂直间距
|
||
int currentCount = 0;
|
||
int cols = CanDivideEvenly(totalObjects, rows) ? totalObjects / rows : totalObjects / rows + 1;
|
||
for (int row = 0; row < rows; row++)
|
||
{
|
||
for (int col = 0; col < cols; col++)
|
||
{
|
||
if (currentCount < totalObjects)
|
||
{
|
||
Vector3 position = new Vector3(col * offsetX, 0, -row * offsetZ);
|
||
if (unmannedAerialVehicles[currentCount])
|
||
unmannedAerialVehicles[currentCount].transform.localPosition = position;
|
||
currentCount++;
|
||
}
|
||
}
|
||
}
|
||
BoxCollider box = transform.GetComponent<BoxCollider>();
|
||
if (box)
|
||
{
|
||
Debug.Log("cols..:" + cols);
|
||
Debug.Log("rows..:" + rows);
|
||
box.center = new Vector3(cols - 1, 0, -(rows - 1));
|
||
box.size = new Vector3(cols * 2, 1, 2 * rows);
|
||
}
|
||
}
|
||
|
||
bool CanDivideEvenly(int dividend, int divisor)
|
||
{
|
||
return dividend % divisor == 0;
|
||
}
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 关闭航线设置
|
||
/// </summary>
|
||
public void TurnOffCourseSettings()
|
||
{
|
||
if (airRoute)
|
||
{
|
||
ObjectPlanner objectPlanner = airRoute.GetComponent<ObjectPlanner>();
|
||
if (objectPlanner)
|
||
{
|
||
objectPlanner.isPathCanBePlanned = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 开启航线设置
|
||
/// </summary>
|
||
public void RouteSettings()
|
||
{
|
||
if (airRoute)
|
||
{
|
||
ObjectPlanner objectPlanner = airRoute.GetComponent<ObjectPlanner>();
|
||
if (objectPlanner)
|
||
{
|
||
objectPlanner.isPathCanBePlanned = true;
|
||
objectPlanner.lineRenderer.SetVertexCount(0);
|
||
positions.Clear();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
GameObject _object = Instantiate(LinePrefab);
|
||
airRoute = _object;
|
||
airRoute.transform.position = Vector3.zero;
|
||
ObjectPlanner objectPlanner = airRoute.GetComponent<ObjectPlanner>();
|
||
if (objectPlanner)
|
||
{
|
||
objectPlanner.unmannedAerialVehicleManage = this;
|
||
objectPlanner.isPathCanBePlanned = true;
|
||
objectPlanner.SetSelectedObject(transform.gameObject);
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool isMove = true;
|
||
/// <summary>
|
||
/// 按规划路径开始移动
|
||
/// </summary>
|
||
public void StartMoveObjectAlongPath()
|
||
{
|
||
if (isMove && positions.Count > 0)
|
||
{
|
||
isMove = false;
|
||
StartCoroutine(MoveObjectAlongPath(positions.Dequeue())); // 启动协程,按规划的路线移动物体
|
||
}
|
||
}
|
||
|
||
IEnumerator MoveObjectAlongPath(Vector3 positions) // 协程:按路线移动物体
|
||
{
|
||
Vector3 targetPosition = new Vector3(positions.x, 10, positions.z);// 目标位置为当前顶点坐标
|
||
float _distance = Vector3.Distance(transform.position, targetPosition);
|
||
float _time = _distance / FireSpeed;
|
||
transform.LookAt(endPosition);
|
||
transform.DOMove(targetPosition, _time).SetEase(Ease.Linear);
|
||
yield return new WaitForSeconds(_time); // 等待一帧时间
|
||
isMove = true;
|
||
}
|
||
private void OnDestroy()
|
||
{
|
||
OnActivationChanged -= OnActivationChangedHandler;
|
||
}
|
||
|
||
|
||
}
|
||
public enum Pattern
|
||
{
|
||
待机,
|
||
警戒,
|
||
攻击
|
||
} |