522 lines
18 KiB
C#
522 lines
18 KiB
C#
using DG.Tweening;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering.HighDefinition;
|
||
|
||
/// <summary>
|
||
/// UAV模拟控制器,不跟随移动
|
||
/// </summary>
|
||
public class UAVSimulator : MonoBehaviour
|
||
{
|
||
//[HideInInspector]
|
||
public UAVController controller;//本体上
|
||
public UavTrailRender uav_trail_render;//轨迹渲染器
|
||
public LODGroup uav_lighter_lod_group;
|
||
public MeshRenderer uav_lighter_meshrenderer;//无人机灯光渲染器
|
||
public MeshRenderer[] uav_model_meshrenderer;//无人机模型渲染器
|
||
public Material uav_lighter_mat;//无人机灯光材质
|
||
public Transform uav_fps_camera_transform;//第一人称位置
|
||
public int uav_id;
|
||
public string uav_name;
|
||
|
||
public float rise_speed_modify = 4;
|
||
public float descend_speed_modify = 4;
|
||
public float move_speed_modify = 4;
|
||
public float rotate_speed_modify = 4;
|
||
public float minf = 8;
|
||
|
||
/// <summary>
|
||
/// 速度最大最小值
|
||
/// </summary>
|
||
public float min, max;
|
||
/// <summary>
|
||
/// 定点飞行模式
|
||
/// </summary>
|
||
public bool FlyToFixedPointMode;
|
||
/// <summary>
|
||
/// 固定方向飞行时间
|
||
/// </summary>
|
||
//public float fly_by_direction_time;
|
||
|
||
#region 无人机编队飞行数据
|
||
/// <summary>
|
||
/// 无人机执行时刻队列
|
||
/// </summary>
|
||
public Queue<float> uav_time_queue = new Queue<float>();
|
||
/// <summary>
|
||
/// 时间与数据字典
|
||
/// </summary>
|
||
public Dictionary<float, UavTimeData> uav_time_data = new Dictionary<float, UavTimeData>();
|
||
/// <summary>
|
||
/// 下一个执行时间点
|
||
/// </summary>
|
||
private float next_time = -1;
|
||
/// <summary>
|
||
/// 下一条执行数据
|
||
/// </summary>
|
||
private UavTimeData next_uav_time_data;
|
||
/// <summary>
|
||
/// 当前时间
|
||
/// </summary>
|
||
private float current_time;
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 无人机模拟控制器初始化
|
||
/// </summary>
|
||
public void Init()
|
||
{
|
||
if (controller == null)
|
||
controller = transform.parent.GetComponentInChildren<UAVController>();
|
||
if (uav_lighter_meshrenderer != null)
|
||
uav_lighter_mat = uav_lighter_meshrenderer.material;
|
||
if (GameManager.Instance)
|
||
{
|
||
uav_lighter_lod_group.ForceLOD(GameManager.current_scene_time == "夜" ? 1 : -1);
|
||
}
|
||
}
|
||
|
||
private void FixedUpdate()
|
||
{
|
||
f_all = f1 + f2 + f3 + f4;
|
||
|
||
if (f_all > mass)
|
||
{
|
||
f_升降 = (f_all - mass) / rise_speed_modify;
|
||
}
|
||
else
|
||
{
|
||
f_升降 = (f_all - mass) / descend_speed_modify;
|
||
}
|
||
//>0上升;<0下降
|
||
//f_前后 = (f3 + f4) - (f1 + f2);//>0向前;<0向后
|
||
//f_左右 = (f1 + f3) - (f2 + f4);//>0右移;<0左移
|
||
//f_旋转 = (f1 + f4) - (f2 + f3);//>0顺时针;<0逆时针
|
||
|
||
f_前后 = ((f3 + f4) - (f1 + f2)) / move_speed_modify;//>0向前;<0向后
|
||
f_左右 = ((f1 + f3) - (f2 + f4)) / move_speed_modify;//>0右移;<0左移
|
||
f_旋转 = ((f1 + f4) - (f2 + f3)) / rotate_speed_modify;//>0顺时针;<0逆时针
|
||
|
||
controller.SingleDrone(0, f1);
|
||
controller.SingleDrone(1, f2);
|
||
controller.SingleDrone(2, f3);
|
||
controller.SingleDrone(3, f4);
|
||
|
||
Use();
|
||
DoDataUpdate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启动
|
||
/// </summary>
|
||
public void StartUav()
|
||
{
|
||
if (!controller.motorOn)
|
||
{
|
||
f1 = f2 = f3 = f4 = 1;
|
||
}
|
||
controller.ToggleMotor(1);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 关闭
|
||
/// </summary>
|
||
public void ShutDownUAV()
|
||
{
|
||
controller.ToggleMotor(0);
|
||
f1 = f2 = f3 = f4 = 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 直接控制物体运动
|
||
/// </summary>
|
||
/// <param name="_mode_ison"> </param>
|
||
/// <param name="_velocity"> 速度</param>
|
||
/// <param name="_use_velocity"> 是否使用给定速度</param>
|
||
public void VelocityController(bool _mode_ison, Vector3 _velocity = new Vector3(), bool _use_velocity = false)
|
||
{
|
||
controller.mode_fly_by_propeller = false;
|
||
controller.mode_fly_by_direction = _mode_ison;
|
||
|
||
if (_use_velocity)
|
||
{
|
||
controller.rigidBody.velocity = _velocity;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 进入悬停模式
|
||
/// </summary>
|
||
public void HoveringController()
|
||
{
|
||
DOTween.Kill(controller.transform);
|
||
controller.mode_fly_by_propeller = false;
|
||
controller.mode_fly_by_direction = false;
|
||
controller.simulated_flight_speed = 0;
|
||
controller.simulated_flight_speed_direction = Vector3.zero;
|
||
FlyToFixedPointMode = false;
|
||
f1 = f2 = f3 = f4 = 5;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动控制旋翼转速
|
||
/// </summary>
|
||
public void ManualSpeed()
|
||
{
|
||
DOTween.Kill(controller.transform);
|
||
ExitFlyByDirection();
|
||
controller.rigidBody.velocity = Vector3.zero;
|
||
controller.simulated_flight_speed = 0;
|
||
controller.simulated_flight_speed_direction = Vector3.zero;
|
||
|
||
controller.mode_fly_by_propeller = true;
|
||
controller.mode_fly_by_direction = false;
|
||
FlyToFixedPointMode = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自动控制旋翼转速
|
||
/// </summary>
|
||
public void AutoSpeed()
|
||
{
|
||
DOTween.Kill(controller.transform);
|
||
ExitFlyByDirection();
|
||
controller.rigidBody.velocity = Vector3.zero;
|
||
controller.mode_fly_by_propeller = false;
|
||
controller.mode_fly_by_direction = false;
|
||
FlyToFixedPointMode = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打开、更新灯光设置
|
||
/// </summary>
|
||
/// <param name="_color">颜色</param>
|
||
/// <param name="_intensity">灯光强度</param>
|
||
/// <param name="_halo">光晕强度</param>
|
||
public void OpenLighter(string _color, float _intensity=1, float _halo = 0.04f)
|
||
{
|
||
if (_color == null) return;
|
||
|
||
transform.parent.Find("_Drone [Quad]/Root").gameObject.SetActive(false);
|
||
transform.parent.Find("_Drone [Quad]/FPSView").gameObject.SetActive(false);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Front)").gameObject.SetActive(false);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Back)").gameObject.SetActive(false);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Right)").gameObject.SetActive(false);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Left)").gameObject.SetActive(false);
|
||
transform.parent.Find("_Drone [Quad]/PoliceRadioChatter").gameObject.SetActive(false);
|
||
transform.parent.GetComponent<LODGroup>().enabled = false;
|
||
//关闭碰撞
|
||
transform.parent.Find("_Drone [Quad]").GetComponents<Collider>().ToList().ForEach(a =>
|
||
{
|
||
a.enabled = false;
|
||
});
|
||
//设置无人机不掉下去
|
||
StartUav();
|
||
AutoSpeed();
|
||
f1 = f2 = f3 = f4 = 5;
|
||
|
||
_intensity = Mathf.Clamp01(_intensity);
|
||
ColorUtility.TryParseHtmlString(_color, out Color __color);
|
||
uav_lighter_mat.color = __color;
|
||
//uav_lighter_mat.EnableKeyword("_EMISSION");
|
||
//Color.RGBToHSV(__color, out float _h, out float _s, out float _v);
|
||
//uav_lighter_mat.SetColor("_EmissiveColorLDR", Color.HSVToRGB(_h, _s, _intensity * 10));
|
||
uav_lighter_mat.SetColor("_MColor", __color);
|
||
uav_lighter_mat.SetFloat("_ExposureWeight", _halo);
|
||
uav_lighter_mat.SetFloat("_TransparentValue", _intensity);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 关闭无人机灯光
|
||
/// </summary>
|
||
public void CloseLighter()
|
||
{
|
||
transform.parent.Find("_Drone [Quad]/Root").gameObject.SetActive(true);
|
||
transform.parent.Find("_Drone [Quad]/FPSView").gameObject.SetActive(true);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Front)").gameObject.SetActive(true);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Back)").gameObject.SetActive(true);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Right)").gameObject.SetActive(true);
|
||
transform.parent.Find("_Drone [Quad]/Tilt (Left)").gameObject.SetActive(true);
|
||
transform.parent.Find("_Drone [Quad]/PoliceRadioChatter").gameObject.SetActive(true);
|
||
transform.parent.GetComponent<LODGroup>().enabled = true;
|
||
//打开碰撞
|
||
transform.parent.Find("_Drone [Quad]").GetComponents<Collider>().ToList().ForEach(a =>
|
||
{
|
||
a.enabled = true;
|
||
});
|
||
|
||
uav_lighter_mat.SetColor("_MColor", Color.white);
|
||
uav_lighter_mat.SetFloat("_ExposureWeight", 0);
|
||
uav_lighter_mat.SetFloat("_TransparentValue", 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置无人机
|
||
/// </summary>
|
||
public void ResetUAV()
|
||
{
|
||
ShutDownUAV();
|
||
controller.transform.localPosition = new Vector3(0, 0, 0);
|
||
controller.transform.eulerAngles = Vector3.zero;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 速度优化
|
||
/// </summary>
|
||
public float conversion = 10;
|
||
/// <summary>
|
||
/// 质量
|
||
/// </summary>
|
||
public int mass;
|
||
|
||
public float f_all, f1, f2, f3, f4;
|
||
|
||
public float f_升降, f_前后, f_左右, f_旋转;
|
||
|
||
/// <summary>
|
||
/// 由方向飞行
|
||
/// </summary>
|
||
/// <param name="_velocity_direction"> 速度方向 </param>
|
||
/// <param name="_time"> 飞行时间 </param>
|
||
public void FlyByDirection(Vector3 _velocity_direction, float _speed, float _time)
|
||
{
|
||
StartUav();
|
||
AutoSpeed();
|
||
f1 = f2 = f3 = f4 = 5;
|
||
//fly_by_direction_time = _time;
|
||
//VelocityController(true, _velocity_direction.normalized * _speed, true);
|
||
controller.simulated_flight_speed = _speed;
|
||
controller.simulated_flight_speed_direction = _velocity_direction;
|
||
controller.transform.DOMove(_velocity_direction * _speed * _time + controller.transform.position, _time).OnComplete(() => { VelocityController(false); HoveringController(); });
|
||
//到达时间后退出状态
|
||
//Invoke("ExitFlyByDirection", fly_by_direction_time);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 退出由方向飞行状态
|
||
/// </summary>
|
||
public void ExitFlyByDirection()
|
||
{
|
||
//fly_by_direction_time = 0;
|
||
//AutoSpeed();
|
||
VelocityController(false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据时间飞至指定位置
|
||
/// </summary>
|
||
/// <param name="_tar"></param>
|
||
/// <param name="_fly_time"></param>
|
||
public void ToTargetByTime(Vector3 _tar, float _fly_time, Action<bool> _callback = null)
|
||
{
|
||
StartUav();
|
||
AutoSpeed();
|
||
f1 = f2 = f3 = f4 = 5;
|
||
//FlyToFixedPointMode = true;
|
||
//VelocityController(true);
|
||
controller.simulated_flight_speed_direction = (_tar + transform.parent.parent.position) - controller.transform.position;
|
||
controller.simulated_flight_speed = Vector3.Distance(controller.transform.position, controller.transform.position + (_tar + transform.parent.parent.position)) / _fly_time;
|
||
controller.transform.DOMove(_tar + transform.parent.parent.position, _fly_time).OnComplete(() => { VelocityController(false); HoveringController(); _callback?.Invoke(true); });
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据速度飞至指定位置
|
||
/// </summary>
|
||
/// <param name="tar"></param>
|
||
/// <param name="fly_speed"></param>
|
||
public void ToTargetBySpeed(Vector3 _tar, float _fly_speed, Action<bool> _callback = null)
|
||
{
|
||
StartUav();
|
||
AutoSpeed();
|
||
f1 = f2 = f3 = f4 = 5;
|
||
//FlyToFixedPointMode = true;
|
||
controller.simulated_flight_speed = _fly_speed;
|
||
controller.simulated_flight_speed_direction = (_tar + transform.parent.parent.position) - controller.transform.position;
|
||
var _fly_time = Vector3.Distance(_tar, controller.transform.localPosition) / _fly_speed;
|
||
//VelocityController(true);
|
||
controller.transform.DOMove(_tar + transform.parent.parent.position, _fly_time).OnComplete(() =>
|
||
{
|
||
VelocityController(false);
|
||
HoveringController();
|
||
_callback?.Invoke(true);
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 飞路径
|
||
/// </summary>
|
||
/// <param name="points"></param>
|
||
/// <param name="_fly_speed"></param>
|
||
/// <param name="_callback"></param>
|
||
public void ToPathByTime(List<Vector3> points, float time, Color color,float thick ,Action<bool> _callback = null)
|
||
{
|
||
StartUav();
|
||
AutoSpeed();
|
||
f1 = f2 = f3 = f4 = 5;
|
||
|
||
//根据gamecenter偏移
|
||
for (int i = 0; i < points.Count; i++)
|
||
{
|
||
points[i] = transform.parent.parent.position + points[i];
|
||
}
|
||
|
||
//关闭轨迹,先飞至第一个点
|
||
uav_trail_render.Close();
|
||
Debug.Log("OnWaypointChange 共:"+points.Count);
|
||
controller.transform.DOPath(points.ToArray(), time).OnWaypointChange(a =>
|
||
{
|
||
Debug.Log("OnWaypointChange: "+a+" 坐标:"+ points[a-1]);
|
||
if (a == 1)
|
||
{
|
||
//到首个点打开轨迹
|
||
uav_trail_render.Open(color, thick, true);
|
||
//路径模式生成第一个点
|
||
uav_trail_render.UpdateTrail(points[0]);
|
||
}
|
||
else
|
||
{
|
||
//更新点
|
||
uav_trail_render.UpdateTrail(points[a - 1]);
|
||
}
|
||
}).OnComplete(() =>
|
||
{
|
||
uav_trail_render.Close();
|
||
_callback?.Invoke(true);
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无人机f动力输入
|
||
/// </summary>
|
||
public void Use()
|
||
{
|
||
if (FlyToFixedPointMode) return;
|
||
controller.LiftInput(SpeedClamp(f_升降 / conversion));
|
||
controller.DriveInput(SpeedClamp(f_前后 / conversion));
|
||
controller.StrafeInput(SpeedClamp(f_左右 / conversion));
|
||
controller.TurnInput(SpeedClamp(f_旋转 / conversion));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无人机速度钳制
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <returns></returns>
|
||
private float SpeedClamp(float value) => Mathf.Clamp(value, min, max);
|
||
|
||
/// <summary>
|
||
/// 无人机飞行数据处理
|
||
/// </summary>
|
||
/// <param name="_uav_data"></param>
|
||
public float HandleUavTimeData(UavIndexData _uav_data)
|
||
{
|
||
controller.fallAfterCollision = false;//关闭撞击后坠落
|
||
float __max_time = _uav_data.uav_time_data[0].time;
|
||
bool match;
|
||
//先做排序,确保时间顺序
|
||
for (int i = 0; i < _uav_data.uav_time_data.Length; i++)
|
||
{
|
||
match = false;
|
||
for (int j = 0; j < _uav_data.uav_time_data.Length - i - 1; j++)
|
||
{
|
||
if (_uav_data.uav_time_data[j].time > _uav_data.uav_time_data[j + 1].time)
|
||
{
|
||
var temp = _uav_data.uav_time_data[j];
|
||
_uav_data.uav_time_data[j] = _uav_data.uav_time_data[j + 1];
|
||
_uav_data.uav_time_data[j + 1] = temp;
|
||
|
||
match = true;
|
||
}
|
||
if (_uav_data.uav_time_data[j + 1].time > __max_time)
|
||
__max_time = _uav_data.uav_time_data[j + 1].time;
|
||
if (match)
|
||
continue;
|
||
}
|
||
}
|
||
|
||
//排序完毕,数据加入队列,同时以字典形式保存数据
|
||
for (int i = 0; i < _uav_data.uav_time_data.Length; i++)
|
||
{
|
||
uav_time_queue.Enqueue(_uav_data.uav_time_data[i].time);
|
||
if (!uav_time_data.ContainsKey(_uav_data.uav_time_data[i].time))
|
||
uav_time_data.Add(_uav_data.uav_time_data[i].time, _uav_data.uav_time_data[i]);
|
||
}
|
||
|
||
//使用固定旋翼转速,不影响数据飞行
|
||
StartUav();
|
||
AutoSpeed();
|
||
f1 = f2 = f3 = f4 = 5;
|
||
FlyToFixedPointMode = true;
|
||
|
||
return __max_time;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行数据
|
||
/// </summary>
|
||
private void DoDataUpdate()
|
||
{
|
||
if (uav_time_queue.Count > 0)
|
||
{
|
||
//时刻队列有数据时开始计时
|
||
current_time += Time.deltaTime;
|
||
if (next_uav_time_data == null)
|
||
{
|
||
//查看下一条时间,并取出到达下一条时间时无人机应处的位置
|
||
next_time = uav_time_queue.Peek();
|
||
next_uav_time_data = uav_time_data[next_time];
|
||
|
||
var __duration_time = next_time - current_time;
|
||
if (next_uav_time_data.position != null)
|
||
{
|
||
//无人机根据时间差及位置执行飞行任务
|
||
var __pos = next_uav_time_data.position.Split(',');
|
||
var __target_position = new Vector3(float.Parse(__pos[0]), float.Parse(__pos[1]), float.Parse(__pos[2]));
|
||
if (!UAVManager.Instance.useGlobalPosition) __target_position += UAVManager.Instance.UAVParent.position;
|
||
|
||
//执行飞行
|
||
controller.VirtualFlightSpeed = Vector3.Distance(__target_position, controller.transform.position) / __duration_time;
|
||
//DOTween.To(() => controller.transform.position, (t) => controller.transform.position = t, __target_position, __duration_time).SetEase(Ease.Linear);
|
||
VelocityController(true);
|
||
controller.transform.DOMove(__target_position, __duration_time).OnComplete(() => { VelocityController(false); HoveringController(); });
|
||
}
|
||
if (next_uav_time_data.color != null)
|
||
{
|
||
OpenLighter(next_uav_time_data.color, next_uav_time_data.intensity);
|
||
}
|
||
}
|
||
|
||
if (current_time >= next_time)
|
||
{
|
||
//当时间达到所查询的时间时,清空该条时间位置数据,并取出队列中已执行的时间
|
||
next_uav_time_data = null;
|
||
uav_time_queue.Dequeue();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (current_time != 0)
|
||
{
|
||
current_time = 0;
|
||
next_time = -1;
|
||
//controller.autoAttitudeControl = true;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 更新无人机模型颜色
|
||
/// </summary>
|
||
public void UpdateModelColor(Color _color_1, Color _color_2)
|
||
{
|
||
Array.ForEach(uav_model_meshrenderer, (_renderer) =>
|
||
{
|
||
_renderer.material.SetColor("_Area_1_Col", _color_1);
|
||
_renderer.material.SetColor("_Area_2_Col", _color_2);
|
||
});
|
||
|
||
//uav_model_meshrenderer.material.SetColor("_Area_2_Col", _color_2);
|
||
}
|
||
}
|