using DG.Tweening; using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Rendering.HighDefinition; /// /// UAV模拟控制器,不跟随移动 /// 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; /// /// 速度最大最小值 /// public float min, max; /// /// 定点飞行模式 /// public bool FlyToFixedPointMode; /// /// 固定方向飞行时间 /// //public float fly_by_direction_time; #region 无人机编队飞行数据 /// /// 无人机执行时刻队列 /// public Queue uav_time_queue = new Queue(); /// /// 时间与数据字典 /// public Dictionary uav_time_data = new Dictionary(); /// /// 下一个执行时间点 /// private float next_time = -1; /// /// 下一条执行数据 /// private UavTimeData next_uav_time_data; /// /// 当前时间 /// private float current_time; #endregion /// /// 无人机模拟控制器初始化 /// public void Init() { if (controller == null) controller = transform.parent.GetComponentInChildren(); 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(); } /// /// 启动 /// public void StartUav() { if (!controller.motorOn) { f1 = f2 = f3 = f4 = 1; } controller.ToggleMotor(1); } /// /// 关闭 /// public void ShutDownUAV() { controller.ToggleMotor(0); f1 = f2 = f3 = f4 = 0; } /// /// 直接控制物体运动 /// /// /// 速度 /// 是否使用给定速度 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; } } /// /// 进入悬停模式 /// 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; } /// /// 手动控制旋翼转速 /// 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; } /// /// 自动控制旋翼转速 /// 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; } /// /// 打开、更新灯光设置 /// /// 颜色 /// 灯光强度 /// 光晕强度 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().enabled = false; //关闭碰撞 transform.parent.Find("_Drone [Quad]").GetComponents().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); } /// /// 关闭无人机灯光 /// 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().enabled = true; //打开碰撞 transform.parent.Find("_Drone [Quad]").GetComponents().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); } /// /// 重置无人机 /// public void ResetUAV() { ShutDownUAV(); controller.transform.localPosition = new Vector3(0, 0, 0); controller.transform.eulerAngles = Vector3.zero; } /// /// 速度优化 /// public float conversion = 10; /// /// 质量 /// public int mass; public float f_all, f1, f2, f3, f4; public float f_升降, f_前后, f_左右, f_旋转; /// /// 由方向飞行 /// /// 速度方向 /// 飞行时间 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); } /// /// 退出由方向飞行状态 /// public void ExitFlyByDirection() { //fly_by_direction_time = 0; //AutoSpeed(); VelocityController(false); } /// /// 根据时间飞至指定位置 /// /// /// public void ToTargetByTime(Vector3 _tar, float _fly_time, Action _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); }); } /// /// 根据速度飞至指定位置 /// /// /// public void ToTargetBySpeed(Vector3 _tar, float _fly_speed, Action _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); }); } /// /// 飞路径 /// /// /// /// public void ToPathByTime(List points, float time, Color color,float thick ,Action _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); }); } /// /// 无人机f动力输入 /// 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)); } /// /// 无人机速度钳制 /// /// /// private float SpeedClamp(float value) => Mathf.Clamp(value, min, max); /// /// 无人机飞行数据处理 /// /// 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; } /// /// 执行数据 /// 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; } } } /// /// 更新无人机模型颜色 /// 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); } }