648 lines
21 KiB
C#
648 lines
21 KiB
C#
using DG.Tweening;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using AdamThinkDevicesData;
|
||
using AdamSync;
|
||
using System.Linq;
|
||
using static InterfaceManager;
|
||
using Newtonsoft.Json;
|
||
|
||
/// <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;
|
||
|
||
/// <summary>
|
||
/// 检测范围半径
|
||
/// </summary>
|
||
public float detectionRadius = 80; //
|
||
/// <summary>
|
||
/// 是否正在攻击目标
|
||
/// </summary>
|
||
public bool isEngagedTarget = false;
|
||
|
||
#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)
|
||
{
|
||
switch (pattern)
|
||
{
|
||
case Pattern.待机:
|
||
break;
|
||
case Pattern.警戒:
|
||
SelectiveAttackDrone();
|
||
break;
|
||
case Pattern.攻击:
|
||
SelectiveAttackDrone();
|
||
if (airRoute)
|
||
{
|
||
StartMoveObjectAlongPath();
|
||
}
|
||
break;
|
||
}
|
||
|
||
var _unmannedAerialVehicle = unmannedAerialVehicles.FindAll(x => x != null);
|
||
if (_unmannedAerialVehicle.Count == 0)
|
||
{
|
||
string nowData = string.Format("{0},{1}", "SetToBeDestroyed", equipmentCommon.deviceID);
|
||
Debug.Log(nowData);
|
||
_ = SyncCreateRoom.SendMessageAsync(string.Format("send2room {0}", nowData));
|
||
UploadLog(equipmentCommon.deviceID);
|
||
WWWForm headers = new WWWForm();
|
||
headers.AddField("id", equipmentCommon.deviceID);
|
||
StartCoroutine(PostString(Url_Deletepracticedevicedetail, headers, data =>
|
||
{
|
||
Debug.Log(data);
|
||
Destroy(gameObject);
|
||
}));
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
///上传日志
|
||
/// </summary>
|
||
/// <param name="deviceID"></param>
|
||
public void UploadLog(string deviceID)
|
||
{
|
||
string currentTime = System.DateTime.Now.ToString();
|
||
List<UploadLogMain> uploadLogMains = new List<UploadLogMain>();
|
||
UploadLogMain uploadLogMain = new UploadLogMain();
|
||
uploadLogMain.PracticeId = GlobalFlag.practiceSubjectID;
|
||
uploadLogMain.ThinkId = GlobalFlag.currentThinkId;
|
||
string log = currentTime + " " + equipmentCommon.equipmentType + "(" + deviceID + ")" + "被成建制销毁了 ";
|
||
uploadLogMain.log = log;
|
||
uploadLogMains.Add(uploadLogMain);
|
||
string uploadLogMainJson = JsonConvert.SerializeObject(uploadLogMains);
|
||
WWWForm wWWForm = new WWWForm();
|
||
wWWForm.AddField("data", uploadLogMainJson);
|
||
Debug.Log(uploadLogMainJson);
|
||
StartCoroutine(PostString(Url_Addpracticelog, wWWForm, data =>
|
||
{
|
||
Debug.Log(data);
|
||
}));
|
||
}
|
||
|
||
/// <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;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 攻击打击
|
||
/// </summary>
|
||
private void SelectiveAttackDrone()
|
||
{
|
||
if (isEngagedTarget) return;
|
||
List<Collider> colliders = Physics.OverlapSphere(transform.position, detectionRadius).ToList(); // 检索范围内的所有碰撞体
|
||
List<Collider> colliders1 = new List<Collider>();
|
||
for (int i = 0; i < colliders.Count; i++)
|
||
{
|
||
if (colliders[i].transform.tag == "AttackTarget")
|
||
colliders1.Add(colliders[i]);
|
||
}
|
||
if (colliders1.Count > 0)
|
||
{
|
||
isEngagedTarget = true;
|
||
colliders1.ForEach(x => Debug.Log(x.transform.name));
|
||
int _number = UnityEngine.Random.Range(0, colliders1.Count - 1);
|
||
List<UnmannedAerialVehicle> _unmannedAerialVehicles = unmannedAerialVehicles.FindAll(x => x != null);
|
||
SendMsg(colliders1[_number].transform);
|
||
for (int i = 0; i < _unmannedAerialVehicles.Count; i++)
|
||
{
|
||
_unmannedAerialVehicles[i].AttAck(colliders1[_number].transform);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void SendMsg(Transform attackTarget)
|
||
{
|
||
string nowData = GetSyncData(attackTarget);
|
||
Debug.Log(nowData);
|
||
_ = SyncCreateRoom.SendMessageAsync(string.Format("send2room {0}", nowData));
|
||
}
|
||
/// <summary>
|
||
/// 无人机攻击目标传递
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
protected string GetSyncData(Transform attackTarget)
|
||
{
|
||
return string.Format("{0},{1},{2},{3},{4}", "SingleDronePosition", equipmentCommon.deviceID,
|
||
attackTarget.position.x, attackTarget.position.y, attackTarget.position.z);
|
||
|
||
}
|
||
|
||
|
||
#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;
|
||
switch (weaponitemone[i].para_value)
|
||
{
|
||
case "0":
|
||
satellitePositioningFrequency = "1227.60 MHz";
|
||
break;
|
||
case "1":
|
||
satellitePositioningFrequency = "1381.05 MHz";
|
||
break;
|
||
case "2":
|
||
satellitePositioningFrequency = "1575.42 MHz";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case "数据链通信频点:":
|
||
//dataLinkCommunicationFrequency = weaponitemone[i].para_value;
|
||
switch (weaponitemone[i].para_value)
|
||
{
|
||
case "0":
|
||
dataLinkCommunicationFrequency = "2GHz";
|
||
break;
|
||
case "1":
|
||
dataLinkCommunicationFrequency = "4GHz";
|
||
break;
|
||
case "2":
|
||
dataLinkCommunicationFrequency = "5GHz";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case "电子侦察能力:":
|
||
//electronicReconnaissanceCapability = weaponitemone[i].para_value;
|
||
switch (weaponitemone[i].para_value)
|
||
{
|
||
case "0":
|
||
electronicReconnaissanceCapability = "UHF";
|
||
break;
|
||
case "1":
|
||
electronicReconnaissanceCapability = "L";
|
||
break;
|
||
case "2":
|
||
electronicReconnaissanceCapability = "S";
|
||
break;
|
||
case "3":
|
||
electronicReconnaissanceCapability = "C";
|
||
break;
|
||
case "4":
|
||
electronicReconnaissanceCapability = "X";
|
||
break;
|
||
case "5":
|
||
electronicReconnaissanceCapability = "Ku";
|
||
break;
|
||
case "6":
|
||
electronicReconnaissanceCapability = "Ka";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case "光学侦察能力:":
|
||
//opticalReconnaissanceCapability = weaponitemone[i].para_value;
|
||
switch (weaponitemone[i].para_value)
|
||
{
|
||
case "0":
|
||
opticalReconnaissanceCapability = "有";
|
||
break;
|
||
case "1":
|
||
opticalReconnaissanceCapability = "无";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (i == (weaponitemone.Count - 1))
|
||
{
|
||
StartCoroutine(WeaponitemoneDataAddition());
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 单个无人机数据写入
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
IEnumerator WeaponitemoneDataAddition()
|
||
{
|
||
yield return new WaitForSeconds(0.01f);
|
||
for (int i = 0; i < unmannedAerialVehicles.Count; i++)
|
||
{
|
||
if (unmannedAerialVehicles[i] != null)
|
||
{
|
||
unmannedAerialVehicles[i].unmannedAerialVehicleManage = this;
|
||
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;
|
||
|
||
}
|
||
}
|
||
}
|
||
#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)
|
||
{
|
||
DistanceMeasurement distanceMeasurement = airRoute.GetComponent<DistanceMeasurement>();
|
||
if (distanceMeasurement)
|
||
{
|
||
distanceMeasurement.isPathCanBePlanned = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 开启航线设置
|
||
/// </summary>
|
||
public void RouteSettings()
|
||
{
|
||
if (airRoute)
|
||
{
|
||
DistanceMeasurement distanceMeasurement = airRoute.GetComponent<DistanceMeasurement>();
|
||
if (distanceMeasurement)
|
||
{
|
||
distanceMeasurement.isPathCanBePlanned = true;
|
||
positions.Clear();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
GameObject _object = Instantiate(LinePrefab);
|
||
airRoute = _object;
|
||
airRoute.transform.position = Vector3.zero;
|
||
DistanceMeasurement distanceMeasurement = airRoute.GetComponent<DistanceMeasurement>();
|
||
if (distanceMeasurement)
|
||
{
|
||
distanceMeasurement.isPathCanBePlanned = true;
|
||
distanceMeasurement.markers[0] = transform;
|
||
distanceMeasurement.unmannedAerialVehicleManage = this;
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool isMove = true;
|
||
/// <summary>
|
||
/// 按规划路径开始移动
|
||
/// </summary>
|
||
public void StartMoveObjectAlongPath()
|
||
{
|
||
if (isMove && positions.Count > 0)
|
||
{
|
||
isMove = false;
|
||
Vector3 _positions = positions.Dequeue();
|
||
var nowData = GetSyncData(_positions);
|
||
_ = SyncCreateRoom.SendMessageAsync(string.Format("send2room {0}", nowData));
|
||
StartCoroutine(MoveObjectAlongPath(_positions)); // 启动协程,按规划的路线移动物体
|
||
}
|
||
}
|
||
|
||
public IEnumerator MoveObjectAlongPath(Vector3 _positions) // 协程:按路线移动物体
|
||
{
|
||
Vector3 targetPosition = new Vector3(_positions.x, 150, _positions.z);// 目标位置为当前顶点坐标
|
||
float _distance = Vector3.Distance(transform.position, targetPosition);
|
||
float _time = _distance / FireSpeed;
|
||
transform.LookAt(targetPosition);
|
||
transform.DOMove(targetPosition, _time).SetEase(Ease.Linear);
|
||
yield return new WaitForSeconds(_time); // 等待一帧时间
|
||
isMove = true;
|
||
}
|
||
public IEnumerator MoveObjectAlongPath(Vector3 _positions, bool _isMove) // 协程:按路线移动物体
|
||
{
|
||
Vector3 targetPosition = new Vector3(_positions.x, 200, _positions.z);// 目标位置为当前顶点坐标
|
||
float _distance = Vector3.Distance(transform.position, targetPosition);
|
||
float _time = _distance / FireSpeed;
|
||
transform.LookAt(targetPosition);
|
||
transform.DOMove(targetPosition, _time).SetEase(Ease.Linear);
|
||
yield return new WaitForSeconds(_time); // 等待一帧时间
|
||
equipmentCommon.isMove = _isMove;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无人机整体位置传递
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
protected string GetSyncData(Vector3 _positions)
|
||
{
|
||
return string.Format("{0},{1},{2},{3},{4}", "DronePosition", equipmentCommon.deviceID, _positions.x, _positions.y, _positions.z);
|
||
}
|
||
private void OnDestroy()
|
||
{
|
||
Destroy(airRoute.gameObject);
|
||
OnActivationChanged -= OnActivationChangedHandler;
|
||
}
|
||
|
||
|
||
}
|
||
public enum Pattern
|
||
{
|
||
待机,
|
||
警戒,
|
||
攻击
|
||
} |