C# 卡车装车示例
Posted 多见多闻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 卡车装车示例相关的知识,希望对你有一定的参考价值。
1. 创建一个货物类,包含长、宽、高、重量、颜色、标签等属性,并定义一个列表用于存储所有货物对象。
public class Cargo
public float length;
public float width;
public float height;
public float weight;
public Color color;
public string label;
public Cargo(float l, float w, float h, float m, Color c, string lbl)
length = l;
width = w;
height = h;
weight = m;
color = c;
label = lbl;
List<Cargo> cargoes = new List<Cargo>();
2. 在UI界面中添加输入框和按钮,让用户输入货物参数和算法选择。
float length = float.Parse(lengthInput.text);
float width = float.Parse(widthInput.text);
float height = float.Parse(heightInput.text);
float weight = float.Parse(weightInput.text);
string label = labelInput.text;
Color color = colorPicker.color;
// 添加新货物到列表中
Cargo newCargo = new Cargo(length, width, height, weight, color, label);
cargoes.Add(newCargo);
// 计算最优摆放方案,使用选择的算法
if (algorithmDropdown.value == 0)
// 贪心算法
else if (algorithmDropdown.value == 1)
// 回溯算法
else if (algorithmDropdown.value == 2)
// 遗传算法
3. 实现贪心算法来计算最优摆放方案,并在场景中绘制货物。
// 定义贪心算法函数
public void GreedyAlgorithm()
float maxWidth = 20f;
float maxHeight = 10f;
float maxLength = 50f;
// 按照重量从大到小排序
cargoes.Sort((a, b) => b.weight.CompareTo(a.weight));
// 计算总体积和总重量,同时记录每个货物的位置和旋转角度
Vector3 pos = Vector3.zero;
Quaternion rot = Quaternion.identity;
float totalWeight = 0f;
float totalVolume = 0f;
foreach (Cargo cargo in cargoes)
if (cargo.length <= maxLength && cargo.width <= maxWidth && cargo.height <= maxHeight)
// 判断是否可以放入卡车
if (totalWeight + cargo.weight <= maxWeight && totalVolume + cargo.length * cargo.width * cargo.height <= maxVolume)
totalWeight += cargo.weight;
totalVolume += cargo.length * cargo.width * cargo.height;
// 计算当前货物的位置和旋转角度
cargo.transform.position = pos;
cargo.transform.rotation = rot;
cargo.gameObject.SetActive(true);
// 更新下一个货物的位置和旋转角度
Vector3 nextPos = pos + new Vector3(cargo.length / 2f, cargo.height / 2f, -cargo.width / 2f);
if (nextPos.y > maxHeight)
nextPos.y = 0f;
nextPos.x += maxLength;
pos = nextPos;
// 在场景中创建货物对象,设置位置和旋转角度,并添加到列表中
Cargo cargo1 = Instantiate(cargoPrefab).GetComponent<Cargo>();
cargo1.length = 5f;
cargo1.width = 2f;
cargo1.height = 3f;
cargo1.weight = 10f;
cargo1.color = Color.red;
cargo1.label = "Box 1";
cargo1.gameObject.SetActive(false);
cargoes.Add(cargo1);
// 绘制卡车模型,并计算最优摆放方案
CreateTruck();
GreedyAlgorithm();
4. 实现拖放事件和数据显示组件。
public class Cargo : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
public void OnBeginDrag(PointerEventData eventData)
// 开始拖动货物时,记录初始位置和旋转角度
startPos = transform.position;
startRot = transform.rotation;
5. 实现摆放到卡车功能,并在UI界面中添加“装载”按钮。
public class Cargo : MonoBehaviour
public void LoadToTruck()
// 将货物设置为静态,禁止再次拖放
GetComponent<Rigidbody>().isKinematic = true;
// 设置货物父节点为卡车对象
transform.SetParent(truck.transform);
// 将货物加入已装载货物列表中
loadedCargoes.Add(this);
public void LoadCargoesToTruck()
foreach (Cargo cargo in selectedCargoes)
cargo.LoadToTruck();
// 计算已装载货物的总重量和总体积
float totalWeight = 0f;
float totalVolume = 0f;
foreach (Cargo cargo in loadedCargoes)
totalWeight += cargo.weight;
totalVolume += cargo.length * cargo.width * cargo.height;
// 显示已装载货物的总重量和总体积
weightText.text = "Total weight: " + totalWeight.ToString("F2");
volumeText.text = "Total volume: " + totalVolume.ToString("F2");
6. 实现场景旋转、放大、拖动功能,并使用Unity自带的Camera类实现视角控制。
public class CameraController : MonoBehaviour
public float moveSpeed = 10f;
public float rotateSpeed = 100f;
public float zoomSpeed = 10f;
private Camera camera;
void Start()
camera = GetComponent<Camera>();
void Update()
// 控制场景移动
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
float depth = Input.GetAxis("Depth");
transform.position += transform.right * horizontal * moveSpeed * Time.deltaTime;
transform.position += transform.up * vertical * moveSpeed * Time.deltaTime;
transform.position += transform.forward * depth * moveSpeed * Time.deltaTime;
// 控制场景旋转
float rotateHorizontal = Input.GetAxis("Mouse X");
float rotateVertical = Input.GetAxis("Mouse Y");
transform.Rotate(Vector3.up, rotateHorizontal * rotateSpeed * Time.deltaTime, Space.World);
transform.Rotate(Vector3.left, rotateVertical * rotateSpeed * Time.deltaTime, Space.World);
// 控制摄像机缩放
float zoom = Input.GetAxis("Mouse ScrollWheel");
camera.fieldOfView -= zoom * zoomSpeed;
camera.fieldOfView = Mathf.Clamp(camera.fieldOfView, 1f, 100f);
7. 在UI界面中添加“保存场景”按钮,并使用Unity自带的JsonUtility类将货物列表保存到本地文件。
public void SaveScene()
// 将货物列表转换为JSON格式字符串
string json = JsonUtility.ToJson(cargoes);
// 将JSON字符串写入本地文件
string filePath = Application.dataPath + "/cargoes.json";
File.WriteAllText(filePath, json);
8. 在UI界面中添加“加载场景”按钮,并使用Unity自带的JsonUtility类从本地文件中读取货物列表。
public void LoadScene()
// 从本地文件读取JSON字符串
string filePath = Application.dataPath + "/cargoes.json";
string json = File.ReadAllText(filePath);
// 将JSON字符串转换为货物对象列表
cargoes = JsonUtility.FromJson<List<Cargo>>(json);
// 在场景中创建每个货物对象,并设置其位置和旋转角度
foreach (Cargo cargo in cargoes)
Cargo newCargo = Instantiate(cargoPrefab).GetComponent<Cargo>();
newCargo.length = cargo.length;
newCargo.width = cargo.width;
newCargo.height = cargo.height;
newCargo.weight = cargo.weight;
newCargo.color = cargo.color;
newCargo.label = cargo.label;
newCargo.transform.position = cargo.position;
newCargo.transform.rotation = cargo.rotation;
9. 在货物类中添加序列化属性,以便将货物对象保存到本地文件。
[System.Serializable]
public class Cargo
public float length;
public float width;
public float height;
public float weight;
public Color color;
public string label;
// 序列化货物位置和旋转角度
public Vector3 position;
public Quaternion rotation;
public Cargo(float l, float w, float h, float m, Color c, string lbl)
length = l;
width = w;
height = h;
weight = m;
color = c;
label = lbl;
10. 在货物类中添加Equals方法和GetHashCode方法,以便将相同属性的货物对象视为相等。
public override bool Equals(object obj)
if (obj == null) return false;
Cargo other = obj as Cargo;
if (other == null) return false;
return length == other.length && width == other.width && height == other.height && weight == other.weight && color.Equals(other.color) && label.Equals(other.label);
public override int GetHashCode()
return length.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ weight.GetHashCode() ^ color.GetHashCode() ^ label.GetHashCode();
11. 在摆放算法中实现相同货物尽量放置在一起的要求,并使用字典记录已放置的货物类型和数量。
// 定义贪心算法函数
public void GreedyAlgorithm()
float maxWidth = 20f;
float maxHeight = 10f;
float maxLength = 50f;
// 按照重量从大到小排序
cargoes.Sort((a, b) => b.weight.CompareTo(a.weight));
// 计算总体积和总重量,同时记录每个货物的位置和旋转角度
Vector3 pos = Vector3.zero;
Quaternion rot = Quaternion.identity;
float totalWeight = 0f;
float totalVolume = 0f;
Dictionary<Cargo, int> cargoCount = new Dictionary<Cargo, int>();
foreach (Cargo cargo in cargoes)
if (cargo.length <= maxLength && cargo.width <= maxWidth && cargo.height <= maxHeight)
// 判断是否可以放入卡车
if (totalWeight + cargo.weight <= maxWeight && totalVolume + cargo.length * cargo.width * cargo.height <= maxVolume)
// 判断是否需要新建一层
if (pos.y + cargo.height / 2f > maxHeight)
pos.y = 0f;
pos.x += maxLength;
// 判断是否与上一个货物相同
bool sameCargo = false;
foreach (KeyValuePair<Cargo, int> item in cargoCount)
if (item.Key.Equals(cargo))
sameCargo = true;
pos.z += item.Key.length / 2f + cargo.length / 2f;
break;
if (!sameCargo)
cargoCount[cargo] = 1;
else
cargoCount[cargo]++;
// 更新当前货物的位置和旋转角度
cargo.transform.position = pos;
cargo.transform.rotation = rot;
cargo.gameObject.SetActive(true);
// 更新下一个货物的位置和旋转角度
pos += new Vector3(0f, cargo.height / 2f, cargo.width / 2f);
totalWeight += cargo.weight;
totalVolume += cargo.length * cargo.width * cargo.height;
12. 在摆放算法中实现最大化利用空间要求,根据卡车尺寸计算每层最大可用空间,并动态调整货物高度来最大化利用空间。
// 定义贪心算法函数
public void GreedyAlgorithm()
float maxWidth = 20f;
float maxHeight = 10f;
float maxLength = 50f;
// 按照重量从大到小排序
cargoes.Sort((a, b) => b.weight.CompareTo(a.weight));
// 计算总体积和总重量,同时记录每个货物的位置和旋转角度
Vector3 pos = Vector3.zero;
Quaternion rot = Quaternion.identity;
float totalWeight = 0f;
float totalVolume = 0f;
Dictionary<Cargo, int> cargoCount = new Dictionary<Cargo, int>();
foreach (Cargo cargo in cargoes)
if (cargo.length <= maxLength && cargo.width <= maxWidth && cargo.height <= maxHeight)
// 判断是否可以放入卡车
if (totalWeight + cargo.weight <= maxWeight && totalVolume + cargo.length * cargo.width * cargo.height <= maxVolume)
// 判断是否需要新建一层
if (pos.y + cargo.height / 2f > maxHeight)
pos.y = 0f;
pos.x += maxLength;
// 判断是否与上一个货物相同
bool sameCargo = false;
foreach (KeyValuePair<Cargo, int> item in cargoCount)
if (item.Key.Equals(cargo))
sameCargo = true;
pos.z += item.Key.length / 2f + cargo.length / 2f;
break;
if (!sameCargo)
cargoCount[cargo] = 1;
else
cargoCount[cargo]++;
// 动态调整货物高度来最大化利用空间
float availableHeight = maxHeight - pos.y;
if (availableHeight < cargo.height)
cargo.transform.localScale *= availableHeight / cargo.height;
cargo.height = availableHeight;
// 更新当前货物的位置和旋转角度
cargo.transform.position = pos;
cargo.transform.rotation = rot;
cargo.gameObject.SetActive(true);
// 更新下一个货物的位置和旋转角度
pos += new Vector3(0f, cargo.height / 2f, cargo.width / 2f);
totalWeight += cargo.weight;
totalVolume += cargo.length * cargo.width * cargo.height;
13. 在UI界面中添加“清空场景”按钮,并在点击后移除所有已放置的货物,并重置数据显示。
public void ClearScene()
foreach (Cargo cargo in loadedCargoes)
Destroy(cargo.gameObject);
loadedCargoes.Clear();
weightText.text = "Total weight: ";
volumeText.text = "Total volume: ";
14. 在UI界面中添加“退出应用程序”按钮,并在点击后退出应用程序。
public void QuitApplication()
Application.Quit();
15. 在UI界面中添加“选择算法”下拉框,并在其中添加各种摆放算法选项。
public Dropdown algorithmDropdown;
void Start()
// 在下拉框中添加选项
List<string> algorithms = new List<string>() "Greedy Algorithm", "Genetic Algorithm", "Simulated Annealing" ;
algorithmDropdown.AddOptions(algorithms);
16. 在UI界面中添加“摆放货物”按钮,并在点击后根据选定的算法进行货物摆放。
public void LoadCargoes()
// 移除之前的货物
ClearScene();
// 根据选定的算法进行货物摆放
switch (algorithmDropdown.value)
case 0:
GreedyAlgorithm();
break;
case 1:
GeneticAlgorithm();
break;
case 2:
SimulatedAnnealing();
break;
// 更新数据显示
weightText.text = "Total weight: " + loadedWeight.ToString("F2") + " tons";
volumeText.text = "Total volume: " + loadedVolume.ToString("F2") + " cubic meters";
17. 在UI界面中添加“摆放到卡车”按钮,并在点击后将货物摆放到卡车上。
public void PlaceCargoes()
// 将货物摆放到卡车上
foreach (Cargo cargo in loadedCargoes)
cargo.transform.SetParent(truck.transform);
18. 在UI界面中添加“拖动场景”按钮,并在点击后启用场景拖放功能。
public void EnableDrag()
dragManager.enabled = true;
19. 在UI界面中添加“缩放场景”选框,并在选中后开启场景缩放功能。
public Toggle zoomToggle;
void Update()
// 如果选中了缩放场景选框,则开启场景缩放功能
if (zoomToggle.isOn)
float zoom = Input.GetAxis("Mouse ScrollWheel");
Camera.main.transform.position += Camera.main.transform.forward * zoom * zoomSpeed;
20. 在UI界面中添加“显示/隐藏方案”选框,并在选中后显示或隐藏货物摆放方案。
public Toggle planToggle;
void Update()
// 如果选中了显示/隐藏方案选框,则显示或隐藏货物摆放方案
foreach (Cargo cargo in loadedCargoes)
cargo.plan.SetActive(planToggle.isOn);
21. 在货物类中添加plan属性,并在创建货物时同时创建其对应的货物摆放方案。
public GameObject planPrefab;
public GameObject plan get; private set;
void Awake()
plan = Instantiate(planPrefab, transform.position, transform.rotation, transform);
plan.SetActive(false);
22. 在卡车类中添加bounds属性,表示卡车所占用的空间范围,并在添加货物时更新该属性。
public Bounds bounds get; private set;
void Awake()
bounds = new Bounds(transform.position, new Vector3(maxLength, maxHeight, maxWidth));
public bool AddCargo(Cargo cargo)
// 判断是否可以放入卡车
if (loadedWeight + cargo.weight <= maxWeight && loadedVolume + cargo.length * cargo.width * cargo.height <= maxVolume)
// 判断是否与上一个货物相同
bool sameCargo = false;
foreach (KeyValuePair<Cargo, int> item in cargoCount)
if (item.Key.Equals(cargo))
sameCargo = true;
pos.z += item.Key.length / 2f + cargo.length / 2f;
break;
if (!sameCargo)
cargoCount[cargo] = 1;
else
cargoCount[cargo]++;
// 更新当前货物的位置和旋转角度
cargo.transform.position = pos;
cargo.transform.rotation = rot;
cargo.gameObject.SetActive(true);
// 更新卡车的属性和下一个货物的位置和旋转角度
loadedCargoes.Add(cargo);
loadedWeight += cargo.weight;
loadedVolume += cargo.length * cargo.width * cargo.height;
bounds.Encapsulate(new Bounds(cargo.transform.position, new Vector3(cargo.length, cargo.height, cargo.width)));
pos += new Vector3(0f, cargo.height / 2f, cargo.width / 2f);
return true;
else
return false;
23. 在UI界面中添加“拖动货物”选框,并在选中后启用货物拖放功能。
public Toggle cargoDragToggle;
void Update()
// 如果选中了拖动货物选框,则启用货物拖放功能
if (cargoDragToggle.isOn)
foreach (Cargo cargo in loadedCargoes)
cargo.gameObject.AddComponent<DragManager>();
在 Anylogic 中,我如何为向多个客户交付订单的卡车建模
【中文标题】在 Anylogic 中,我如何为向多个客户交付订单的卡车建模【英文标题】:In Anylogic How can I model truck that deliver orders to multiple clients 【发布时间】:2021-10-21 00:26:03 【问题描述】:我正在根据 AnyLogic 提供的产品交付示例创建一个模型。在我自己的模型中,我希望一辆卡车在一次旅行中交付多个订单,而不是一次。我的流程图如下所示。在这里,一个订单通过 enter 块进入,并且在批处理块中累积了几个订单。每个订单都有一个指定的目的地。如何对卡车进行建模,使其结合两个订单并首先移动到最近的交货地点,然后是第二个等?
主要问题是我不知道每个订单中访问参数“交货位置”的代码。
enter image description here enter image description here
附加信息:
生成订单代理并将交货地点存储在名为“client”的参数中 批处理块将(比如说 2 个)订单组合成订单类型的批处理(高级设置设置为代理人数) 服务块从资源包中拉出一辆卡车,并使用 send(batch.unit) 将这批订单发送给卡车代理 卡车代理将订单/订单(?)存储在一个名为“订单”的变量中 然后,moveTo 函数应该将订单传递到第一个目的地移动到第一个、第二个等目的地的代码是什么?
【问题讨论】:
我已经删除了你的 [batch-file] 标签。每个标签都有一个描述,说明它们的用途。 [batch-file] 标签用于基于文本的脚本,这些脚本使用.bat
或.cmd
文件扩展名,并且在MS-DOS、OS/2 或Microsoft Windows 上运行。如果您认为有必要,请随意添加另一个标签,但请考虑是否有必要将您的问题引导给适当的受众。使用不适当的标签不仅不太可能帮助您获得解决方案,而且可能会吸引反对票或关闭票。
【参考方案1】:
这是您可能不知道的概念部分,它应该可以帮助您朝着正确的方向前进:
您可以将“for 循环”作为流程的一部分。在下面,您会看到一个示例,其中代理一直开车到某个地方,直到没有包裹为止。
显然,模块的详细信息取决于您的型号,但在每个模块中,如果您的卡车代理类型中有卡车订单(显然这是必需的),您就可以访问卡车的订单。
【讨论】:
以上是关于C# 卡车装车示例的主要内容,如果未能解决你的问题,请参考以下文章
在 Anylogic 中,我如何为向多个客户交付订单的卡车建模
制作卡车和按钮以提高速度,通过 jQuery 使用 html/js 改变方向
2021 中青杯 A题:汽车组装车间流水线物料配送问题 赛题思路