AGVManager에 pool적용. MQTTPipeLineInfo, updatedDataOnly=true 일때 값 검증해야 함

This commit is contained in:
logonkhi
2025-06-25 19:44:34 +09:00
parent 784238efbf
commit aa9caab761
7 changed files with 509 additions and 57 deletions

View File

@@ -4,9 +4,11 @@ using SampleProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UVC.Core;
using UVC.Data;
using UVC.Pool;
namespace UVC.Factory.Component
{
@@ -78,8 +80,7 @@ namespace UVC.Factory.Component
{
private readonly string prefabPath = "Prefabs/SampleProject/Factory/AGV";
private GameObject? prefab;
private List<AGV> agvList;
private MonoBehaviourPool<AGV>? agvPool;
/// <summary>
/// AGVManager의 초기화 메서드입니다.
@@ -87,16 +88,16 @@ namespace UVC.Factory.Component
/// </summary>
protected override void Init()
{
agvList = new List<AGV>();
SceneMain.Instance.Initialized += OnSceneInitialized;
SceneMain.Instance.Initialized += OnSceneInitializedAsync;
}
/// <summary>
/// 씬이 완전히 초기화된 후 호출됩니다.
/// AGV 데이터를 수신하기 위한 MQTT 파이프라인을 설정합니다.
/// </summary>
private void OnSceneInitialized()
private async void OnSceneInitializedAsync()
{
await InitializePoolAsync();
//데이터를 어떤 형식으로 받을지 정의합니다.
var dataMask = new DataMask();
dataMask["VHL_NAME"] = "";
@@ -134,23 +135,31 @@ namespace UVC.Factory.Component
}
/// <summary>
/// 데이터 수신 시 호출되는 공개 핸들러입니다.
/// 비동기 처리 메서드인 OnUpdateDataAsync를 호출합니다.
/// AGV 풀을 비동기적으로 초기화합니다.
/// </summary>
/// <param name="data">수신된 데이터 객체 (일반적으로 DataArray 형태)</param>
public void OnUpdateData(IDataObject? data)
private async UniTask InitializePoolAsync()
{
OnUpdateDataAsync(data).Forget();
if (agvPool != null) return;
var prefab = await Resources.LoadAsync<GameObject>(prefabPath) as GameObject;
if (prefab == null)
{
Debug.LogError($"Prefab not found at path: {prefabPath}");
return;
}
agvPool = new MonoBehaviourPool<AGV>(prefab, transform);
}
/// <summary>
/// 데이터 수신 시 호출되는 공개 핸들러입니다.
/// 수신된 AGV 데이터 배열을 비동기적으로 처리하여 씬에 반영합니다.
/// 추가, 제거, 수정된 AGV 데이터를 각각 구분하여 처리합니다.
/// </summary>
/// <param name="data">수신된 데이터 (DataArray)</param>
public async UniTask OnUpdateDataAsync(IDataObject? data)
{
if (data == null) return;
/// <param name="data">수신된 데이터 객체 (DataArray 형태)</param>
public void OnUpdateData(IDataObject? data)
{
if (data == null || agvPool == null) return;
DataArray? arr = data as DataArray;
if (arr == null || arr.Count == 0) return;
@@ -159,32 +168,44 @@ namespace UVC.Factory.Component
var RemovedItems = arr.RemovedItems;
var ModifiedList = arr.ModifiedList;
//Debug.Log($"AGVManager received data: Added={AddedItems.Count}, Removed={RemovedItems.Count}, Modified={ModifiedList.Count}");
// 새로 추가된 AGV 처리
foreach (var item in AddedItems.ToList())
{
AGV? agv = await CreateAGV(item);
if (agv != null)
AGV? agv = agvPool.GetItem(item.GetString("VHL_NAME")!);
if (agv == null)
{
agv.UpdateData(item);
agvList.Add(agv);
Debug.LogError($"Failed to create AGV for {item.GetString("VHL_NAME")}");
continue;
}
agv.Info = new FactoryObjectInfo(
item.GetString("VHL_NAME"),
item.GetString("NODE_ID"),
"",
"",
item.GetString("MODE")
);
agv.UpdateData(item);
}
// 제거된 AGV 처리
foreach (var item in RemovedItems.ToList())
{
AGV agv = agvList.Find(x => x.Info != null && x.Info.Name == item.GetString("VHL_NAME"));
string vhlName = item.GetString("VHL_NAME")!;
AGV? agv = agvPool.FindActiveItem(vhlName);
if (agv != null)
{
Destroy(agv.gameObject);
agvList.Remove(agv);
agvPool.ReturnItem(vhlName);
}
}
// 정보가 수정된 AGV 처리
foreach (var item in ModifiedList.ToList())
{
AGV agv = agvList.Find(x => x.Info != null && x.Info.Name == item.GetString("VHL_NAME"));
Debug.Log($"AGVManager modified data: {item.ToString()}");
string vhlName = item.GetString("VHL_NAME")!;
AGV? agv = agvPool.FindActiveItem(vhlName);
if (agv != null)
{
agv.UpdateData(item);
@@ -193,40 +214,6 @@ namespace UVC.Factory.Component
}
/// <summary>
/// AGV 프리팹을 사용하여 새로운 AGV 게임 오브젝트를 생성하고 초기화합니다.
/// </summary>
/// <param name="data">신규 AGV의 정보가 담긴 DataObject</param>
/// <returns>생성 및 초기화된 AGV 컴포넌트, 실패 시 null</returns>
private async UniTask<AGV?> CreateAGV(DataObject data)
{
if (prefab == null)
{
prefab = await Resources.LoadAsync<GameObject>(prefabPath) as GameObject;
if (prefab == null)
{
Debug.LogError($"Prefab not found at path: {prefabPath}");
return null;
}
}
GameObject prefabInstance = Instantiate(prefab, transform);
if (prefabInstance == null)
{
Debug.LogError("Failed to instantiate AGV prefab.");
return null;
}
var agv = prefabInstance.GetComponent<AGV>();
// AGV의 고정 정보(Info)를 설정합니다. 이 정보는 FactoryObjectManager 등에서 사용될 수 있습니다.
agv.Info = new FactoryObjectInfo(
data.GetString("VHL_NAME"),
data.GetString("NODE_ID"),
"",
"",
data.GetString("MODE")
);
return agv;
}
/// <summary>
/// AGVManager가 파괴될 때 호출됩니다.
/// MQTT 파이프라인에서 'AGV' 핸들러를 제거하여 메모리 누수를 방지합니다.
@@ -235,6 +222,7 @@ namespace UVC.Factory.Component
{
base.OnDestroy();
AppMain.Instance.MQTTPipeLine.Remove("AGV");
agvPool?.ClearRecycledItems();
}
}
}