【m】11.PointCloudTools 上传

This commit is contained in:
2025-09-02 10:42:11 +08:00
parent 421b516485
commit 66443003d1
31 changed files with 1578 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 858218743db24324ea70f5aabd5a59e1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 28b0336be33262a499bd2d0271e6ce4d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 07b86d86f93839748931b2c738d8392e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 534adf1a70225b147b60b06e492b6ef3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
{
"name": "PointCloud.Runtime",
"rootNamespace": "",
"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:f3fa071c399c4383a9ff8115e53dfefc",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9255f5abe57e6154b9d700de650dced1
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Main;
using UnityEngine;
public static class PointCloudService
{
private static readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
static PointCloudService()
{
Services.Clear();
}
public static void RegisterService<T>(T service)
{
var type = typeof(T);
if (Services.ContainsKey(type))
{
Services[type] = service;
}
else
{
Services.Add(type, service);
}
}
public static T GetService<T>()
{
var type = typeof(T);
if (Services.TryGetValue(type, out var service))
{
return (T)service;
}
else
{
// 抛出异常或返回空服务
throw new Exception($"Service of type 【{type}】 not found, please check if the service is registered.");
}
}
public static void UnregisterService<T>()
{
var type = typeof(T);
if (Services.ContainsKey(type))
{
Services.Remove(type);
}
}
public static void ClearServices()
{
Services.Clear();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f427d12273ddf14e8e82d29eabbec83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 18def5e1e37d03a438b2e1240ff6fb78
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 08e4dd259b2cfef419fa885222c533b1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Main;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;
[CreateAssetMenu(fileName = "PointGatherData", menuName = "Evo/Create PointGatherData")]
public class PointGatherData : SerializedScriptableObject
{
/// <summary>
/// 碰撞盒是否渲染
/// </summary>
public bool isGizmo = false;
#if UNITY_EDITOR
[Button("一键生成坐标数据")]
public void CreatPosData()
{
ZoneController[] zoneControllers = FindObjectsOfType<ZoneController>(true);
PointController[] pointControllers = FindObjectsOfType<PointController>(true);
for (int i = 0; i < ZoneDatas.Count; i++)
{
ZoneData zoneData = ZoneDatas[i];
foreach (var zoneController in zoneControllers)
{
if (zoneController.name == zoneData.name)
{
zoneData.transformData.position = zoneController.transform.localPosition;
zoneData.transformData.rotation = zoneController.transform.localEulerAngles;
zoneData.transformData.scale = zoneController.transform.localScale;
}
}
for (int j = 0; j < zoneData.pointDatas.Count; j++)
{
PointData pointData = zoneData.pointDatas[j];
foreach (var pointController in pointControllers)
{
if (pointController.name == pointData.name)
{
pointData.colliderData.position = pointController.transform.localPosition;
pointData.colliderData.rotation = pointController.transform.localEulerAngles;
pointData.colliderData.scale = pointController.transform.localScale;
var collider = pointController.transform.Find("collisionbox");
pointData.colliderData.colPosition = collider.localPosition;
pointData.colliderData.colRotation = collider.localEulerAngles;
pointData.colliderData.colScale = collider.localScale;
}
}
}
}
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
#endif
public List<ZoneData> ZoneDatas;
}
/// <summary>
/// 区域数据
/// </summary>
[Serializable]
public class ZoneData
{
public string id;
public string name;
[BoxGroup("坐标数据"), HideLabel][ReadOnly] public TransformData transformData;
//[HideLabel] public ColliderData colliderData;
public List<PointData> pointDatas;
public ZoneData()
{
transformData = new TransformData();
pointDatas = new List<PointData>();
}
}
/// <summary>
/// 点位数据
/// </summary>
[Serializable]
public class PointData
{
public int order;
public string id;
public bool isTigger = true;
public string name;
[HideLabel][ReadOnly] public ColliderData colliderData;
}
/// <summary>
/// 点位数据
/// </summary>
[Serializable]
public struct TransformData
{
public Vector3 position;
public Vector3 rotation;
public Vector3 scale;
}
/// <summary>
/// 点位数据
/// </summary>
[Serializable]
public struct ColliderData
{
[BoxGroup("碰撞点坐标数据"), HideLabel] public Vector3 position;
[BoxGroup("碰撞点坐标数据"), HideLabel] public Vector3 rotation;
[BoxGroup("碰撞点坐标数据"), HideLabel] public Vector3 scale;
[BoxGroup("包围盒数据"), HideLabel] public Vector3 colPosition;
[BoxGroup("包围盒数据"), HideLabel] public Vector3 colRotation;
[BoxGroup("包围盒数据"), HideLabel] public Vector3 colScale;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 79b808b96820ad546951a6859e2a99be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 01775802bfc184743916af27066a85dd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,131 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BoxColliderGizmo : MonoBehaviour {
void Start() {
}
// Update is called once per frame
void OnRenderObject() {
var colliders = gameObject.GetComponents<BoxCollider >();
if (colliders == null) {
return;
}
CreateLineMaterial();
lineMaterial.SetPass(0);
GL.PushMatrix();
GL.MultMatrix(transform.localToWorldMatrix);
for (int i = 0; i < colliders.Length; i++) {
var col = colliders[i];
var c = col.center;
var size = col.size;
float rx = size.x / 2f;
float ry = size.y / 2f;
float rz = size.z / 2f;
Vector3 p0, p1, p2, p3;
Vector3 p4, p5, p6, p7;
p0 = c + new Vector3(-rx,-ry,rz);
p1 = c + new Vector3(rx, -ry, rz);
p2 = c + new Vector3(rx, -ry, -rz);
p3 = c + new Vector3(-rx, -ry, -rz);
p4 = c + new Vector3(-rx, ry, rz);
p5 = c + new Vector3(rx, ry, rz);
p6 = c + new Vector3(rx, ry, -rz);
p7 = c + new Vector3(-rx, ry, -rz);
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p0);
GL.Vertex(p1);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p1);
GL.Vertex(p2);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p2);
GL.Vertex(p3);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p0);
GL.Vertex(p3);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p4);
GL.Vertex(p5);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p5);
GL.Vertex(p6);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p6);
GL.Vertex(p7);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p4);
GL.Vertex(p7);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p0);
GL.Vertex(p4);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p1);
GL.Vertex(p5);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p2);
GL.Vertex(p6);
GL.End();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(p3);
GL.Vertex(p7);
GL.End();
}
GL.PopMatrix();
}
static Material lineMaterial;
static void CreateLineMaterial() {
if (!lineMaterial) {
// Unity has a built-in shader that is useful for drawing
// simple colored things.
Shader shader = Shader.Find("Hidden/Internal-Colored");
lineMaterial = new Material(shader);
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
lineMaterial.SetInt("_ZWrite", 0);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67b37331afa91f6418b142c26b0ba6fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,108 @@
using UnityEditor;
using UnityEngine;
[RequireComponent(typeof(CapsuleCollider))]
public class CapsuleColliderGizmo : MonoBehaviour
{
[Tooltip("Gizmo显示颜色")] public Color gizmoColor = new Color(0, 1, 0, 0.3f);
[Tooltip("是否始终显示Gizmo")] public bool alwaysShow = true;
private CapsuleCollider capsuleCollider;
private void Awake()
{
capsuleCollider = GetComponent<CapsuleCollider>();
}
private void OnDrawGizmos()
{
# if UNITY_EDITOR
if (!alwaysShow && !Selection.Contains(gameObject)) return;
#endif
DrawCapsuleGizmo();
}
private void OnDrawGizmosSelected()
{
if (alwaysShow) return;
DrawCapsuleGizmo();
}
private void DrawCapsuleGizmo()
{
if (capsuleCollider == null)
{
capsuleCollider = GetComponent<CapsuleCollider>();
if (capsuleCollider == null) return;
}
Gizmos.color = gizmoColor;
// 获取胶囊体的参数
Vector3 center = transform.TransformPoint(capsuleCollider.center);
float radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.x, transform.lossyScale.z);
float height = capsuleCollider.height * transform.lossyScale.y;
int direction = capsuleCollider.direction;
// 计算胶囊体的两个半球中心
Vector3 halfHeight = Vector3.zero;
switch (direction)
{
case 0: // X轴
halfHeight = Vector3.right * (height / 2 - radius);
radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.y, transform.lossyScale.z);
break;
case 1: // Y轴
halfHeight = Vector3.up * (height / 2 - radius);
radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.x, transform.lossyScale.z);
break;
case 2: // Z轴
halfHeight = Vector3.forward * (height / 2 - radius);
radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.x, transform.lossyScale.y);
break;
}
Vector3 topCenter = center + halfHeight;
Vector3 bottomCenter = center - halfHeight;
// 绘制胶囊体的圆柱部分
if (height > radius * 2)
{
DrawCylinder(topCenter, bottomCenter, radius, 16);
}
// 绘制上下两个半球
Gizmos.DrawSphere(topCenter, radius);
Gizmos.DrawSphere(bottomCenter, radius);
}
// 添加自定义圆柱绘制方法
private void DrawCylinder(Vector3 topCenter, Vector3 bottomCenter, float radius, int segments)
{
Vector3 up = (topCenter - bottomCenter).normalized;
Vector3 right = Vector3.Cross(up, Vector3.forward).normalized;
if (right.sqrMagnitude < 0.01f)
right = Vector3.Cross(up, Vector3.right).normalized;
Vector3 forward = Vector3.Cross(up, right).normalized;
for (int i = 0; i < segments; i++)
{
float angle = (i / (float)segments) * Mathf.PI * 2;
float nextAngle = ((i + 1) / (float)segments) * Mathf.PI * 2;
Vector3 topPoint = topCenter + (Mathf.Cos(angle) * right + Mathf.Sin(angle) * forward) * radius;
Vector3 topNextPoint = topCenter + (Mathf.Cos(nextAngle) * right + Mathf.Sin(nextAngle) * forward) * radius;
Vector3 bottomPoint = bottomCenter + (Mathf.Cos(angle) * right + Mathf.Sin(angle) * forward) * radius;
Vector3 bottomNextPoint =
bottomCenter + (Mathf.Cos(nextAngle) * right + Mathf.Sin(nextAngle) * forward) * radius;
// 绘制侧面竖线
Gizmos.DrawLine(topPoint, bottomPoint);
// 绘制顶部环线
Gizmos.DrawLine(topPoint, topNextPoint);
// 绘制底部环线
Gizmos.DrawLine(bottomPoint, bottomNextPoint);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8094e78c655752e4b8ed71f3f146a258
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(MeshCollider))]
public class MeshColliderGizmo : MonoBehaviour
{
[Tooltip("Gizmo显示颜色")]
public Color lineColor = new Color(0, 1, 1, 0.8f);
[Tooltip("线框宽度")]
public float lineWidth = 1.0f;
[Tooltip("是否在运行时显示")]
public bool showInPlayMode = true;
[Tooltip("是否只显示边缘")]
public bool showEdgesOnly = true;
private MeshCollider _meshCollider;
private Mesh _mesh;
private List<Vector3> _vertices = new List<Vector3>();
private List<int> _triangles = new List<int>();
private List<Vector3> _linePoints = new List<Vector3>();
private Material _glMaterial;
private Matrix4x4 _localToWorldMatrix;
private void Awake()
{
_meshCollider = GetComponent<MeshCollider>();
InitializeMeshData();
InitializeGLMaterial();
}
private void InitializeMeshData()
{
// 尝试获取网格数据
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter != null && meshFilter.sharedMesh != null)
{
_mesh = meshFilter.sharedMesh;
}
else if (_meshCollider.sharedMesh != null)
{
_mesh = _meshCollider.sharedMesh;
}
if (_mesh != null)
{
_vertices.Clear();
_triangles.Clear();
_mesh.GetVertices(_vertices);
_mesh.GetTriangles(_triangles, 0);
GenerateLinePoints();
}
else
{
Debug.LogWarning("未找到有效的Mesh资源", this);
}
}
private void InitializeGLMaterial()
{
// 创建用于GL绘制的材质
_glMaterial = new Material(Shader.Find("Hidden/Internal-Colored"));
_glMaterial.hideFlags = HideFlags.HideAndDontSave;
_glMaterial.SetInt("ZWrite", 0);
_glMaterial.SetInt("ZTest", (int)UnityEngine.Rendering.CompareFunction.Always);
}
private void GenerateLinePoints()
{
if (showEdgesOnly)
{
// 只显示边缘线(去重处理)
HashSet<long> edgeSet = new HashSet<long>();
_linePoints.Clear();
for (int i = 0; i < _triangles.Count; i += 3)
{
AddEdge(_triangles[i], _triangles[i + 1], edgeSet);
AddEdge(_triangles[i + 1], _triangles[i + 2], edgeSet);
AddEdge(_triangles[i + 2], _triangles[i], edgeSet);
}
}
else
{
// 显示所有三角形线
_linePoints.Clear();
for (int i = 0; i < _triangles.Count; i += 3)
{
_linePoints.Add(_vertices[_triangles[i]]);
_linePoints.Add(_vertices[_triangles[i + 1]]);
_linePoints.Add(_vertices[_triangles[i + 1]]);
_linePoints.Add(_vertices[_triangles[i + 2]]);
_linePoints.Add(_vertices[_triangles[i + 2]]);
_linePoints.Add(_vertices[_triangles[i]]);
}
}
}
private void AddEdge(int v1, int v2, HashSet<long> edgeSet)
{
// 创建唯一的边ID避免重复
long edgeId = (long)Mathf.Min(v1, v2) << 32 | Mathf.Max(v1, v2);
if (edgeSet.Contains(edgeId)) return;
edgeSet.Add(edgeId);
_linePoints.Add(_vertices[v1]);
_linePoints.Add(_vertices[v2]);
}
private void Update()
{
_localToWorldMatrix = transform.localToWorldMatrix;
}
private void OnRenderObject()
{
if (!showInPlayMode || _mesh == null || _linePoints.Count == 0 || _glMaterial == null)
return;
// 设置材质和颜色
_glMaterial.SetPass(0);
GL.PushMatrix();
GL.MultMatrix(_localToWorldMatrix);
GL.Color(lineColor);
// 设置线宽
GL.Begin(GL.LINES);
for (int i = 0; i < _linePoints.Count; i++)
{
GL.Vertex(_linePoints[i]);
}
GL.End();
GL.PopMatrix();
}
// 编辑器下的Gizmo预览
#if UNITY_EDITOR
private void OnDrawGizmos()
{
if (!Application.isPlaying && _mesh != null)
{
Gizmos.color = lineColor;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireMesh(_mesh);
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1be297c9ec995924f872cde2f236e42a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphereColliderGizmo : MonoBehaviour {
void Start() {
}
// Update is called once per frame
void OnRenderObject() {
// 添加SphereCollider处理
var sphereColliders = gameObject.GetComponents<SphereCollider>();
if (sphereColliders != null) {
CreateLineMaterial();
lineMaterial.SetPass(0);
GL.PushMatrix();
GL.MultMatrix(transform.localToWorldMatrix);
foreach (var col in sphereColliders) {
float radius = col.radius;
Vector3 scale = transform.lossyScale;
// 计算最大缩放值
float maxScale = Mathf.Max(scale.x, scale.y, scale.z);
float scaledRadius = radius * maxScale;
Vector3 center = col.center;
// 绘制三个方向的圆环
DrawCircle(center, Vector3.up, Vector3.forward, scaledRadius);
DrawCircle(center, Vector3.forward, Vector3.up, scaledRadius);
DrawCircle(center, Vector3.right, Vector3.up, scaledRadius);
}
GL.PopMatrix();
}
// 原来的BoxCollider代码保持不变...
var colliders = gameObject.GetComponents<BoxCollider>();
// ... 后续BoxCollider的绘制代码保持不变 ...
}
// 新增辅助方法绘制圆形
void DrawCircle(Vector3 center, Vector3 normal, Vector3 axis, float radius) {
int segments = 32;
float angle = 0f;
GL.Begin(GL.LINE_STRIP);
GL.Color(Color.red);
for (int i = 0; i <= segments; i++) {
Vector3 point = center;
point += (axis * Mathf.Cos(angle) + Vector3.Cross(normal, axis) * Mathf.Sin(angle)) * radius;
GL.Vertex(point);
angle += Mathf.PI * 2f / segments;
}
GL.End();
}
static Material lineMaterial;
static void CreateLineMaterial() {
if (!lineMaterial) {
// Unity has a built-in shader that is useful for drawing
// simple colored things.
Shader shader = Shader.Find("Hidden/Internal-Colored");
lineMaterial = new Material(shader);
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
lineMaterial.SetInt("_ZWrite", 0);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4b3d66befec6a284da8001399bdb0d8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Main;
using Stary.Evo;
using TMPro;
using UnityEngine;
namespace Main
{
public class PointController : MonoBehaviour
{
public string pointType;
public bool isTigger;
public ZoneController ZoneController;
private MeshCollider collider;
private IUnRegister _onTriggerEnterUnRegister;
public Action<Collider> OnColliderEnter;
public async void Init(ZoneController ZoneController, PointData pointData)
{
this.gameObject.SetActive(false);
this.ZoneController = ZoneController;
var titleMesh = this.transform.Find("Title").GetComponent<TextMeshPro>();
titleMesh.text = pointData.name;
var numMesh = titleMesh.transform.Find("Num").GetComponent<TextMeshPro>();
numMesh.text = ConvertToCircledNumber(pointData.order);
name = pointData.id;
isTigger = pointData.isTigger;
pointType = pointData.id;
//根据数据设置zone 碰撞盒
transform.localPosition = pointData.colliderData.position;
transform.localRotation = Quaternion.Euler(pointData.colliderData.rotation);
transform.localScale = pointData.colliderData.scale;
collider = transform.Find("collisionbox").GetComponent<MeshCollider>();
collider.transform.localPosition = pointData.colliderData.colPosition;
collider.transform.localRotation = Quaternion.Euler(pointData.colliderData.colRotation);
collider.transform.localScale = pointData.colliderData.colScale;
if (PointCloudService.GetService<IZoneData>().IsGizmo())
{
collider.GetOrAddComponent<MeshColliderGizmo>();
}
_onTriggerEnterUnRegister = collider.OnTriggerEnterEvent(OnPointTriggerEnterEvent);
}
public void OnPointTriggerEnterEvent(Collider collider)
{
if (!isTigger)
return;
if (PointCloudService.GetService<IZoneSystem>().CurrentPointType == pointType)
return;
if (collider.gameObject.CompareTag("GameController"))
{
if (ZoneController != null)
{
//隐藏当前点,显示其余点
ZoneController.CurrentPointActiveHideOrShow(this, false);
}
else
{
this.gameObject.SetActive(false);
}
PointCloudService.GetService<IZoneSystem>().OpenDomain(this.name);
OnColliderEnter?.Invoke(collider);
PointCloudService.GetService<IZoneSystem>().CurrentPointType = pointType;
Debug.Log($"【{name}】OnPointTriggerEnterEvent");
}
}
private static string ConvertToCircledNumber(int number)
{
// 检查数字是否在1-20范围内
if (number < 1 || number > 20)
{
return number.ToString(); // 超出范围则返回原数字
}
// Unicode中①对应的编码是0x2460依次递增
char circledChar = (char)(0x2460 + number - 1);
return circledChar.ToString();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1d999e82fdea4ce287a59f805605e760
timeCreated: 1744884916

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using UnityEngine;
namespace Main
{
public class ZoneController : MonoBehaviour
{
public string pointType;
public List<PointController> pointControllerEntities;
/// <summary>
/// 大区域网格碰撞
/// </summary>
private MeshCollider bigMeshCollider;
//大区域范围进入事件
public IUnRegister _onBigMeshColliderStayUnRegister;
public IUnRegister _onBigMeshColliderExitUnRegister;
public IUnRegister _onBigMeshColliderEnterUnRegister;
public Action<Collider> OnColliderStay;
public Action<Collider> OnColliderExit;
public Action<Collider> OnColliderEnter;
public async UniTask Init(ZoneData zoneData)
{
name = zoneData.name;
pointType = name;
//根据数据设置zone 碰撞盒
transform.localPosition = zoneData.transformData.position;
transform.localRotation = Quaternion.Euler(zoneData.transformData.rotation);
transform.localScale = zoneData.transformData.scale;
pointControllerEntities = new List<PointController>(zoneData.pointDatas.Count);
await UniTask.CompletedTask;
}
public void InitMeshCollider(MeshCollider bigMeshCollider)
{
this.bigMeshCollider = bigMeshCollider;
_onBigMeshColliderStayUnRegister = bigMeshCollider.OnTriggerStayEvent(OnBigMeshColliderStayEvent);
_onBigMeshColliderExitUnRegister = bigMeshCollider.OnTriggerExitEvent(OnBigMeshColliderExitEvent);
_onBigMeshColliderEnterUnRegister = bigMeshCollider.OnTriggerEnterEvent(OnBigMeshColliderEnterEvent);
}
private void OnBigMeshColliderStayEvent(Collider collider)
{
PointCloudService.GetService<IZoneSystem>().HideBigMeshColliderStayUnRegister();
OnBigMeshColliderEnterEvent(collider);
OnColliderStay?.Invoke(collider);
}
private void OnBigMeshColliderEnterEvent(Collider collider)
{
if (PointCloudService.GetService<IZoneSystem>().CurrentZoneType == pointType)
return;
if (collider.gameObject.CompareTag("GameController"))
{
Debug.Log($"collider:【{collider.name}】 point:【{name}】 OnBigMeshColliderEnterEvent");
PointCloudService.GetService<IZoneSystem>().OpenNextZonePoint(this);
// ActiveAllPointHideOrShow(true);
bigMeshCollider.transform.parent.Find("Arrow").gameObject.SetActive(true);
OnColliderEnter?.Invoke(collider);
PointCloudService.GetService<IZoneSystem>().CurrentZoneType = pointType;
//this.GetSystem<IZoneSystem>().HideBigMeshColliderStayUnRegister(_onBigMeshColliderStayUnRegister);
}
}
private void OnBigMeshColliderExitEvent(Collider collider)
{
if (collider.gameObject.CompareTag("GameController"))
{
Debug.Log($"collider:【{collider.name}】 point:【{name}】 OnBigMeshColliderExitEvent");
bigMeshCollider.transform.parent.Find("Arrow").gameObject.SetActive(false);
OnColliderExit?.Invoke(collider);
}
}
/// <summary>
/// 打开区域的点位
/// </summary>
/// <param name="force">是否打开</param>
/// <param name="isOpenCurrentDomain">是否打开当前触发点位</param>
public void ActiveAllPointHideOrShow(bool force = true, bool isOpenCurrentDomain = true)
{
foreach (var controller in pointControllerEntities)
{
if (force == false)
{
controller.gameObject.SetActive(false);
}
else
{
if (isOpenCurrentDomain)
{
controller.gameObject.SetActive(true);
}
else
{
if (PointCloudService.GetService<IZoneSystem>().CurrentPointType == controller.name)
{
controller.gameObject.SetActive(false);
}
else
{
controller.gameObject.SetActive(true);
}
}
}
}
}
public void CurrentPointActiveHideOrShow(PointController controller, bool force = true)
{
foreach (var controllerEntity in pointControllerEntities)
{
if (controllerEntity == controller)
{
controller.gameObject.SetActive(force);
}
else
{
controllerEntity.gameObject.SetActive(!force);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5f2837f45bfd4347b76957e11fd63f6b
timeCreated: 1744876130

View File

@@ -0,0 +1,114 @@
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using UnityEngine;
namespace Main
{
public interface IZoneData
{
ZoneData[] GetZoneDataAll();
ZoneData GetZoneData(string domain);
PointData GetPointData(string zoneDomain, string pointDomain);
bool IsGizmo();
}
public class ZoneGatherData : IZoneData
{
private PointGatherData _pointGatherData;
public ZoneGatherData(PointGatherData pointGatherData)
{
_pointGatherData = pointGatherData;
}
/// <summary>
/// 通过id获取区域数据
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ZoneData[] GetZoneDataAll()
{
if (_pointGatherData != null)
{
for (int i = 0; i < _pointGatherData.ZoneDatas.Count; i++)
{
return _pointGatherData.ZoneDatas.ToArray();
}
Debug.LogWarning($"UnityEvo:PointGatherData is null");
}
else
{
Debug.LogError("UnityEvo:PointGatherData is null");
}
return default;
}
public bool IsGizmo()
{
if (_pointGatherData != null)
{
return _pointGatherData.isGizmo;
}
return false;
}
/// <summary>
/// 通过id获取区域数据
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ZoneData GetZoneData(string domain)
{
if (_pointGatherData != null)
{
for (int i = 0; i < _pointGatherData.ZoneDatas.Count; i++)
{
if (_pointGatherData.ZoneDatas[i].name == domain)
{
return _pointGatherData.ZoneDatas[i];
}
}
Debug.LogWarning($"UnityEvo:{domain}在PointGatherData is null");
}
else
{
Debug.LogError("UnityEvo:PointGatherData is null");
}
return default;
}
public PointData GetPointData(string zoneDomain, string pointDomain)
{
ZoneData zoneData = GetZoneData(zoneDomain);
if (zoneData.pointDatas != null)
{
for (int i = 0; i < zoneData.pointDatas.Count; i++)
{
if (zoneData.pointDatas[i].name == pointDomain)
{
return zoneData.pointDatas[i];
}
}
Debug.LogWarning($"UnityEvo:{pointDomain}在PointGatherData.zoneData.pointDatas is null");
}
else
{
Debug.LogError("UnityEvo:PointGatherData.zoneData.pointDatas is null");
}
return default;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 23cb528afab304d429cd1873c3ec2281
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,376 @@
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}");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c0daf3dc0256eff458e570c61418625b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "com.staryevo.codechecker",
"version": "1.0.0",
"displayName": "09.CodeChecker",
"description": "代码检查工具",
"unity": "2021.3",
"unityRelease": "30f1",
"keywords": [
"unity",
"scirpt"
],
"author": {
"name": "staryEvo",
"url": "https://www.unity3d.com"
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 72ff42479d0b7fc43bb5800cdba5b608
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: