- LocalizationManager: 新增翻译表(SetFormatted/SetDuration/LocalizeOperateMsg) - LoginPanel: InputField placeholder本地化、字体颜色保持 - HistoryPanel: 用时数据本地化、placeholder本地化 - RecordDetailPanel: 操作详情消息本地化(LanguageChanged重建) - AppraiseWindowBase: 评价等级本地化、操作消息重建 - EditorAppraiser: 所有评估消息改用InjectOperateMsgLocalized - StudentOperateRecorder: 新增InjectOperateMsgLocalized方法 - LocalizationLanguageTestBar: 单例模式、ScreenSpaceOverlay筛选 - 字体切换时保留颜色和verticalOverflow
409 lines
13 KiB
C#
409 lines
13 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using DevelopEngine;
|
|
using XFramework;
|
|
using System;
|
|
using UnityEngine.EventSystems;
|
|
|
|
//场景物体控制器 用于引用存储、获取、物体外部控制、厂区分配、统计需同步物体的位置并发送等逻辑
|
|
public class GameObjectManager : MonoSingleton<GameObjectManager>
|
|
{
|
|
List<CarCtrl> Cars = new List<CarCtrl>();
|
|
List<AreaFlageCtrl> areaFlages = new List<AreaFlageCtrl>();//规划完成的一区九场
|
|
Dictionary<string, List<CarCtrl>> inAreaCarDic = new Dictionary<string, List<CarCtrl>>();//分配完所属区域的车辆
|
|
bool onLooked;//教员监视状态
|
|
float timer;
|
|
Dictionary<ManagerGOTypes, Dictionary<int,GameObject>> allGOs = new Dictionary<ManagerGOTypes, Dictionary<int,GameObject>>();//所有待管理的对象
|
|
CarCtrl currentSelectCar;//当前选中的车辆 用于后期控制
|
|
public CarCtrlType ctrlType = CarCtrlType.AI;
|
|
AdjustingCarIconData[] carIconMsgs;//待发送的车辆图标数据类
|
|
|
|
Surveyor rulerManager;
|
|
|
|
private void Update()
|
|
{
|
|
if (onLooked) //同步模式下 同步位置信息
|
|
{
|
|
GetCarsPosAndSend();
|
|
}
|
|
|
|
RayHitMoveCar();
|
|
|
|
rulerManager?.Update();
|
|
}
|
|
|
|
//获取点击事件 控制车辆移动
|
|
private void RayHitMoveCar()
|
|
{
|
|
if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject()) return; //射线检测时屏蔽UI部分
|
|
if (Cars.Count < 0) return; //无车辆时 不需要射线检测
|
|
if (Input.GetMouseButtonDown(0))
|
|
{
|
|
RaycastHit hit;//鼠标射线检测
|
|
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
|
if (Physics.Raycast(ray, out hit, 2000) && hit.collider.gameObject.layer == LayerMask.NameToLayer("Floor"))//只有点击到地面时才设置车辆位移
|
|
{
|
|
SetCarMovePoints(hit.point);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//梳理车辆位置信息 发送到服务端 每0.5f发送一次同步位置信息
|
|
private void GetCarsPosAndSend()
|
|
{
|
|
if (Cars.Count < 0) return;
|
|
timer += Time.unscaledTime;
|
|
if (timer < 0.5f) return;
|
|
timer = 0;
|
|
if (carIconMsgs == null || carIconMsgs.Length != Cars.Count)
|
|
{
|
|
carIconMsgs = new AdjustingCarIconData[Cars.Count];
|
|
}
|
|
for (int i = 0; i < Cars.Count; i++)
|
|
{
|
|
if (carIconMsgs[i] == null)
|
|
carIconMsgs[i] = new AdjustingCarIconData();
|
|
carIconMsgs[i].carName = Cars[i].transform.name;
|
|
Vector2 pos = Cars[i].iconBase_thisIcon.GetComponent<RectTransform>().anchoredPosition;
|
|
carIconMsgs[i].anchorPos = new VectorTwo(pos);
|
|
carIconMsgs[i].angle = ((CarIconInstanceCtrl)Cars[i].iconBase_thisIcon).dir.transform.localEulerAngles.z;
|
|
}
|
|
TCPManager.Instance.SendNetMsg<AdjustingCarIconData[]>(carIconMsgs, NetMsgName.Syn);
|
|
}
|
|
|
|
|
|
//改变选中装备的展开状态
|
|
internal void ChangeCarOpening()
|
|
{
|
|
//throw new NotImplementedException();
|
|
currentSelectCar?.ChangeOpening();
|
|
}
|
|
|
|
//修理所展开时 改变车辆控制方式为人员控制 注册展开事件 展开时分配所属分区
|
|
public void StartPersonCtrl()
|
|
{
|
|
ctrlType = CarCtrlType.Person;
|
|
for (int i = 0; i < Cars.Count; i++)
|
|
{
|
|
Cars[i].ChangeCtrlType(CarCtrlType.Person);
|
|
Cars[i].carOpenedEvent += CarOpened;
|
|
Cars[i].transform.GetOrAddComponent<Cam_InteractionObject>().Event_ParamClick += Event_ParamClick;
|
|
}
|
|
CameraCtrl.Instance.AddGOEventSystem();
|
|
CameraCtrl.Instance.rightButtonEvent += RightButtonEvent;
|
|
}
|
|
|
|
//右键取消当前选中车辆的选中状态
|
|
private void RightButtonEvent()
|
|
{
|
|
if (currentSelectCar != null)
|
|
{
|
|
currentSelectCar.carStateChangedEvent -= ShowCarState;//取消车辆状态监视
|
|
currentSelectCar.IsSelect = false;//关闭车辆选中状态
|
|
ShowCarState(CarState.none);//情况车辆状态显示UI
|
|
currentSelectCar = null;//清空选中车辆
|
|
}
|
|
}
|
|
|
|
//修理所展开科目时的 车辆选取事件
|
|
private void Event_ParamClick(GOEventSystem.GOPointerEventData data)
|
|
{
|
|
CarCtrl pointHitCar = data.pointerPress.GetComponentInParent<CarCtrl>();
|
|
if (pointHitCar == null) return;
|
|
if (pointHitCar.OtherUserCtrl) return;//协同模式下他人正在控制的物体无法获取
|
|
if (currentSelectCar != pointHitCar)//选了一个新的车辆
|
|
{
|
|
if (currentSelectCar != null)//当前已经选了一个车辆
|
|
{
|
|
currentSelectCar.IsSelect = false;
|
|
currentSelectCar.carStateChangedEvent -= ShowCarState;//取消对上一个选中车辆的状态监视事件
|
|
}
|
|
currentSelectCar = pointHitCar;
|
|
currentSelectCar.IsSelect = true;
|
|
currentSelectCar.carStateChangedEvent += ShowCarState;
|
|
ShowCarState(currentSelectCar.CarState);//选中车辆时显示车辆状态
|
|
Debug.Log(currentSelectCar.gameObject.name);
|
|
}
|
|
}
|
|
|
|
//当前选中车辆的状态发生变化
|
|
private void ShowCarState(CarState carState)
|
|
{
|
|
GameMain.Instance.UIManager.ChangePanel("CarState",carState);
|
|
}
|
|
|
|
//车辆展开完毕时执行 为车辆分配所属区域
|
|
private void CarOpened(CarCtrl car)
|
|
{
|
|
DistributionAreaForOneCar(car);
|
|
}
|
|
|
|
//为当前选择车辆设置移动路点
|
|
private void SetCarMovePoints(Vector3 vector3)
|
|
{
|
|
if (currentSelectCar != null)//选择车辆后点击地面时 移动车辆
|
|
{
|
|
currentSelectCar.SetWayPoints(new List<Vector3>() { vector3 });
|
|
}
|
|
}
|
|
|
|
//获取首车Trans
|
|
public Transform GetFirstCar()
|
|
{
|
|
for (int i = 0; i < Cars.Count; i++)
|
|
{
|
|
if (Cars[i].carType == CarPosType.firstCar)
|
|
return Cars[i].transform;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 教员开始监视或取消监视时执行
|
|
/// </summary>
|
|
/// <param name="isLooked"></param>
|
|
public void SetAdjustingState(bool isLooked)
|
|
{
|
|
this.onLooked = isLooked;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 注入待管理的对象
|
|
/// </summary>
|
|
/// <param name="type">待管理对象的类型</param>
|
|
/// <param name="t">带管理的对象</param>
|
|
public void InjeectGO(ManagerGOTypes type, GameObject t,int id)
|
|
{
|
|
if (!allGOs.ContainsKey(type))
|
|
allGOs.Add(type, new Dictionary<int,GameObject>());
|
|
allGOs[type][id] = t;
|
|
}
|
|
|
|
///// <summary>
|
|
///// 获取某类型的所有对象
|
|
///// </summary>
|
|
///// <param name="type">对象类型</param>
|
|
//public GameObject[] GetGOs(ManagerGOTypes type)
|
|
//{
|
|
// if (allGOs.ContainsKey(type))
|
|
// return allGOs[type].ToArray();
|
|
// return null;
|
|
//}
|
|
|
|
|
|
/// <summary>
|
|
/// 删除突发事件检测器
|
|
/// </summary>
|
|
public void DestoryTuFaGO(int id)
|
|
{
|
|
if (allGOs[ManagerGOTypes.tufa].ContainsKey(id))
|
|
{
|
|
Destroy(allGOs[ManagerGOTypes.tufa][id].gameObject);
|
|
allGOs[ManagerGOTypes.tufa].Remove(id);
|
|
}
|
|
else
|
|
{
|
|
Debug.Log($"不存在id为{id}的触发器,无需删除!");
|
|
}
|
|
}
|
|
|
|
|
|
//存储新建车辆 便于后续调用 按照排列顺序添加
|
|
public void SetNewCar(CarCtrl carCtrl)
|
|
{
|
|
if (Cars.Count > 0)//设置前一辆车为后车跟随对象
|
|
{
|
|
carCtrl.SetFollowTarget(Cars[Cars.Count - 1].transform);
|
|
}
|
|
Cars.Add(carCtrl);
|
|
}
|
|
|
|
//重新为所有车辆规划所属厂区
|
|
public void DistributionAreaForCars()
|
|
{
|
|
for (int i = 0; i < Cars.Count; i++)
|
|
{
|
|
if (Cars[i].CarState == CarState.opened || Cars[i].CarState == CarState.openingAnim)//完成展开的/展开过程中的车辆规划厂区 未展开的不进行规划
|
|
{
|
|
DistributionAreaForOneCar(Cars[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//按照最近距离原则 为车辆分配所属厂区
|
|
private void DistributionAreaForOneCar(CarCtrl car)
|
|
{
|
|
string areaName = GetNearestDistanceArea(car.transform.position);
|
|
if (!inAreaCarDic.ContainsKey(areaName))
|
|
inAreaCarDic.Add(areaName, new List<CarCtrl>());
|
|
inAreaCarDic[areaName].Add(car);
|
|
car.SetArea(areaName);
|
|
}
|
|
|
|
//获取与车辆最近的厂区名称
|
|
private string GetNearestDistanceArea(Vector3 carPos)
|
|
{
|
|
float nearDistance = float.MaxValue;
|
|
string nearFlageName = "";
|
|
for (int i = 0; i < areaFlages.Count; i++)
|
|
{
|
|
float currentDis = Vector3.Distance(carPos, areaFlages[i].transform.position);
|
|
if (currentDis < nearDistance)
|
|
{
|
|
nearDistance = currentDis;
|
|
nearFlageName = areaFlages[i].AreaName;
|
|
}
|
|
}
|
|
return nearFlageName;
|
|
}
|
|
|
|
//记录完成位置规划的厂区
|
|
public void AddPlannedArea(AreaFlageCtrl area)
|
|
{
|
|
areaFlages.Add(area);
|
|
inAreaCarDic.Add(area.AreaName, new List<CarCtrl>());
|
|
|
|
if (StudentStateManager.Instance.LearnState == LearnState.learning)//训练模式提示厂区规划距离是否合适
|
|
{
|
|
string checkResult = EditorAppraiser.CheckAreaDistance(areaFlages);//先检查厂区之间的距离
|
|
if (!string.IsNullOrEmpty(checkResult))//厂区之间距离不符合要求
|
|
{
|
|
GameMain.Instance.UIManager.ShowPromptText(checkResult, Color.blue);
|
|
}
|
|
else if(area.AreaName== AreaNameEnum.洗消场.ToString())//厂区间距符合要求 在继续检查是否是洗消场
|
|
{
|
|
checkResult = EditorAppraiser.CheckAreaToWaterDistance(area.transform);//若是洗消场则继续检查距离水源的间距
|
|
if (!string.IsNullOrEmpty(checkResult))//洗消场与水源距离不符合要求
|
|
{
|
|
GameMain.Instance.UIManager.ShowPromptText(checkResult, Color.blue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//重新规划时移除
|
|
public void RemoveArea(AreaFlageCtrl area)
|
|
{
|
|
if (areaFlages.Contains(area))
|
|
{
|
|
areaFlages.Remove(area);
|
|
inAreaCarDic.Remove(area.AreaName);
|
|
}
|
|
}
|
|
|
|
//获取当前所有完成规划的厂区
|
|
public List<AreaFlageCtrl> GetAllAreas()
|
|
{
|
|
return areaFlages;
|
|
}
|
|
|
|
//改变当前棋子是否能够 捡起
|
|
public void ChangeAreaFlagePick(bool can)
|
|
{
|
|
Debug.Log($"当前旗子交互状态:{can}");
|
|
for (int i = 0; i < areaFlages.Count; i++)
|
|
{
|
|
areaFlages[i].ChangePicked(can);
|
|
}
|
|
}
|
|
|
|
//获取当前所有厂区的车辆Trans规划汇总 若无车辆时存入区域标志Trans
|
|
public Dictionary<string, List<Transform>> GetAreaAndCars()
|
|
{
|
|
Dictionary<string, List<Transform>> areaAndTransDic = new Dictionary<string, List<Transform>>();
|
|
foreach (var item in inAreaCarDic)
|
|
{
|
|
List<Transform> inAreaTrans = new List<Transform>();
|
|
for (int i = 0; i < item.Value.Count; i++)
|
|
{
|
|
inAreaTrans.Add(item.Value[i].transform);
|
|
}
|
|
if (inAreaTrans.Count == 0)//未在厂区内部规划车辆
|
|
{
|
|
inAreaTrans.Add(ArrayHelper.Find(areaFlages, (P) => P.AreaName == item.Key).transform);//将厂区Trans 加入 用于计算距离
|
|
}
|
|
areaAndTransDic.Add(item.Key, inAreaTrans);
|
|
}
|
|
return areaAndTransDic;
|
|
}
|
|
|
|
//车队开始移动
|
|
public void StartAIMove()
|
|
{
|
|
for (int i = 0; i < Cars.Count; i++)
|
|
{
|
|
Cars[i].StartMove();
|
|
}
|
|
}
|
|
|
|
//车队结束移动
|
|
public void StopMove()
|
|
{
|
|
for (int i = 0; i < Cars.Count; i++)
|
|
{
|
|
Cars[i].StopMove();
|
|
}
|
|
}
|
|
|
|
//设置行军路径 车队首个元素为首车
|
|
public void SetWayPoints(List<Vector3> points)
|
|
{
|
|
Cars[0].SetWayPoints(points);
|
|
}
|
|
|
|
//获取所有的车辆
|
|
public List<CarCtrl> GetCarList()
|
|
{
|
|
return Cars;
|
|
}
|
|
|
|
///// <summary>
|
|
///// 硬件控制当前选中的车辆
|
|
///// </summary>
|
|
//public void CtrlCarMove(float hor,float ver,float handBreak)
|
|
//{
|
|
// currentSelectCar?.CarMove(hor, ver, handBreak);
|
|
//}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 改变测量状态
|
|
/// </summary>
|
|
/// <param name="isOn">true 开始测量模式 false 关闭测量模式</param>
|
|
public void ChangeCLState(bool isOn)
|
|
{
|
|
if (isOn)//开时测量 创建测量员
|
|
{
|
|
rulerManager = new Surveyor(Resources.Load<GameObject>(ResourcesManager.GetPath("Ruler")));
|
|
}
|
|
else//结束测量 销毁测量员
|
|
{
|
|
rulerManager?.StopCL();
|
|
rulerManager = null;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 待管理的物体类型
|
|
/// </summary>
|
|
public enum ManagerGOTypes
|
|
{
|
|
//行军车辆
|
|
car,
|
|
|
|
//修理厂区域标志
|
|
areaFlag,
|
|
|
|
//突发事件触发器
|
|
tufa,
|
|
|
|
//VR模式下能看到的提示文字
|
|
vr3DText,
|
|
} |