469 lines
13 KiB
C#
469 lines
13 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Events;
|
|
using Octopus.Simulator.Networks;
|
|
using Newtonsoft.Json;
|
|
using Octopus.Simulator;
|
|
|
|
#region class
|
|
[Serializable]
|
|
public class MoveDataClass_start
|
|
{
|
|
public string move_id;
|
|
public string move_label;
|
|
public string type;
|
|
public float move_time;
|
|
public int capacity;
|
|
public int products_per_batch;
|
|
public List<InputQueue> input_queues;
|
|
public string output_queue;
|
|
public string defect_queue;
|
|
public string required_resource;
|
|
public float return_time;
|
|
public int min_batch_size;
|
|
public float loading_delay;
|
|
public float unloading_delay;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_loading
|
|
{
|
|
public string move_id;
|
|
public string move_label;
|
|
public int loaded_count;
|
|
public List<string> source_queues;
|
|
public List<string> source_stores;
|
|
public float loading_delay;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Request_Resource
|
|
{
|
|
public string move_id;
|
|
public string move_label;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Resource_Acquired
|
|
{
|
|
public string resource;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Speed_Factor_Applied
|
|
{
|
|
public float original;
|
|
public float adjusted;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Move_Moving
|
|
{
|
|
public float time;
|
|
public float loading_delay;
|
|
public float unloading_delay;
|
|
public MoveMovingInput input;
|
|
public MoveMovingOutput output;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveMovingInput
|
|
{
|
|
public List<string> queues;
|
|
public List<string> stores;
|
|
}
|
|
[Serializable]
|
|
public class MoveMovingOutput
|
|
{
|
|
public string queue;
|
|
public string store;
|
|
public string defect_queue;
|
|
public string defect_store;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Arrived
|
|
{
|
|
public int count;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Unloading_Defect
|
|
{
|
|
public string product_id;
|
|
public string output_queue;
|
|
public int output_queue_length;
|
|
public float unloading_delay;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Unloading_Defect_Store
|
|
{
|
|
public string product_id;
|
|
public string store_name;
|
|
public int store_length;
|
|
public float unloading_delay;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Unloading
|
|
{
|
|
public string product_id;
|
|
public string output_queue;
|
|
public int output_queue_length;
|
|
public float unloading_delay;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_Unloading_Store
|
|
{
|
|
public string product_id;
|
|
public string store_name;
|
|
public int store_queue_length;
|
|
public float unloading_delay;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClass_returning
|
|
{
|
|
public float return_time;
|
|
}
|
|
|
|
[Serializable]
|
|
public class MoveDataClassStatistics
|
|
{
|
|
public statisticsMove statistics;
|
|
}
|
|
|
|
[Serializable]
|
|
public class statisticsMove
|
|
{
|
|
public int total_moved;
|
|
}
|
|
|
|
public enum UnLoadingState
|
|
{
|
|
store,
|
|
queue,
|
|
defectStore,
|
|
defectQueue
|
|
}
|
|
#endregion
|
|
|
|
public class SimulationModelMove : SimulationModel
|
|
{
|
|
[Header("Transport")]
|
|
public List<GameObject> listProducts = new List<GameObject>();
|
|
public Transform productPos;
|
|
public Vector3 productDistance = new Vector3(0, 0.321f, 0);
|
|
|
|
int productCount = 0;
|
|
int currentCount = 0;
|
|
int totalMoved = 0;
|
|
bool isFirstTransport = true;
|
|
|
|
Transform origin = null;
|
|
public Transform destination = null;
|
|
|
|
public float arrivalTime = 0;
|
|
public float elapsedTime = 0;
|
|
|
|
Vector3 originalPos;
|
|
Vector3 prevPos;
|
|
|
|
void Update()
|
|
{
|
|
if (!simulationUI.isplaying)
|
|
return;
|
|
|
|
UpdateProductStacking();
|
|
UpdateMovement();
|
|
}
|
|
|
|
private void UpdateProductStacking()
|
|
{
|
|
if (productCount != listProducts.Count)
|
|
{
|
|
productCount = listProducts.Count;
|
|
// 단순하게 모두 같은 offset으로 배치 (필요 시 i 기반 offset으로 확장)
|
|
foreach (var gb in listProducts)
|
|
{
|
|
if (gb != null)
|
|
{
|
|
gb.transform.localPosition = productDistance;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateMovement()
|
|
{
|
|
if (destination == null)
|
|
return;
|
|
|
|
elapsedTime += Time.deltaTime * WebParameters.speed;
|
|
|
|
if (arrivalTime <= 0f)
|
|
return;
|
|
|
|
float t = elapsedTime / arrivalTime;
|
|
if (t > 1f)
|
|
{
|
|
transform.position = destination.position;
|
|
transform.forward = destination.forward;
|
|
destination = null;
|
|
}
|
|
else
|
|
{
|
|
Vector3 newPos = Vector3.Lerp(originalPos, destination.position, t);
|
|
transform.position = newPos;
|
|
|
|
Vector3 dir = newPos - prevPos;
|
|
dir.y = 0;
|
|
if (dir.sqrMagnitude > 0.0001f)
|
|
{
|
|
dir.Normalize();
|
|
transform.forward = dir;
|
|
}
|
|
|
|
prevPos = newPos;
|
|
}
|
|
}
|
|
|
|
public override void GetData(string data)
|
|
{
|
|
var wrapclass = JsonConvert.DeserializeObject<SimulationDefaultJson>(data);
|
|
if (wrapclass == null || string.IsNullOrEmpty(wrapclass._event))
|
|
return;
|
|
|
|
switch (wrapclass._event)
|
|
{
|
|
case "move_loading":
|
|
LoadingCargo(wrapclass.data.ToString());
|
|
break;
|
|
case "move_moving":
|
|
Moving(wrapclass.data.ToString());
|
|
break;
|
|
case "move_unloading":
|
|
Unloading(wrapclass.data.ToString(), UnLoadingState.queue);
|
|
break;
|
|
case "move_unloading_store":
|
|
Unloading(wrapclass.data.ToString(), UnLoadingState.store);
|
|
break;
|
|
case "move_unloading_defect":
|
|
Unloading(wrapclass.data.ToString(), UnLoadingState.defectQueue);
|
|
break;
|
|
case "move_unloading_defect_store":
|
|
Unloading(wrapclass.data.ToString(), UnLoadingState.defectStore);
|
|
break;
|
|
case "move_arrived":
|
|
Arrive(wrapclass.data.ToString());
|
|
break;
|
|
case "move_speed_factor_applied":
|
|
SpeedFactorApply(wrapclass.data.ToString());
|
|
break;
|
|
case "move_returning":
|
|
Returning(wrapclass.data.ToString());
|
|
break;
|
|
case "move_statistics_update":
|
|
totalMoved = JsonConvert.DeserializeObject<MoveDataClassStatistics>(wrapclass.data.ToString()).statistics.total_moved;
|
|
SetBubble(totalMoved);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void LoadingCargo(string data)
|
|
{
|
|
var loading = JsonConvert.DeserializeObject<MoveDataClass_loading>(data);
|
|
if (loading == null)
|
|
return;
|
|
|
|
currentCount = loading.loaded_count;
|
|
SetBubble(currentCount);
|
|
|
|
// 처음 운송이면 출발 위치 세팅
|
|
if (isFirstTransport)
|
|
{
|
|
string sourceId = GetFirstNonEmpty(loading.source_queues, loading.source_stores);
|
|
if (!string.IsNullOrEmpty(sourceId))
|
|
{
|
|
var sourceModel = DataManager.I.GetModel(sourceId) as SimulationModelStore;
|
|
if (sourceModel != null)
|
|
{
|
|
transform.position = sourceModel.GetTransporterPosition()?.position ?? transform.position;
|
|
}
|
|
}
|
|
isFirstTransport = false;
|
|
}
|
|
|
|
AddProducts(loading.loaded_count);
|
|
}
|
|
|
|
private void Moving(string data)
|
|
{
|
|
var moveData = JsonConvert.DeserializeObject<MoveDataClass_Move_Moving>(data);
|
|
if (moveData == null)
|
|
return;
|
|
|
|
elapsedTime = 0f;
|
|
arrivalTime = moveData.time;
|
|
originalPos = transform.position;
|
|
prevPos = transform.position;
|
|
|
|
string inputId = GetFirstNonEmpty(moveData.input?.queues, moveData.input?.stores);
|
|
if (!string.IsNullOrEmpty(inputId))
|
|
{
|
|
var model = DataManager.I.GetModel(inputId) as SimulationModelStore;
|
|
if (model != null)
|
|
origin = model.GetTransporterPosition();
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(moveData.output?.queue))
|
|
{
|
|
var model = DataManager.I.GetModel(moveData.output.queue) as SimulationModelStore;
|
|
if (model != null)
|
|
destination = model.GetTransporterPosition();
|
|
}
|
|
else if (!string.IsNullOrEmpty(moveData.output?.store))
|
|
{
|
|
var model = DataManager.I.GetModel(moveData.output.store) as SimulationModelStore;
|
|
if (model != null)
|
|
destination = model.GetTransporterPosition();
|
|
}
|
|
}
|
|
|
|
private string GetFirstNonEmpty(List<string> listA, List<string> listB)
|
|
{
|
|
if (listA != null && listA.Count > 0)
|
|
return listA[0];
|
|
if (listB != null && listB.Count > 0)
|
|
return listB[0];
|
|
return string.Empty;
|
|
}
|
|
|
|
private void AddProducts(int count)
|
|
{
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var product = ProductManager.Instance.SpawnProduct();
|
|
if (product == null)
|
|
continue;
|
|
|
|
product.GetComponent<SimulationModelProduct>().SetParent(this.nodeID);
|
|
product.transform.parent = productPos;
|
|
product.transform.localPosition = Vector3.zero;
|
|
product.transform.localRotation = Quaternion.identity;
|
|
listProducts.Add(product);
|
|
}
|
|
}
|
|
|
|
private void Unloading(string data, UnLoadingState state)
|
|
{
|
|
string targetID = string.Empty;
|
|
|
|
switch (state)
|
|
{
|
|
case UnLoadingState.store:
|
|
var store = JsonConvert.DeserializeObject<MoveDataClass_Unloading_Store>(data);
|
|
targetID = store?.store_name ?? string.Empty;
|
|
break;
|
|
case UnLoadingState.queue:
|
|
var queue = JsonConvert.DeserializeObject<MoveDataClass_Unloading>(data);
|
|
targetID = queue?.output_queue ?? string.Empty;
|
|
break;
|
|
case UnLoadingState.defectStore:
|
|
var defectStore = JsonConvert.DeserializeObject<MoveDataClass_Unloading_Defect_Store>(data);
|
|
targetID = defectStore?.store_name ?? string.Empty;
|
|
break;
|
|
case UnLoadingState.defectQueue:
|
|
var defectQueue = JsonConvert.DeserializeObject<MoveDataClass_Unloading_Defect>(data);
|
|
targetID = defectQueue?.output_queue ?? string.Empty;
|
|
break;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(targetID))
|
|
return;
|
|
|
|
var model = DataManager.I.GetModel(targetID);
|
|
if (model == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var storeModel = model.GetComponent<SimulationModelStore>();
|
|
|
|
if (listProducts.Count > 0)
|
|
{
|
|
var product = listProducts[0];
|
|
// storeModel?.StoreProduct(product); // 필요 시 활성화
|
|
listProducts.RemoveAt(0);
|
|
Destroy(product);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("Trying to unload from empty transporter : " + nodeID);
|
|
}
|
|
}
|
|
|
|
private void Arrive(string data)
|
|
{
|
|
var arrived = JsonConvert.DeserializeObject<MoveDataClass_Arrived>(data);
|
|
if (arrived == null)
|
|
return;
|
|
|
|
currentCount -= arrived.count;
|
|
SetBubble(currentCount);
|
|
}
|
|
|
|
private void SpeedFactorApply(string data)
|
|
{
|
|
var speedData = JsonConvert.DeserializeObject<MoveDataClass_Speed_Factor_Applied>(data);
|
|
if (speedData == null)
|
|
return;
|
|
|
|
float originalTime = speedData.original;
|
|
float adjustedTime = speedData.adjusted;
|
|
arrivalTime += adjustedTime - originalTime;
|
|
elapsedTime = 0f;
|
|
originalPos = transform.position;
|
|
prevPos = transform.position;
|
|
}
|
|
|
|
private void Returning(string data)
|
|
{
|
|
var ret = JsonConvert.DeserializeObject<MoveDataClass_returning>(data);
|
|
if (ret == null)
|
|
return;
|
|
|
|
elapsedTime = 0f;
|
|
arrivalTime = ret.return_time;
|
|
originalPos = transform.position;
|
|
prevPos = transform.position;
|
|
if (origin != null)
|
|
destination = origin;
|
|
}
|
|
|
|
public override void SetBubble(object data)
|
|
{
|
|
string msg = $"{currentCount}/{totalMoved}";
|
|
|
|
if (currentBubble == null)
|
|
{
|
|
// 생성
|
|
currentBubble = Instantiate(bubbleUIPrefab, FindAnyObjectByType<Canvas_Bubble>().transform);
|
|
currentBubble.target = DataBubbleSocket;
|
|
currentBubble.worldOffset = new Vector3(0, 2.0f, 0); // 필요에 따라 조절
|
|
currentBubble.GetComponent<RectTransform>().SetAsFirstSibling();
|
|
}
|
|
// 텍스트 갱신
|
|
currentBubble.SetMessage(msg);
|
|
List<string> datas = new List<string>
|
|
{
|
|
currentCount.ToString(),
|
|
totalMoved.ToString()
|
|
};
|
|
currentBubble.SetDetail(datas, logicType.move, LogicUIManager.instance.GetItemLabelByID(nodeID));
|
|
}
|
|
}
|