/******************************************************************************** * 文件名: ActiveSceneManager.cs * 全路径: \Script\Scene\ActiveSceneManager.cs * 创建人: 李嘉 * 创建时间:2013-10-29 * * 功能说明:游戏当前激活场景,负责游戏的场景数据保存和提供常用方法 * 修改记录: *********************************************************************************/ using Games.GlobeDefine; using Games.LogicObj; using GCGame.Table; using Module.Log; using UnityEngine; using UnityEngine.AI; namespace Games.Scene { public class Scene_Init_Data { public bool m_bIsValid; //该结构体是否合法,创建的时候不合法,必须手动赋值后再设置该项 public int m_nCurSceneSrvID; //场景服务器ID private Scene_Init_Data() { m_bIsValid = false; } } public class ActiveScene { public const float navSampleHeight = 5f; public const float raycastHeight = 200f; public const float sphereCastRadius = 3f; public const float edgeSnapDist = 0.05f; //public static Vector3 GetTrrainPositionByAndroid(Vector3 orgPosition) //{ // Vector3 newPosition = orgPosition; // // return newPosition; //} public static readonly int terrainLayMask = LayerMask.GetMask("Default", "T4MLayer"); public static readonly int obstacleLayer = LayerMask.NameToLayer("Terrain"); private SkillCircleProjector _skillCircleProjector; //技能范围光圈 public DialogTipUIRoot DialogTipUIRoot; private float m_ChangeTime = -1; ////////////////////////////////////////////////////////////////////////// //地面特效部分 ////////////////////////////////////////////////////////////////////////// private GameObject m_MovingCircle; //地表移动特效 private float m_SceneTimeScaleStart = -1; private GameObject m_SelectCircle; //怪物选中特效 private GameObject m_SelectCircleNPC; //NPC选中特效 //地形文件 public ActiveScene() { SelectObj = null; //TerrainData = null; } /// /// 场景主摄像机 /// //public GameObject MainCamera { get; private set; } public int CurSceneServerID { get; set; } public GameObject UIRoot { get; set; } public GameObject FellowDialogueRoot { set; get; } public GameObject NameBoardRoot { set; get; } public GameObject FakeObjRoot { get; set; } public GameObject FakeObjTrans { get { return FakeObjRoot.transform.Find("TransformOff").gameObject; } } public GameObject[] SceneAudioSources { get; set; } public GameObject Teleport { get; set; } public GameObject TeleportCopyScene { get; set; } public GameObject[] QingGongPointList { get; set; } //名字版池子 // 注:之前实现方式已经脱离名字版池的概念,在移除相关代码前只有Player名字板受到这个东西影响,其他类型都脱离了该系统。 //private GameObjectPool m_NameBoardPool = null; //public GameObjectPool NameBoardPool //{ // get { return m_NameBoardPool; } // set { m_NameBoardPool = value; } //} public GameObject SelectObj { get; set; } //设置移动特效状态和位置 public void ActiveMovingCircle(Vector3 pos) { if (null == m_MovingCircle) return; if (!m_MovingCircle.activeSelf) m_MovingCircle.SetActive(true); m_MovingCircle.transform.position = pos; //DeactiveSelectCircle(); } public void DeactiveMovingCircle() { if (null != m_MovingCircle) m_MovingCircle.SetActive(false); } //设置选择特效状态和位置 public void ActiveSelectCircle(GameObject obj) { //在开启显示服务器主角位置的情况下,选中特效作为位置显示使用,不参与选中逻辑 if (GameManager.gameManager.ShowMainPlayerServerTrace) return; if (null == obj) return; //激活 SelectObj = obj; var camp = 1; var targetObj = SelectObj.GetComponent(); if (targetObj != null) if (Reputation.CanAttack(targetObj)) camp = 0; SetCirCleColor(camp); //float height = 0; //if (GameManager.gameManager.ActiveScene.IsT4MScene()) //{ // height = GameManager.gameManager.ActiveScene.GetTerrainHeight(obj.transform.position); //} //else //{ // height = UnityEngine.Terrain.activeTerrain.SampleHeight(obj.transform.position); //} ////由于特效需要显示在最上层,所以判断点击点和地表哪个更高,取最高值 //if (height > obj.transform.position.y) //{ // Vector3 pos = m_SelectCircle.transform.position; // pos.y = height; // m_SelectCircle.transform.position = pos; //} } //设置选中框的颜色 public void SetCirCleColor(int camp) { if (SelectObj == null) { if (m_SelectCircle) m_SelectCircle.SetActive(false); if (m_SelectCircleNPC) m_SelectCircleNPC.SetActive(false); } else { GameObject current; GameObject other; if (camp > 0) { current = m_SelectCircleNPC; other = m_SelectCircle; } else { current = m_SelectCircle; other = m_SelectCircleNPC; } if (current != null) { current.transform.position = SelectObj.transform.position; current.SetActive(true); } if (other != null) other.SetActive(false); } } public void DeactiveSelectCircle() { //在开启显示服务器主角位置的情况下,选中特效作为位置显示使用,不参与选中逻辑 if (GameManager.gameManager.ShowMainPlayerServerTrace) return; if (null != m_SelectCircle) m_SelectCircle.SetActive(false); if (null != m_SelectCircleNPC) m_SelectCircleNPC.SetActive(false); SelectObj = null; } private void UpdateSelectCircle() { //在开启显示服务器主角位置的情况下,选中特效作为位置显示使用,不参与选中逻辑 if (GameManager.gameManager.ShowMainPlayerServerTrace) return; if (null != SelectObj) { var z = SceneLogic.CameraController != null && SceneLogic.CameraController.MainCamera != null ? -SceneLogic.CameraController.MainCamera.transform.forward : Vector3.back; z.y = 0f; var rotation = z == Vector3.zero ? Quaternion.identity : Quaternion.LookRotation(z, Vector3.up); if (m_SelectCircle != null) { m_SelectCircle.transform.position = SelectObj.transform.position; m_SelectCircle.transform.rotation = rotation; } if (m_SelectCircleNPC != null) { m_SelectCircleNPC.transform.position = SelectObj.transform.position; m_SelectCircleNPC.transform.rotation = rotation; } } } //主角服务器位置测试选项 public void ShowMainPlayerServerPosition(float fX, float fZ) { if (false == GameManager.gameManager.ShowMainPlayerServerTrace) return; if (null != m_SelectCircle) { m_SelectCircle.SetActive(true); SetCirCleColor(1); var pos = new Vector3(fX, 0, fZ); pos.y = Singleton.GetInstance().MainPlayer.ObjTransform.position.y; m_SelectCircle.transform.position = pos; } } //public Vector2 SkillAttackPoint //{ // get { return _skillAttackPoint; } // set // { // _skillAttackPoint = value; // LogModule.WarningLog("Set Skill Attack: " + _skillAttackPoint); // } //} // //private Vector2 _skillAttackPoint; // //public void SetSkillTargetPoint(Vector2 point) //{ // LogModule.WarningLog("Set Skill Target Point: " + point); // SkillAttackPoint = point; //} // //public void AfterUseSkill() //{ // SkillAttackPoint = Vector2.zero; //} public void UpdateSkillCirclePos(Vector2 vec, bool isEnterRelex) { if (_skillCircleProjector != null) _skillCircleProjector.UpdatePos(vec, isEnterRelex); } public void ShowSkillCircleEffect(Tab_SkillEx skillEx, Vector2 vec) { if (skillEx != null) { if (_skillCircleProjector != null) { _skillCircleProjector.gameObject.SetActive(true); _skillCircleProjector.InitSkillInfo(skillEx, vec); } } else { HideSkillCircleEffect(); } } public void HideSkillCircleEffect() { if (_skillCircleProjector != null) _skillCircleProjector.gameObject.SetActive(false); } public bool Init() { //m_UIRoot = GameObject.Find("UI Root"); //if (null == m_UIRoot) //{ // LogModule.WarningLog("can not find uiroot in curscene"); //} //else //{ // if (null == m_UIRoot.GetComponent()) // { // m_UIRoot.AddComponent(); // } //} var dialogUI = GameObject.Find("UI Root/WorldUIRoot/DialogueRoot"); if (dialogUI != null) DialogTipUIRoot = dialogUI.GetComponent(); NameBoardRoot = GameObject.Find("UI Root/WorldUIRoot/NameBoardRoot"); if (DropBoardManager.Instacne == null) ResourceManager.InstantiateResource("Prefab/HeadInfo/DropItemBoardRoot"); //初始化特效 if (null == m_MovingCircle) { m_MovingCircle = ResourceManager.InstantiateResource("Prefab/Effect/MovingCircle"); if (null != m_MovingCircle) { m_MovingCircle.transform.position = Vector3.zero; m_MovingCircle.transform.rotation = Quaternion.Euler(Vector3.zero); m_MovingCircle.SetActive(false); m_MovingCircle.name = "MovingCircle"; Object.DontDestroyOnLoad(m_MovingCircle); } } if (null == m_SelectCircle) { m_SelectCircle = ResourceManager.InstantiateResource("Prefab/Effect/SelectCircle"); if (null != m_SelectCircle) { m_SelectCircle.transform.position = Vector3.zero; m_SelectCircle.transform.rotation = Quaternion.Euler(Vector3.zero); m_SelectCircle.SetActive(false); m_SelectCircle.name = "SelectCircle"; Object.DontDestroyOnLoad(m_SelectCircle); } } if (null == m_SelectCircleNPC) { m_SelectCircleNPC = ResourceManager.InstantiateResource("Prefab/Effect/SelectCircleNPC"); if (null != m_SelectCircleNPC) { m_SelectCircleNPC.transform.position = Vector3.zero; m_SelectCircleNPC.transform.rotation = Quaternion.Euler(Vector3.zero); m_SelectCircleNPC.SetActive(false); m_SelectCircleNPC.name = "m_SelectCircleNPC"; Object.DontDestroyOnLoad(m_SelectCircleNPC); } } GameObject skillCircleProjectObj = null; if (null == _skillCircleProjector) skillCircleProjectObj = ResourceManager.InstantiateResource("Prefab/Effect/SkillCircleEffect"); if (null == skillCircleProjectObj) { LogModule.ErrorLog("无法获得技能范围指示器!"); } else { _skillCircleProjector = skillCircleProjectObj.GetComponent(); skillCircleProjectObj.SetActive(false); } Teleport = GameObject.Find("Teleport"); if (Teleport != null) { //if (IsCopyScene()) //{ // m_Teleport.SetActive(false); //} } TeleportCopyScene = GameObject.Find("TeleportCopyScene"); if (TeleportCopyScene) { //if (IsCopyScene()) //{ // m_TeleportCopyScene.SetActive(false); //} } QingGongPointList = GameObject.FindGameObjectsWithTag("QingGongPoint"); // if (m_QingGongPoint != null) // { // if (IsCopyScene()) // { // m_QingGongPoint.SetActive(false); // } // } for (var i = 0; i < QingGongPointList.Length; ++i) if (IsCopyScene() && QingGongPointList[i] != null) QingGongPointList[i].SetActive(false); //声音资源 SceneAudioSources = GameObject.FindGameObjectsWithTag("SceneSoundEffect"); for (var i = 0; i < SceneAudioSources.Length; ++i) if (SceneAudioSources[i] != null && !PlayerPreferenceData.SystemSoundEffect) SceneAudioSources[i].SetActive(false); //初始化Terrain数据 //if (GameManager.gameManager != null) GameManager.gameManager.m_loadErrorNum = 0; //SetTerrainData(); ////初始化名字版池子 //if (null == m_NameBoardPool) //{ // m_NameBoardPool = new GameObjectPool("HeadInfo", 128); //} //if (null != m_NameBoardPool) //{ // m_NameBoardPool.ClearAllPool(); //} //if (MainCamera == null) // MainCamera = GameObject.Find("Main Camera"); return true; } /// /// 设置TerrainData 数据 /// // public void SetTerrainData() // { // if (GameManager.gameManager.RunningScene == // (int) GameDefine_Globe.SCENE_DEFINE.SCENE_LOGIN) // return; // // if (null != TerrainData) TerrainData = null; // // var sceneClass = TableManager.GetSceneClassByID(GameManager.gameManager.RunningScene, 0); // if (null != sceneClass) // { // //PC上Raw文件路径为Assets/MLDJ/Scene/TerrainRaw/+场景名称.raw // //iPhone上文件路径为Application.dataPath/TerrainRaw/+场景名称.raw // var streamingAssetPath = Utils.GetStreamingAssetPath(); // //if ("" == streamingAssetPath) // //{ // // return false; // //} // // var strTerrainRawFilePath = streamingAssetPath + "/TerrainRaw/" + sceneClass.ResName + ".raw"; // //#if UNITY_ANDROID && !UNITY_EDITOR // m_TerrainData = new TerrainManager(); // 可优化区 // //场景如果分32*32个块,那么顶点应该是33*33 // if (false == m_TerrainData.InitTerrianData(strTerrainRawFilePath, // sceneClass.TerrainHeightMapLength + 1, // sceneClass.TerrainHeightMapWidth + 1, // sceneClass.TerrainHeightMax, // sceneClass.Length + 1, // sceneClass.Width + 1)) // { // LogModule.DebugLog("init Scene TerrainData Failed"); // } //#else // // GameManager.gameManager.m_loadErrorNum++; // // if (GameManager.gameManager.m_loadErrorNum > GameManager.gameManager.m_MaxErrorNum) return; // // if (File.Exists(strTerrainRawFilePath)) // { // TerrainData = new TerrainManager(); // 可优化区 // //场景如果分32*32个块,那么顶点应该是33*33 // if (false == TerrainData.InitTerrianData(strTerrainRawFilePath, // sceneClass.TerrainHeightMapLength + 1, // sceneClass.TerrainHeightMapWidth + 1, // sceneClass.TerrainHeightMax, // sceneClass.Length + 1, // sceneClass.Width + 1)) // { // LogModule.DebugLog("init Scene TerrainData Failed"); // // //资源加载失败时 // SetTerrainData(); // } // } // else // { // //文件不存在或路径不对时,重新申请资源 // SetTerrainData(); // } //#endif // } // } public void Update() { UpdateSelectCircle(); //UpdateMovingCircle(); UpdateSceneTimeScale(); } public void RelaseActiveSceneData() { CurSceneServerID = GlobeVar.INVALID_ID; UIRoot = null; NameBoardRoot = null; //TerrainData = null; m_MovingCircle = null; m_SelectCircle = null; Teleport = null; TeleportCopyScene = null; QingGongPointList = null; SceneAudioSources = null; } public void SceneTimeScale(int nTimeScaleType) { if (nTimeScaleType == 0) { Time.timeScale = 0.2f; m_ChangeTime = 0.6f; m_SceneTimeScaleStart = Time.fixedTime; } else if (nTimeScaleType == 1) //todo 临时实验代码 { // Time.timeScale = 0.5f; // m_ChangeTime = 0.1f; // m_SceneTimeScaleStart = Time.fixedTime; } } private void UpdateSceneTimeScale() { if (m_ChangeTime > 0) if (Time.fixedTime - m_SceneTimeScaleStart >= m_ChangeTime) { m_SceneTimeScaleStart = -1; m_ChangeTime = -1; Time.timeScale = 1; } } public bool IsCopyScene() { return IsCopyScene(GameManager.gameManager.RunningScene); } public bool IsCopyScene(int sceneId) { var tabSceneClass = TableManager.GetSceneClassByID(sceneId, 0); return tabSceneClass != null && tabSceneClass.IsCopyScene(); } public bool IsWildeScene() { var tabSceneClass = TableManager.GetSceneClassByID(GameManager.gameManager.RunningScene, 0); if (tabSceneClass != null) if (tabSceneClass.Type == (int) GameDefine_Globe.SCENE_TYPE.SCENETYPE_WILDCITY) return true; return false; } public void SetSceneSoundEffect(bool bIsActive) { for (var i = 0; i < SceneAudioSources.Length; ++i) if (SceneAudioSources[i] != null) SceneAudioSources[i].SetActive(bIsActive); } public static bool GetTerrainPosition(ref Vector3 origin) { var result = false; if (GameManager.gameManager != null) { #if UNITY_EDITOR // 为Log输出备份的原始位置 var originBackup = origin; #endif var raySource = origin; raySource.y = raycastHeight; // 试图使用射线位置校正高度 RaycastHit raycastHit; if (Physics.Raycast(raySource, Vector3.down, out raycastHit, raycastHeight * 2f, terrainLayMask)) { origin.y = raycastHit.point.y; } else // if (GameManager.gameManager.SceneLogic != null && GameManager.gameManager.SceneLogic.allowSphereCast) { #if UNITY_EDITOR LogModule.WarningLog(string.Format("射线无法获得高度于位置{0},使用半径{1}球形射线修正高度。", originBackup, sphereCastRadius)); #endif // 注:SamplePosition 30f超过SphereCast 3f的20倍,因此使用SphereCast直接过滤。 if (Physics.SphereCast(raySource, sphereCastRadius, Vector3.down, out raycastHit, raycastHeight * 2f, terrainLayMask)) { origin.y = raycastHit.point.y; } else { #if UNITY_EDITOR //LogModule.WarningLog(string.Format("球体射线无法找到地形碰撞体于位置{0},使用主角高度修正。", originBackup)); #endif // 暂时使用MainPlayer来校正位置 var mainPlayer = ObjManager.Instance.MainPlayer; if (mainPlayer) origin.y = mainPlayer.Position.y; } } // 对高度修正后的位置实现采样 NavMeshHit navMeshHit; if (NavMesh.SamplePosition(origin, out navMeshHit, navSampleHeight, NavMesh.AllAreas)) { result = true; origin = navMeshHit.position; // 防止采样点是在边界上导致寻路机卡住 if (NavMesh.FindClosestEdge(origin, out navMeshHit, NavMesh.AllAreas) && (navMeshHit.position - origin).sqrMagnitude < edgeSnapDist.ToSquare()) origin = navMeshHit.position; } else { #if UNITY_EDITOR //LogModule.ErrorLog(string.Format("地图NavMesh采样失败于位置{0}", originBackup)); #endif } } return result; } /// /// 将服务器推送的2d寻路目标转化为客户端3d位置 /// /// 服务器位置 /// 客户端位置 public static Vector3 GetTerrainPosition(Vector3 origin) { GetTerrainPosition(ref origin); return origin; } /// /// 将射线转换为客户端3d位置 /// public static Vector3? GetTerrainPosition(Ray ray) { Vector3? result = null; RaycastHit hit; if (Physics.Raycast(ray, out hit, float.PositiveInfinity, terrainLayMask)) { NavMeshHit navMeshHit; if (NavMesh.SamplePosition(hit.point, out navMeshHit, navSampleHeight, NavMesh.AllAreas)) result = navMeshHit.position; } return result; } public void ShowFakeObj() { FakeObjRoot.SetActive(true); } public void HideFakeObj() { FakeObjRoot.SetActive(false); } public void ClearUiBoard() { if (m_MovingCircle != null) { Object.Destroy(m_MovingCircle); m_MovingCircle = null; } if (m_SelectCircle != null) { Object.Destroy(m_SelectCircle); m_SelectCircle = null; } if (m_SelectCircleNPC != null) { Object.Destroy(m_SelectCircleNPC); m_SelectCircleNPC = null; } if (_skillCircleProjector != null) { Object.Destroy(_skillCircleProjector.gameObject); _skillCircleProjector = null; } if (DropBoardManager.Instacne != null) DropBoardManager.Instacne.ClearDropName(); } } }