/********************************************************************************
* 文件名: 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();
}
}
}