ict.lixian.single/Assets/Scripts/UAV/UAVSimulator.cs

522 lines
18 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}