데이터 즉시 업데이트 로직 추가

This commit is contained in:
logonkhi
2025-08-13 18:35:11 +09:00
parent 29a08c22e5
commit 026d6554ae
12 changed files with 1670 additions and 2729 deletions

View File

@@ -64,6 +64,12 @@ namespace UVC.Factory.Component
private float agvFloorOffset = 200f; //agv의 층을 구별하기 위한 값
private float agvZOffset = -197.5f; //층을 옮긴 agv의 위치를 잡아주기 위한 값
// true일 경우, UpdatePositionAndRotation에서 즉시 위치와 회전을 변경합니다.
// 한번으로 않되서 3번 즉시 변경하도록 설정
private bool needUpdateImmediately = false;
private int maxImmediateUpdateCount = 3;
private int immediateUpdateCount = 0;
/// <summary>
/// AGV 객체가 생성될 때 처음 한 번 호출되는 초기화 메서드입니다.
/// </summary>
@@ -101,6 +107,8 @@ namespace UVC.Factory.Component
base.OnDestroy();
}
/// <summary>
/// 선택 된 효과로 외곽선을 표시합니다.
/// </summary>
@@ -117,6 +125,17 @@ namespace UVC.Factory.Component
if (outlinable != null) outlinable.enabled = false;
}
/// <summary>
/// 즉시 객체의 상태를 업데이트합니다.
/// </summary>
/// <param name="count">업데이트 횟수. 기본값은 1입니다.</param>
public override void UpdateImmediately(int count = 3)
{
needUpdateImmediately = true; // 다음 데이터 업데이트에서 즉시 위치와 회전을 변경하도록 플래그를 설정합니다.
immediateUpdateCount = 0;
maxImmediateUpdateCount = count;
}
/// <summary>
/// AGVManager로부터 새로운 데이터를 받았을 때 호출되는 핵심 메서드입니다.
@@ -136,15 +155,18 @@ namespace UVC.Factory.Component
UpdatePositionAndRotation(newData);
// 받은 데이터를 내부 데이터 저장소에 저장합니다.
data = newData;
// 시작 시에는 현재 위치를 목표 위치로 설정하여 움직이지 않도록 합니다.
targetPosition = transform.position;
targetRotation = transform.rotation;
}
else // 이미 데이터가 있는 경우 (업데이트)
{
// 새 데이터를 기반으로 목표 위치와 회전을 갱신합니다.
UpdatePositionAndRotation(newData);
if (needUpdateImmediately)
{
transform.position = targetPosition;
transform.rotation = targetRotation;
immediateUpdateCount++;
if (immediateUpdateCount >= maxImmediateUpdateCount) needUpdateImmediately = false;
}
// 기존 데이터(data)에 새로운 데이터(newData)의 내용을 덮어씁니다.
foreach (var keyValue in newData)
{
@@ -172,8 +194,8 @@ namespace UVC.Factory.Component
float x = xVal.Value * scaleFactor;
float y = yVal.Value * scaleFactor;
Quaternion rotation = Quaternion.Euler(0, degreeVal.Value, 0);
transform.position = new Vector3(x, 0, y);
transform.rotation = rotation;
transform.position = targetPosition = new Vector3(x, 0, y);
transform.rotation = targetRotation = rotation;
}
}
else // 이후 업데이트의 경우
@@ -323,5 +345,11 @@ namespace UVC.Factory.Component
angularVelocity = 0f;
}
}
public override void UnregisterFactoryObject()
{
base.UnregisterFactoryObject();
needUpdateImmediately = false; // 파괴 시 즉시 위치와 회전 변경 플래그를 초기화합니다.
}
}
}

View File

@@ -223,6 +223,18 @@ namespace UVC.Factory.Component
}
}
/// <summary>
/// 즉시 객체의 상태를 업데이트합니다.
/// </summary>
public void UpdateImmediately(int count = 1)
{
if (agvPool == null) return;
foreach (var agv in agvPool.ActiveItems.Values)
{
if (agv != null) agv.UpdateImmediately(count);
}
}
/// <summary>
/// AGVManager가 파괴될 때 호출됩니다.
/// MQTT 파이프라인에서 'AGV' 핸들러를 제거하여 메모리 누수를 방지합니다.

View File

@@ -154,6 +154,27 @@ namespace UVC.Factory.Component
}
}
private Renderer[]? objectRenderers;
/// <summary>
/// 객체와 모든 자식의 렌더링 상태를 제어합니다.
/// true이면 보이게, false이면 보이지 않게 설정합니다.
/// </summary>
public bool IsVisible
{
get => objectRenderers?.Length > 0 && objectRenderers[0] != null && objectRenderers[0].enabled;
set
{
if (objectRenderers != null)
{
foreach (var r in objectRenderers)
{
if (r != null) r.enabled = value;
}
}
}
}
protected virtual void Awake()
{
// 초기화 작업을 수행합니다.
@@ -167,12 +188,15 @@ namespace UVC.Factory.Component
modelObject.OnPointerEnterHandler += OnPointerEnter;
modelObject.OnPointerExitHandler += OnPointerExit;
}
// 자신과 모든 자식 객체에서 Renderer 컴포넌트를 찾아 캐시합니다.
objectRenderers = GetComponentsInChildren<Renderer>();
}
/// <summary>
/// FactoryObject를 FactoryObjectManager에 등록합니다.
/// </summary>
public void RegisterFactoryObject()
public virtual void RegisterFactoryObject()
{
if (Info != null) FactoryObjectManager.Instance.RegisterFactoryObject(this);
}
@@ -180,7 +204,7 @@ namespace UVC.Factory.Component
/// <summary>
/// FactoryObject를 FactoryObjectManager에서 등록 해제합니다.
/// </summary>
public void UnregisterFactoryObject()
public virtual void UnregisterFactoryObject()
{
if(Info != null) FactoryObjectManager.Instance.UnregisterFactoryObject(Info);
}
@@ -278,6 +302,12 @@ namespace UVC.Factory.Component
/// </summary>
public virtual void HideOutLine() { }
/// <summary>
/// 즉시 객체의 상태를 업데이트합니다.
/// </summary>
/// <param name="count">업데이트 횟수. 기본값은 1입니다.</param>
public virtual void UpdateImmediately(int count = 1) { }
/// <summary>
/// 객체의 위치를 가져옵니다. 월드 좌표 또는 로컬 좌표로 반환할 수 있습니다.
/// </summary>

View File

@@ -129,7 +129,7 @@ namespace UVC.Factory.Component
if (Input.GetMouseButtonDown(0))
{
// 포인터가 UI 요소 위에 있는지 확인합니다. UI 클릭 시에는 선택/해제 로직을 무시합니다.
Debug.Log($"IsPointerOverUIObject() : {IsPointerOverUIObject()}");
//Debug.Log($"IsPointerOverUIObject() : {IsPointerOverUIObject()}");
if (IsPointerOverUIObject())
{
return;

View File

@@ -72,7 +72,6 @@ namespace UVC.Factory.Playback
DataRepository.Instance.MqttReceiver.Stop();
await PlaybackService.Instance.StartAsync(data);
FactoryCameraController.Instance.Enable = true;
UILoading.Hide();
}

View File

@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using UnityEngine;
using UVC.Data.Core;
using UVC.Data.Http;
using UVC.Factory.Component;
using UVC.Factory.Playback.UI;
using UVC.Util;
namespace UVC.Factory.Playback
@@ -44,12 +45,13 @@ namespace UVC.Factory.Playback
private readonly PlaybackRepository repository;
private string date;
private string time;
private string fileName;
private string date = string.Empty;
private string time = string.Empty;
private string fileName = string.Empty;
public Action? OnStartPlayback;
public Action? OnExitPlayback;
public Action? OnChangedTime;
private float timeScale = 1.0f;
/// <summary>
@@ -76,12 +78,12 @@ namespace UVC.Factory.Playback
}
}
public Action<float> OnChangeTimeScale;
public Action<float>? OnChangeTimeScale;
/// <summary>
/// 생성자. 일반적으로 직접 호출하지 않고 싱글턴 인스턴스를 사용합니다.
/// </summary>
public PlaybackService(PlaybackRepository repository)
private PlaybackService(PlaybackRepository repository)
{
this.repository = repository;
}
@@ -135,6 +137,7 @@ namespace UVC.Factory.Playback
List <PlaybackSQLiteDataEntity> list = await repository.SelectBySecondBaseInfo(date, fileName, formatTime);
if (list.Count > 0)
{
if(OnChangedTime != null) OnChangedTime.Invoke();
HttpRequestConfig httpRequestConfig = new HttpRequestConfig("");
httpRequestConfig.SetUpdatedDataOnly(true);
httpRequestConfig.SetSplitResponseByKey(true);