using Assets.Scripts.Apis; using Assets.Scripts.Apis.Models; using System; using System.Linq; using System.Collections; using System.Collections.Generic; using UnityEngine.Networking; using Assets.Scenes.Ride.Scripts.Model; using Assets.Scenes.Ride.Scripts.Model.CyclingModels; using Assets.Scenes.Ride.Scripts; using Mapbox.Unity.Map; using UnityEngine; using GeoJSON.Net.Geometry; using TurfCS; using Mapbox.Utils; using Assets.Scripts; using System.Threading.Tasks; using UnityEngine.EventSystems; using UnityEngine.Events; using Assets.Scenes.Ride.Scripts.Model.RiderModels; using System.IO; using ChartAndGraph; using UnityEngine.UI; using System.Diagnostics; using UnityEngine.SceneManagement; public class CyclingController : DeviceServiceMonoBase { public AbstractMap map; public GameObject player; public GameObject UIObject; public RouteResultParam selectParamModel; public RouteResult routeResult; public GameObject minicamera; public Dictionary selectPlayerDic { set; get; } = new Dictionary(); public int preticks { get; set; } #region 参数 public MapRoute mapRoute { get; set; }//当前路书数据 public MapCompetition competition { get; set; }//当前赛事数据 private MapDataModel mapData { get; set; }//当前路书数据 private Route route { get; set; }//当前路书综合数据 public List mapRouteRankingList { get; set; } private Vector2d coordiantes;//当前地图中心 public bool isStart { get; set; }//当前游戏是否开始 public CyclingModel cyclingModel { get; set; }//当前骑行模式 public BaseCycling cyclingController { get; set; } private int routeId; public int competitionId { get; set; } private MapApi mapApi; public DateTime startTime { get; set; } public DateTime endTime; public bool isQuit; public bool isPause; #endregion GameObject loadingcanvas; AbstratctLoadingController loadingController; private async Task Login() { var result = await new UserApi().Login("15261826280", "123456", ""); App.CurrentUser = result.data; } GameObject miniMap { get; set; } GameObject resultPanel; public ChartDataSourceScript chartDataSourceScript { get; set; } public GraphChartBase graph { get; set; } private float activeSeconds { get; set; }//移动端用户进入骑行超过2min,界面进入沉浸状态 protected override void Awake() { base.Awake(); #if UNITY_EDITOR if (App.CurrentUser == null) { Login(); } #endif //获取路书信息 mapApi = ConfigHelper.mapApi; routeId = App.RouteIdParam > 0 ? App.RouteIdParam : 2633; competitionId = App.CompetionId; App.CompetionId = 0;//清空比赛参数 //处理异常中断的骑行 if (App.tempRecordData != null) { selectParamModel = App.tempRecordData.selectParam; competitionId = selectParamModel.CompetitionId ?? 0; routeId = selectParamModel.RouteId ?? 0; } Resources.UnloadUnusedAssets(); } void OnDestroy() { //MapUDPService.Dispose(); Resources.UnloadUnusedAssets(); GC.Collect(); } Transform target; GameObject watcher; Transform uiParent; GameObject uipanel { get; set; } GameObject onlineUserPrefab3d { get; set; } GameObject OnlineHeadPanel { get; set; } public GameObject GetOnlineheadPanel() { if (OnlineHeadPanel == null) { OnlineHeadPanel = Resources.Load("UI/Prefab/Ride/OnlineHeadPanel"); } return OnlineHeadPanel; } Material Graph3d { get; set; } Material Graph4 { get; set; } Material Graph1 { get; set; } public Material Get3dGraph2() { if (Graph3d == null) { Graph3d = Resources.Load("UI/Material/3dGraph2"); } return Graph3d; } public Material GetMaterial4() { if (Graph4 == null) { Graph4 = Resources.Load("UI/Material/4"); } return Graph4; } public Material GetMaterial1() { if (Graph1 == null) { Graph1 = Resources.Load("UI/Material/1"); } return Graph1; } Image CompetitionArrow { get; set; } public Image GetCompetitionArrow() { if (CompetitionArrow == null) { CompetitionArrow = Resources.Load("UI/Prefab/Match/CompetitionArrow"); } return CompetitionArrow; } Image CompetitionMobileArrow { get; set; } public Image GetCompetitionMobileArrow() { if (CompetitionMobileArrow == null) { CompetitionMobileArrow = Resources.Load("UI/Prefab/Match/Mobile/CompetitionArrow"); } return CompetitionMobileArrow; } private void Start() { var uicanvasScaler = UIObject.GetComponent(); var loadingcanvasScaler = transform.Find("LoadingCanvas").GetComponent(); #if UNITY_ANDROID || UNITY_IOS uipanel = Instantiate(Resources.Load("UI/Prefab/Ride/Mobile/Panel"), UIObject.transform); uicanvasScaler.referenceResolution = App.MobileResolution; loadingcanvasScaler.referenceResolution = App.MobileResolution; #else uipanel = Instantiate(Resources.Load("UI/Prefab/Ride/Panel"), UIObject.transform); uicanvasScaler.referenceResolution = App.PcResolution; loadingcanvasScaler.referenceResolution = App.PcResolution; var modalRect = transform.Find("UI/ModalPanel").GetComponent(); modalRect.anchorMin = new Vector2(0.5f, 0.5f); modalRect.anchorMax = new Vector2(0.5f, 0.5f); modalRect.offsetMin = Vector2.zero; modalRect.offsetMax = Vector2.zero; modalRect.sizeDelta = new Vector2(1600, 900); #endif uipanel.transform.SetAsFirstSibling(); uiParent = uipanel.transform; resultPanel = uiParent.Find("ResultPanel").gameObject; //获取海拔图UI对象 var graphObject = uiParent.Find("GraphChart"); chartDataSourceScript = graphObject.GetComponent(); graph = graphObject.GetComponent(); UIManager.Instance.MainPanel = uipanel.GetComponent(); UIManager.Instance.ModalsPanel = this.transform.Find("UI/ModalPanel").GetComponent(); onlineUserPrefab = Resources.Load("UI/Prefab/Ride/EmptyOnlinePlayer"); onlineUserPrefab3d = Resources.Load("UI/Prefab/Match/onlinePlayerNoScript"); miniMapPlayerPrefab = Resources.Load("UI/Prefab/Ride/MiniMapPlayer"); watcher = Resources.Load("UI/Prefab/Match/Watcher"); target = transform.Find("Target"); miniMap = transform.Find("MiniMap").gameObject;//小地图 minicamera = transform.Find("MiniCamera").gameObject; //进入倒计时 singleUIManager = UIObject.GetComponent(); TrailRenderer trail = player.GetComponent(); trail.Clear(); playerController = player.GetComponent(); currentPlayer = playerController;//当前选中用户 if (competitionId > 0) { loadingController = transform.Find("LoadingCanvas").gameObject.AddComponent(); } else { loadingController = transform.Find("LoadingCanvas").gameObject.AddComponent(); } //loadingController = FindObjectOfType(); // loadingController.InjectController(this); SceneManager.activeSceneChanged += SceneManager_activeSceneChanged; //进入比赛 if (competitionId > 0) { this.cyclingModel = CyclingModel.Competition; StartCoroutine(InitRace()); return; } //进入单人骑行 if (routeId > 0) { StartCoroutine(Init()); return; } } float timer = 1f; bool clearLock = false; private void SceneManager_activeSceneChanged(Scene arg0, Scene arg1) { ClearTempFile(); } /// /// 检测是否点击UI /// /// /// private bool IsPointerOverGameObject(Vector2 mousePosition) { //创建一个点击事件 PointerEventData eventData = new PointerEventData(EventSystem.current); eventData.position = mousePosition; List raycastResults = new List(); //向点击位置发射一条射线,检测是否点击UI EventSystem.current.RaycastAll(eventData, raycastResults); if (raycastResults.Count > 0) { return !raycastResults.Where(c => c.gameObject.name == "NearPanel" || c.gameObject.name == "ToolBarPanel" || c.gameObject.name == "SettingPanel" || c.gameObject.name == "QuitPanel").Any(); } else { return false; } } bool _dragStartedOnUI = false; protected override void Update() { base.Update(); //CamControl(); timer -= Time.deltaTime; if (timer <= 0)//定时器 一秒执行一次 { TcpHandler(); App.CurrentScene = "Ride"; if (competitionId == 0) { UIManager.SendCompetitionStartMessage("Ride"); } #if UNITY_IOS || UNITY_ANDROID //if (isStart) //{ // activeSeconds++; //} //if (activeSeconds >= App.autoClearTimes && !clearLock) //{ // if (competitionId == 0) // { // clearLock = true; // singleUIManager?.ClearPanel(null); // } //} #endif timer += 1.0f; } } float touchTimer = 0.1f; private void FixedUpdate() { touchTimer -= Time.deltaTime; if (touchTimer <= 0) { #if UNITY_IOS || UNITY_ANDROID HandleTouch(); #else HandleMouseScrollWheel(); #endif touchTimer += 0.1f; } } public bool isWatch { get; set; } private Vector3 currentCameraPos { get; set; } Vector3 far = new Vector3(-25, 73, -70); Vector3 plane = new Vector3(-15, 43, -40); Vector3 near = new Vector3(-8, 23, -20); List cameraList { get; set; } /// /// 处理PC端 /// private void HandleMouseScrollWheel() { var scrollDelta = Input.GetAxis("Mouse ScrollWheel"); UnityEngine.Debug.Log($"scrolldelta{scrollDelta}"); if (cameraList == null) { cameraList = new List(); cameraList.Add(near); cameraList.Add(plane); cameraList.Add(far); } var prePos = Camera.main.transform.localPosition; var nextPos = Camera.main.transform.localPosition; if (scrollDelta < 0) { nextPos = cameraList.Where(c => c.y > Camera.main.transform.localPosition.y).FirstOrDefault(); if (nextPos != Vector3.zero) StartCoroutine(MoveCamera(prePos, nextPos)); } if (scrollDelta > 0) { nextPos = cameraList.Where(c => c.y < Camera.main.transform.localPosition.y).LastOrDefault(); if (nextPos != Vector3.zero) StartCoroutine(MoveCamera(prePos, nextPos)); } } private void HandleTouch() { if (singleUIManager == null) return; var touchCount = Input.touchCount; switch (Input.touchCount) { case 1: { //单击切换极简模式 if (Input.touches[0].tapCount==1 && isStart && singleUIManager.clearLock && competitionId == 0) { if (IsPointerOverGameObject(Input.mousePosition)) { singleUIManager?.ClearPanel(null); } } } break; case 2: { //双手触摸移动摄像机 // Store both touches. Touch touchZero = Input.GetTouch(0); Touch touchOne = Input.GetTouch(1); // Find the position in the previous frame of each touch. Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition; Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition; // Find the magnitude of the vector (the distance) between the touches in each frame. float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude; float touchDeltaMag = (touchZero.position - touchOne.position).magnitude; var offset = touchDeltaMag - prevTouchDeltaMag; if (cameraList == null) { cameraList = new List(); cameraList.Add(near); cameraList.Add(plane); cameraList.Add(far); } var prePos = Camera.main.transform.localPosition; var nextPos = Camera.main.transform.localPosition; if (offset < 0) { nextPos = cameraList.Where(c => c.y > Camera.main.transform.localPosition.y).FirstOrDefault(); if (nextPos != Vector3.zero) StartCoroutine(MoveCamera(prePos, nextPos)); } if (offset > 0) { nextPos = cameraList.Where(c => c.y < Camera.main.transform.localPosition.y).LastOrDefault(); if (nextPos != Vector3.zero) StartCoroutine(MoveCamera(prePos, nextPos)); } } break; } } /// /// 处理中断骑行 /// private void TempFileHandler() { //处理异常中断的骑行 if (App.tempRecordData != null) { recorderData.EndDistance = App.tempRecordData.EndDistance; recorderData.StartTime = App.tempRecordData.StartTime; recorderData.RiderDatas = App.tempRecordData.RiderDatas; coordiantes = Along(App.tempRecordData.EndDistance); startTime = App.tempRecordData.StartTime; preticks = recorderData.RiderDatas.Last().Ticks; App.tempRecordData = null;//清空 } } private IEnumerator Init() { yield return new WaitForSeconds(1); mapRoute = mapApi.GetById(routeId).data; loadingController.Init();//初始化loading页面 loadingController.AddProcess(10); InitData();//初始化数据 InitGameObject();//初始化场景 MapUDPService.Init();//初始化TCP loadingController.AddProcess(10); } //初始比赛 private IEnumerator InitRace() { yield return new WaitForSeconds(1); mapRoute = mapApi.GetById(routeId).data; var mapCompetitionApi = new MapCompetitionApi(); competition = mapCompetitionApi.GetById(competitionId).data; loadingController.Init();//初始化loading页面 loadingController.AddProcess(10); InitRaceData();//初始化比赛数据 InitRaceGameObject();//初始化比赛场景 //MapUDPService.Init(competitionId,isWatch);//初始化比赛TCP loadingController.AddProcess(10); } public void InitTcp() { MapUDPService.Init(competitionId, isWatch);//初始化比赛TCP } //初始化数据 private void InitData() { mapData = mapApi.GetData(routeId);//获取路书地理数据 route = new Route(mapData, mapRoute); loadingController.AddProcess(10); #region 其他场景传参处理 //骑行结果 if (App.routeResult != null) { routeResult = App.routeResult; selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行 preticks = App.routeResult.Ticks; } if (selectParamModel == null) { selectParamModel = new RouteResultParam { CompetitionId = 0, ContinueIndex = 0, ContinueMark = "", GlobalContinue = false, EndDistance = 0, RankingsId = new List(), OnlineUserId = 0, RouteId = App.RouteIdParam }; } App.routeResult = null; #endregion double endDistance = selectParamModel.EndDistance; coordiantes = Along(endDistance); var shaowList = mapApi.GetShadowList(routeId, "", 0, 10); if (shaowList.result) { mapRouteRankingList = shaowList.data.list; } } private void InitRaceData() { mapData = mapApi.GetData(routeId);//获取路书地理数据 route = new Route(mapData, mapRoute); loadingController.AddProcess(10); #region 其他场景传参处理 selectParamModel = new RouteResultParam { CompetitionId = competitionId, ContinueIndex = 0, ContinueMark = "", GlobalContinue = false, EndDistance = 0, RankingsId = new List(), OnlineUserId = 0, RouteId = App.RouteIdParam }; #endregion double endDistance = selectParamModel.EndDistance; //计算上次骑行距离调整地图中心点 coordiantes = Along(endDistance); } private Vector3 mapPos = Vector3.zero; //加载人物和地图以及UI界面 private void InitGameObject() { #if !(UNITY_IOS || UNITY_ANDROID) minicamera.SetActive(true); miniMap.SetActive(true); #endif map.gameObject.SetActive(true); player.SetActive(true); UIObject.SetActive(true); singleUIManager = UIObject.AddComponent(); map.OnTileFinished += Map_OnTileFinished; mapPos = map.transform.position; } private void InitRaceGameObject() { #if !(UNITY_IOS || UNITY_ANDROID) minicamera.SetActive(true); #endif map.gameObject.SetActive(true); player.SetActive(true); UIObject.SetActive(true); singleUIManager = UIObject.AddComponent(); //miniMap.SetActive(true); map.OnTileFinished += Map_OnTileFinished; mapPos = map.transform.position; //为了解决比赛观看模式下,切换观看用户之前跨度过大导致地图海拔信息不完整的问题 RangeAroundTransformTileProviderOptions options = new RangeAroundTransformTileProviderOptions { targetTransform = target, visibleBuffer = 2, disposeBuffer = 2 }; map.SetExtent(MapExtentType.RangeAroundTransform, options); map.SetExtentOptions(options); } //设置骑行模式 public void SetCyclingModel(CyclingModel mode) { this.cyclingModel = mode; switch (cyclingModel) { case CyclingModel.Single: cyclingController = new SingleModel(route, selectParamModel); break; case CyclingModel.Review: cyclingController = new ReviewModel(route, selectParamModel); break; case CyclingModel.Competition: cyclingController = new CompetitionModel(route, selectParamModel, currentPlayer); break; } GameStart(); InitPlayer();//初始化人物方向等 } PlayerController playerController; public AbstractPlayer currentPlayer { get; set; } private GameObject onlinePlayer { get; set; } Vector3 MAX_SIZE = new Vector3(3f, 3f, 3f); Vector3 MIN_SIZE = new Vector3(1f, 1f, 1f); public void ChangeCurrentPlayer(int userId) { var coll = FindObjectsOfType(); var selectedPlayer = coll.Where(c => c.UserId == userId).FirstOrDefault(); if (selectedPlayer != null) { currentPlayer = selectedPlayer; if (selectedPlayer is PlayerController) { selectedPlayer.transform.localScale = Is3dView ? MAX_SIZE : MIN_SIZE; } else { Utils.DestroyChildren(selectedPlayer.transform); var ss = Instantiate(onlineUserPrefab3d, selectedPlayer.transform); ss.transform.localScale = Is3dView ? MAX_SIZE : MIN_SIZE; } } var unselectedPlayers = coll.Where(c => c.UserId != userId).ToList(); foreach (var item in unselectedPlayers) { item.transform.localScale = MIN_SIZE; if (item.transform.childCount > 0) { Utils.DestroyChildren(item.transform); } } //重置海拔图进度 var currentIndex = currentPlayer.CurrentIndex; graph.HorizontalScrolling = chartDataSourceScript.GetCurrentStart(currentIndex); } //初始化人物位置角度 private void InitPlayer() { TempFileHandler();//处理中断骑行继续骑的逻辑 lockView = true; Vector2d lastLatLon = Along(recorderData.EndDistance); Vector3 currentPos = map.GeoToWorldPosition(lastLatLon); currentPos.y += 1f; player.transform.position = currentPos; playerController.currentPos = currentPos; var trail = FindObjectOfType(); trail.enabled = true; Vector2d nextLatLon = Along(recorderData.EndDistance + 0.1); //设定人物方向 var s = map.GeoToWorldPosition(lastLatLon); var e = map.GeoToWorldPosition(nextLatLon); Quaternion neededRotation = Quaternion.LookRotation(s - e); player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0); playerController.currentRotation = neededRotation; //初始化海拔图头像位置 var index = GetCurrentIndex(recorderData.EndDistance); InitGraph(index); int tick = 0; if (recorderData.RiderDatas.Count > 0) { tick = recorderData.RiderDatas.Last().Ticks; } playerController.Init(index, recorderData.EndDistance, tick); } public void InitGraph(int index) { chartDataSourceScript.InitHorizontalScrolling(index); } private IEnumerator MoveCamera(Vector3 prePos, Vector3 nextPos) { float t = 0; while (t < 0.5f) { t += Time.deltaTime; Vector3 v = Vector3.Lerp(prePos, nextPos, t); Camera.main.transform.localPosition = v; yield return new WaitForEndOfFrame(); } } //SingleUIManager singleUIManager; public BaseUIManager singleUIManager; public void GameStart() { StartCoroutine(MoveCamera(far, plane));//初始摄像头 var check = CheckAnt(); #if UNITY_EDITOR check = true; #endif if (check || isWatch) { singleUIManager.StartRide(); transform.Find("UI/Panel(Clone)/ToolBarPanel/StartOrPauseButton").GetComponent