Files
plugin-library/Assets/11.PointCloudTools/Runtime/Script/PointSystem/ZoneSystemBase.cs

376 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using UnityEngine;
namespace Main
{
public interface IZoneSystem
{
string CurrentZoneType { get; set; }
string CurrentPointType { get; set; }
/// <summary>
/// 当进去区域的最后一个小点位的区域范围时,开启下一区域的第一个小点位 和 关闭上一区域的最后一个小点位
/// </summary>
public void OpenNextZonePoint(ZoneController zoneController);
void HideBigMeshColliderStayUnRegister();
void OpenDomain(string domainName);
/// <summary>
/// 绑定区域碰撞事件
/// </summary>
/// <param name="zoneId">区域名称</param>
/// <param name="onColliderEnter">进入事件</param>
/// <param name="onColliderStay">停留事件</param>
/// <param name="onColliderExit">退出事件</param>
void AddOnZoneColliderEvent(string zoneId, Action<Collider> onColliderEnter = null,
Action<Collider> onColliderStay = null, Action<Collider> onColliderExit = null);
/// <summary>
/// 绑定点位碰撞事件
/// </summary>
/// <param name="pointId">点位名称</param>
/// <param name="onColliderEnter">进入事件</param>
void AddOnPointColliderEvent(string pointId, Action<Collider> onColliderEnter = null);
}
public abstract class ZoneSystemBase : IZoneSystem
{
private ZoneController[] zoneControllers;
private List<PointController> pointControllers = new List<PointController>();
/// <summary>
/// mask遮罩大点位触发区域
/// </summary>
private MeshCollider[] _meshBigColliders;
/// <summary>
/// 当前在的区域范围
/// </summary>
public string CurrentZoneType { get; set; }
/// <summary>
/// 当前触发的点位
/// </summary>
public string CurrentPointType { get; set; }
/// <summary>
/// 初始化点位物体
/// </summary>
/// <returns></returns>
public abstract Task<GameObject> InitZonePoint();
/// <summary>
/// 初始化区域
/// </summary>
/// <returns></returns>
public abstract Task<GameObject> InitZoneMask();
/// <summary>
/// 初始化区域数据
/// </summary>
/// <returns></returns>
public abstract Task<PointGatherData> InitZoneData();
public ZoneSystemBase(Transform parent)
{
CreatZone(parent);
}
/// <summary>
/// 创建zone碰撞盒
/// </summary>
private async UniTask CreatZone(Transform parent)
{
//检测环境是否正常
if (!HasValidGameController())
{
// 抛出异常或返回空服务
Debug.LogError(
$"请检查相机环境 1、是否存在GameController物体 2、是否存在BoxCollider,3、GameController物体的tag是否为GameController");
}
//读取配置文件
var pointGatherData = await InitZoneData();
if (pointGatherData == null)
{
Debug.LogError("点位数据为空,请先初始化点位数据");
}
PointCloudService.RegisterService<IZoneData>(new ZoneGatherData(pointGatherData));
var zoneDatas = PointCloudService.GetService<IZoneData>().GetZoneDataAll();
zoneControllers = new ZoneController[zoneDatas.Length];
//加载遮罩数据
var zoneMask = await InitZoneMask();
if (zoneMask == null)
{
Debug.LogError("区域遮罩碰撞体为空,请先初始化区域遮罩碰撞体");
}
var zoneMaskTransform = GameObject.Instantiate(zoneMask, parent);
_meshBigColliders = zoneMaskTransform.transform.Find("AreaDetermination")
.GetComponentsInChildren<MeshCollider>();
//初始化点位物体
var zonePoint = await InitZonePoint();
if (zonePoint == null)
{
Debug.LogError("点位物体为空,请先初始化点位物体");
}
//生成区域
for (int i = 0; i < zoneDatas.Length; i++)
{
var zoneGo = new GameObject(zoneDatas[i].name, typeof(ZoneController));
zoneGo.Parent(parent);
// //ip漫游点位数据赋值
// this.GetSystem<IDigitalHuman>().AddPointData(new DigitalHumanPointData()
// {
// pointType = Enum.Parse<PointType>(zoneDatas[i].name),
// pointTransform = zoneColliderPoint.transform
// });
var zoneController = zoneGo.GetComponent<ZoneController>();
zoneControllers[i] = zoneController;
await zoneController.Init(zoneDatas[i]);
//生成点位
var pointDatas = zoneDatas[i].pointDatas;
foreach (var pointData in pointDatas)
{
var pointGo = GameObject.Instantiate(zonePoint, zoneGo.transform);
PointController pointController = pointGo.GetOrAddComponent<PointController>();
zoneController.pointControllerEntities.Add(pointController);
pointControllers.Add(pointController);
pointController.Init(zoneController, pointData);
}
}
for (int i = 0; i < zoneControllers.Length; i++)
{
var bigMeshCollider = _meshBigColliders[i];
zoneControllers[i].InitMeshCollider(bigMeshCollider);
bigMeshCollider.transform.parent.Find("Arrow").gameObject.SetActive(false);
}
}
/// <summary>
/// 当进去区域的最后一个小点位的区域范围时,开启下一区域的第一个小点位 和 关闭上一区域的最后一个小点位
/// </summary>
public void OpenNextZonePoint(ZoneController zoneController)
{
int currentIndex = 0;
for (int i = 0; i < zoneControllers.Length; i++)
{
if (zoneControllers[i] != zoneController)
{
//先关闭所有点位
zoneControllers[i].ActiveAllPointHideOrShow(false);
}
else
{
zoneControllers[i].ActiveAllPointHideOrShow(true, false);
currentIndex = i;
}
}
int nextIndex = currentIndex + 1;
if (nextIndex < zoneControllers.Length)
{
//开启下一区域的第一个小点位
zoneControllers[nextIndex]
.CurrentPointActiveHideOrShow(
zoneControllers[nextIndex].pointControllerEntities.First(), true);
}
int lastIndex = currentIndex - 1;
if (lastIndex >= 0)
{
//开启上一区域的最后一个小点位
zoneControllers[lastIndex]
.CurrentPointActiveHideOrShow(zoneControllers[lastIndex].pointControllerEntities.Last(),
true);
}
}
/// <summary>
/// 进入当前区域时,关闭当前区域时间,打开别的区域事件
/// </summary>
public void HideBigMeshColliderStayUnRegister()
{
foreach (var zoneController in zoneControllers)
{
zoneController._onBigMeshColliderStayUnRegister.UnRegister();
}
}
public void OpenDomain(string domainName)
{
// if (_entrance != null)
// {
// _entrance.OpenDomain(domainName, OpenDomainType.PointCloud);
InitializeHybridClREntrance(domainName);
// }
// else
// {
// Debug.LogError("UnityEvo:HybridClREntrance is null");
// }
}
/// <summary>
/// 绑定区域碰撞事件
/// </summary>
/// <param name="zoneId">区域名称</param>
/// <param name="onColliderEnter">进入事件</param>
/// <param name="onColliderStay">停留事件</param>
/// <param name="onColliderExit">退出事件</param>
public void AddOnZoneColliderEvent(string zoneId, Action<Collider> onColliderEnter = null,
Action<Collider> onColliderStay = null, Action<Collider> onColliderExit = null)
{
foreach (var zoneController in zoneControllers)
{
if (zoneController.name == zoneId)
{
if (onColliderEnter != null)
{
zoneController.OnColliderEnter += onColliderEnter;
}
if (onColliderStay != null)
{
zoneController.OnColliderStay += onColliderStay;
}
if (onColliderExit != null)
{
zoneController.OnColliderExit += onColliderExit;
}
break;
}
}
}
/// <summary>
/// 绑定点位碰撞事件
/// </summary>
/// <param name="pointId">点位名称</param>
/// <param name="onColliderEnter">进入事件</param>
public void AddOnPointColliderEvent(string pointId, Action<Collider> onColliderEnter = null)
{
foreach (var pointController in pointControllers)
{
if (pointController.name == pointId)
{
if (onColliderEnter != null)
{
pointController.OnColliderEnter += onColliderEnter;
}
break;
}
}
}
/// <summary>
/// 检测指定Camera下是否存在符合条件的GameController
/// </summary>
/// <returns>是否存在符合条件的物体</returns>
private bool HasValidGameController()
{
var targetCamera = Camera.main;
if (targetCamera == null) return false;
// 获取相机下所有子物体(包括 inactive 物体)
Transform[] allChildren = targetCamera.GetComponentsInChildren<Transform>(true);
foreach (Transform child in allChildren)
{
// 跳过相机自身
if (child == targetCamera.transform) continue;
GameObject obj = child.gameObject;
// 检查名称、标签和碰撞体
if (obj.name == "GameController" &&
obj.CompareTag("GameController") &&
obj.TryGetComponent<BoxCollider>(out _))
{
return true;
}
}
return false;
}
private void InitializeHybridClREntrance(string domainName)
{
GameObject entrance = GameObject.Find("LoadDll");
if (entrance == null)
{
Debug.LogError("未找到LoadDll物体");
return;
}
try
{
// 替换为实际程序集名称和类完整名
string assemblyName = "stary.hotfixupdate.main"; // 例如:"HybridCLR.Runtime"
string typeFullName = "Stary.Evo.HybridClREntrance"; // 例如:"HybridCLR.HybridClREntrance"
// 加载程序集并获取类型
Assembly assembly = Assembly.Load(assemblyName);
// 已加载的程序集延续之前的assembly变量
Type hybridType = assembly.GetType(typeFullName);
if (hybridType == null)
{
Debug.LogError("未找到HybridClREntrance类型");
return;
}
// 反射调用GameObject.GetComponent方法
MethodInfo getComponentMethod = typeof(GameObject).GetMethod("GetComponent", Type.EmptyTypes);
MethodInfo genericMethod = getComponentMethod?.MakeGenericMethod(hybridType);
var _entrance = genericMethod?.Invoke(entrance, null);
if (_entrance == null)
{
// 若组件不存在可反射调用AddComponent添加
MethodInfo addComponentMethod = typeof(GameObject).GetMethod("AddComponent", Type.EmptyTypes);
MethodInfo genericAddMethod = addComponentMethod.MakeGenericMethod(hybridType);
_entrance = genericAddMethod.Invoke(entrance, null);
}
// 步骤2获取实例类型并调用方法
Type componentType = _entrance.GetType();
MethodInfo targetMethod = componentType.GetMethod(
"OpenDomain", // 替换为实际方法名
new[] { typeof(string), typeof(string) } // 替换为方法参数类型
);
if (targetMethod == null)
{
Debug.LogError($"组件{componentType.Name}中未找到目标方法");
return;
}
targetMethod.Invoke(_entrance, new[] { domainName, "PointCloud" });
}
catch (Exception ex)
{
Debug.LogError($"反射操作失败: {ex.Message}");
}
}
}
}