first commit

This commit is contained in:
lethanhsonvsp
2025-11-17 15:36:52 +07:00
commit 6f2eafa33c
14093 changed files with 1253472 additions and 0 deletions

View File

@@ -0,0 +1,266 @@
using UnityEngine;
using UnityEngine.Splines;
using Unity.Mathematics;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public class MultiSplineFollower : MonoBehaviour
{
[Header("Tuyến đường 1")]
public SplineRoute[] routes;
[Header("Tuyến đường 2")]
public SplineRoute[] routes1;
[Header("Tuyến đường 3")]
public SplineRoute[] routes2;
[Header("Cài đặt chuyển động")]
public float speed = 2f;
public float rotationSpeed = 180f;
public float angleThreshold = 30f;
[Header("Cài đặt quét TCIA")]
public float scanRadius = 0.5f; // bán kính quét đối tượng TCIA quanh follower
private int currentRouteIndex = 0;
private int currentRouteGroup = 0; // 0 = routes, 1 = routes1, 2 = routes2
private float t = 0f;
private bool onFirstSpline = true;
private bool isDelaying = false;
void Start()
{
if (GetActiveRoutes() == null || GetActiveRoutes().Length == 0) return;
var activeRoutes = GetActiveRoutes();
InitRoute(activeRoutes[0]);
t = activeRoutes[0].tStart;
transform.position = activeRoutes[0].splineStart.EvaluatePosition(0, t);
}
void Update()
{
var activeRoutes = GetActiveRoutes();
if (activeRoutes == null || activeRoutes.Length == 0) return;
if (currentRouteIndex >= activeRoutes.Length) return;
if (isDelaying) return;
SplineRoute route = activeRoutes[currentRouteIndex];
if (onFirstSpline)
MoveOnSpline(route.splineStart, ref t, route.tCommonA, true, route);
else
MoveOnSpline(route.splineEnd, ref t, route.tEnd, false, route);
}
SplineRoute[] GetActiveRoutes()
{
switch (currentRouteGroup)
{
case 0: return routes;
case 1: return routes1;
case 2: return routes2;
default: return null;
}
}
void InitRoute(SplineRoute route)
{
BezierKnot knotStart = route.splineStart.Spline.Knots.ElementAt(route.startKnotIndex);
BezierKnot knotEnd = route.splineEnd.Spline.Knots.ElementAt(route.endKnotIndex);
Vector3 knotX = route.splineStart.transform.TransformPoint((Vector3)knotStart.Position);
Vector3 knotY = route.splineEnd.transform.TransformPoint((Vector3)knotEnd.Position);
route.commonPoint = FindCommonPoint(route.splineStart, route.splineEnd);
float3 nearest;
SplineUtility.GetNearestPoint(route.splineStart.Spline,
(float3)route.splineStart.transform.InverseTransformPoint(knotX),
out nearest, out route.tStart);
SplineUtility.GetNearestPoint(route.splineStart.Spline,
(float3)route.splineStart.transform.InverseTransformPoint(route.commonPoint),
out nearest, out route.tCommonA);
SplineUtility.GetNearestPoint(route.splineEnd.Spline,
(float3)route.splineEnd.transform.InverseTransformPoint(route.commonPoint),
out nearest, out route.tCommonB);
SplineUtility.GetNearestPoint(route.splineEnd.Spline,
(float3)route.splineEnd.transform.InverseTransformPoint(knotY),
out nearest, out route.tEnd);
onFirstSpline = true;
}
void MoveOnSpline(SplineContainer spline, ref float t, float targetT, bool first, SplineRoute route)
{
Vector3 pos = spline.EvaluatePosition(0, t);
Vector3 tangent = Vector3.Normalize((Vector3)spline.EvaluateTangent(0, t));
if (route.reverseDirection) tangent = -tangent;
float angle = Vector3.Angle(transform.forward, tangent);
if (angle > angleThreshold)
{
Quaternion targetRot = Quaternion.LookRotation(tangent, Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
return;
}
float dir = (targetT > t) ? 1f : -1f;
t += dir * (Time.deltaTime * speed / spline.CalculateLength(0));
if ((dir > 0 && t >= targetT) || (dir < 0 && t <= targetT))
t = targetT;
pos = spline.EvaluatePosition(0, t);
tangent = Vector3.Normalize((Vector3)spline.EvaluateTangent(0, t));
if (route.reverseDirection) tangent = -tangent;
transform.position = pos;
transform.rotation = Quaternion.LookRotation(tangent, Vector3.up);
if (first && Mathf.Approximately(t, targetT))
{
onFirstSpline = false;
t = route.tCommonB;
}
else if (!first && Mathf.Approximately(t, targetT))
{
if (route.delayAtEnd)
{
StartCoroutine(DelayAndNextRoute(route));
}
else
{
NextRoute();
}
}
}
IEnumerator DelayAndNextRoute(SplineRoute route)
{
isDelaying = true;
if (route.attachTCIAObjects)
{
Debug.Log($"[{route.splineStart.name}] attachTCIAObjects = TRUE → quét và gắn TCIA");
AttachTCIAChildren();
}
else
{
DetachTCIAChildren();
}
yield return new WaitForSeconds(2f);
isDelaying = false;
NextRoute();
}
void AttachTCIAChildren()
{
GameObject[] allObjects = Object.FindObjectsByType<GameObject>(FindObjectsSortMode.None);
foreach (GameObject obj in allObjects)
{
if (!obj.activeInHierarchy || obj == this.gameObject)
continue;
if (obj.name.ToUpper().Contains("TCIA"))
{
float distance = Vector3.Distance(transform.position, obj.transform.position);
if (distance <= scanRadius)
{
obj.transform.SetParent(this.transform, true);
}
}
}
}
void DetachTCIAChildren()
{
List<Transform> childrenToDetach = new List<Transform>();
foreach (Transform child in transform)
{
if (child.name.ToUpper().Contains("TCIA"))
{
childrenToDetach.Add(child);
}
}
foreach (Transform child in childrenToDetach)
{
child.SetParent(null, true);
}
}
void NextRoute()
{
var activeRoutes = GetActiveRoutes();
currentRouteIndex++;
if (activeRoutes != null && currentRouteIndex < activeRoutes.Length)
{
InitRoute(activeRoutes[currentRouteIndex]);
t = activeRoutes[currentRouteIndex].tStart;
transform.position = activeRoutes[currentRouteIndex].splineStart.EvaluatePosition(0, t);
}
else
{
// Hết nhóm hiện tại → chuyển sang nhóm tiếp theo
currentRouteGroup++;
currentRouteIndex = 0;
var nextGroupRoutes = GetActiveRoutes();
if (nextGroupRoutes != null && nextGroupRoutes.Length > 0)
{
Debug.Log($"Chuyển sang nhóm tuyến: {currentRouteGroup}");
InitRoute(nextGroupRoutes[0]);
t = nextGroupRoutes[0].tStart;
transform.position = nextGroupRoutes[0].splineStart.EvaluatePosition(0, t);
}
else
{
Debug.Log("Hoàn thành toàn bộ tuyến đường!");
}
}
}
Vector3 FindCommonPoint(SplineContainer s1, SplineContainer s2)
{
foreach (var knotA in s1.Spline.Knots)
{
Vector3 pA = s1.transform.TransformPoint((Vector3)knotA.Position);
foreach (var knotB in s2.Spline.Knots)
{
Vector3 pB = s2.transform.TransformPoint((Vector3)knotB.Position);
if (Vector3.Distance(pA, pB) < 0.01f)
return pA;
}
}
Debug.LogWarning("Không tìm thấy điểm chung!");
return Vector3.zero;
}
}
[System.Serializable]
public class SplineRoute
{
public SplineContainer splineStart;
public int startKnotIndex;
public SplineContainer splineEnd;
public int endKnotIndex;
public bool reverseDirection;
public bool delayAtEnd;
public bool attachTCIAObjects = true; // true = gắn TCIA, false = tách TCIA khi delay
[HideInInspector] public Vector3 commonPoint;
[HideInInspector] public float tStart;
[HideInInspector] public float tCommonA;
[HideInInspector] public float tCommonB;
[HideInInspector] public float tEnd;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d70a28c0bc38f874b90921a56348fa45

8
Assets/Script/mqtt.meta Normal file
View File

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

View File

@@ -0,0 +1,46 @@
using UnityEngine;
using MQTTnet;
using MQTTnet.Client;
using System.Threading.Tasks;
using System.Text;
public class MqttClientController : MonoBehaviour
{
public string mqttBrokerAddress = "broker.hivemq.com";
public int mqttPort = 1883;
public IMqttClient mqttClient { get; private set; }
public bool IsConnected => mqttClient?.IsConnected ?? false;
async void Start()
{
var factory = new MqttFactory();
mqttClient = factory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithClientId("UnityClient")
.WithTcpServer(mqttBrokerAddress, mqttPort)
.WithCleanSession()
.Build();
mqttClient.ConnectedAsync += async e =>
{
Debug.Log("Connected to MQTT Broker.");
await Task.CompletedTask;
};
mqttClient.DisconnectedAsync += async e =>
{
Debug.Log("Disconnected from MQTT Broker.");
await Task.CompletedTask;
};
try
{
await mqttClient.ConnectAsync(options);
}
catch (System.Exception ex)
{
Debug.LogError($"MQTT connection failed: {ex.Message}");
}
}
}

View File

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

View File

@@ -0,0 +1,30 @@
using MQTTnet;
using MQTTnet.Protocol;
using UnityEngine;
public class MqttOJ : MonoBehaviour
{
public MqttClientController mqttClientController;
public string topic = "unity/position";
void Update()
{
if (mqttClientController != null && mqttClientController.IsConnected)
{
Vector3 position = transform.position;
string message = JsonUtility.ToJson(position);
var mqttMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(message)
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce)
.Build();
mqttClientController.mqttClient.PublishAsync(mqttMessage);
}
else
{
//Debug.LogWarning("MQTT client is not connected. Skipping publish.");
}
}
}

View File

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

View File

@@ -0,0 +1,54 @@
using MQTTnet;
using MQTTnet.Client;
using System;
using System.Threading.Tasks;
using UnityEngine;
public class MqttUnityClient : MonoBehaviour
{
private IMqttClient _mqttClient;
private async void Start()
{
await ConnectAsync();
// Đăng ký chủ đề để nhận tin nhắn
await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("unity/topic").Build());
}
private async Task ConnectAsync()
{
var factory = new MqttFactory();
_mqttClient = factory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithClientId("UnityClient")
.WithTcpServer("broker.hivemq.com", 1883)
.WithCleanSession()
.Build();
_mqttClient.ApplicationMessageReceivedAsync += e =>
{
// Xử lý tin nhắn nhận được
var message = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment);
Debug.Log($"Received: {message}");
return Task.CompletedTask;
};
await _mqttClient.ConnectAsync(options);
}
public async Task PublishAsync(string topic, string payload)
{
var message = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
.Build();
if (_mqttClient.IsConnected)
{
await _mqttClient.PublishAsync(message);
Debug.Log($"Published: {payload} to {topic}");
}
}
}

View File

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