218 lines
6.8 KiB
C#
218 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UVC.Data.Core;
|
|
|
|
namespace Simulator.Data.Transport
|
|
{
|
|
public enum AGVType
|
|
{
|
|
AGV,
|
|
AFL,
|
|
ForkLift
|
|
}
|
|
public class AGV : ComponentBase
|
|
{
|
|
private Vector3 targetPosition;
|
|
private Vector3 startPosition;
|
|
private Quaternion targetRotation;
|
|
private float moveSpeed;
|
|
private float t = 0f;
|
|
|
|
public GameObject entitySocket;
|
|
public List<Entity> possessEntities = new List<Entity>();
|
|
int index = 0;
|
|
public AGVData data;
|
|
bool getdata = false;
|
|
public event Action<AGVDataType,AGVDataType> onStateUpdated;
|
|
AGVDataType _dataType;
|
|
public AGVDataType dataType
|
|
{
|
|
get
|
|
{
|
|
return _dataType;
|
|
}
|
|
set
|
|
{
|
|
if (value != _dataType)
|
|
{
|
|
onStateUpdated?.Invoke(_dataType,value);
|
|
_dataType = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdatePosition(Vector3 position)
|
|
{
|
|
transform.position = position;
|
|
//FitCollider();
|
|
}
|
|
|
|
public void SetTargetPosition(DataObject agvData)
|
|
{
|
|
var datas = agvData.GetDataObject("data");
|
|
var timing = datas.GetDataObject("timing");
|
|
var duration = timing.GetDataObject("duration");
|
|
targetPosition = AGVNodeManager.Instance.GetNodePosition(datas.GetString("to_node"));
|
|
startPosition = AGVNodeManager.Instance.GetNodePosition(datas.GetString("from_node"));
|
|
moveSpeed = (float)duration.GetFloat("real_seconds");
|
|
t = 0f;
|
|
getdata = true;
|
|
transform.LookAt(targetPosition);
|
|
//Debug.Log($"{datas.GetDateTime("timestamp").ToString()}{index}{data.name},from:{datas.GetString("from_node")},to:{datas.GetString("to_node")}");
|
|
//Debug.Log($"move{agvData.GetString("component_id")}");
|
|
}
|
|
private void PlaceNext(Entity entity)
|
|
{
|
|
if (entity == null) return;
|
|
|
|
if (entitySocket == null)
|
|
{
|
|
Debug.LogWarning("[AGV] entitySocket 이 null 입니다. 배치를 건너뜁니다.");
|
|
return;
|
|
}
|
|
|
|
// 부모/로컬 트랜스폼 설정
|
|
entity.transform.SetParent(entitySocket.transform, worldPositionStays: false);
|
|
|
|
// Z 방향 적층(기존 로직 유지)
|
|
float stepY = EntityManager.Instance.ObjectSize.y;
|
|
entity.transform.localPosition = new Vector3(0f, stepY * index,0f);
|
|
entity.transform.localRotation = Quaternion.identity;
|
|
|
|
// 중복 방지 후 등록
|
|
if (!possessEntities.Contains(entity))
|
|
possessEntities.Add(entity);
|
|
|
|
index++;
|
|
}
|
|
|
|
public override void SetEntity(string key, string name = "")
|
|
{
|
|
PlaceNext(EntityManager.Instance.GetEntity(key, name));
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (EntityManager.HasInstance)
|
|
EntityManager.Instance.OnEntityTransferred += HandleEntityTransferred;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (EntityManager.HasInstance)
|
|
EntityManager.Instance.OnEntityTransferred -= HandleEntityTransferred;
|
|
}
|
|
|
|
private void HandleEntityTransferred(Entity entity)
|
|
{
|
|
if (possessEntities.Contains(entity))
|
|
{
|
|
DecreaseEntity(entity);
|
|
}
|
|
}
|
|
|
|
public void LoadEntity(DataObject agvData)
|
|
{
|
|
var datas = agvData.GetDataObject("data");
|
|
var entity_Ids = datas.GetDataArray("entity_ids");
|
|
|
|
foreach (var entity in entity_Ids)
|
|
{
|
|
var id = entity.GetString("entity_id");
|
|
var name = entity.GetString("prefab_name");
|
|
SetEntity(id, name);
|
|
}
|
|
}
|
|
|
|
public void UnLoadEntity(DataObject agvData)
|
|
{
|
|
var data = agvData.GetDataObject("data");
|
|
var node = data.GetString("component");
|
|
var component = ComponentsManager.Instance.GetComponentData(node);
|
|
var entity_ids = data.GetDataArray("entity_ids");
|
|
foreach(var entity in entity_ids)
|
|
{
|
|
var entity_id = entity.GetString("entity_id");
|
|
component.SetEntity(entity_id);
|
|
}
|
|
}
|
|
|
|
public override void DecreaseEntity(Entity entity)
|
|
{
|
|
if (entity == null) return;
|
|
|
|
// 내부 리스트에서 제거(부모 변경/파괴 등 어떤 상태든 Remove는 안전)
|
|
possessEntities.Remove(entity);
|
|
|
|
// 재배치
|
|
ReflowEntities();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 보유 엔티티들을 0번 인덱스부터 다시 적층하여 빈칸 제거
|
|
/// 순회-수정 예외 방지를 위해 스냅샷을 만든 뒤, 원본을 비우고 다시 채움
|
|
/// </summary>
|
|
public void ReflowEntities()
|
|
{
|
|
|
|
// 위치 인덱스 초기화
|
|
index = 0;
|
|
|
|
// 스냅샷 생성 (null 제거)
|
|
var snapshot = new List<Entity>(possessEntities.Count);
|
|
foreach (var e in possessEntities)
|
|
{
|
|
if (e != null) snapshot.Add(e);
|
|
}
|
|
|
|
// 원본을 비운 뒤 스냅샷 기반으로 재배치
|
|
possessEntities.Clear();
|
|
|
|
foreach (var e in snapshot)
|
|
{
|
|
PlaceNext(e);
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (getdata)
|
|
{
|
|
if (moveSpeed <= 0f) return;
|
|
|
|
t += Time.deltaTime / moveSpeed;
|
|
|
|
// 위치 업데이트
|
|
if (t <= 1f)
|
|
{
|
|
transform.position = Vector3.Lerp(startPosition, targetPosition, t);
|
|
}
|
|
else
|
|
{
|
|
transform.position = targetPosition;
|
|
getdata = false;
|
|
dataType = AGVDataType.Idle;
|
|
}
|
|
}
|
|
|
|
/*
|
|
// 회전 업데이트
|
|
if (isRotating)
|
|
{
|
|
float currentAngle = transform.eulerAngles.y;
|
|
float targetAngle = targetRotation.eulerAngles.y;
|
|
float newAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angularVelocity, rotationSpeed, Mathf.Infinity, dampedTime);
|
|
transform.rotation = Quaternion.Euler(0, newAngle, 0);
|
|
}
|
|
else
|
|
{
|
|
transform.rotation = targetRotation;
|
|
angularVelocity = 0f;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
} |