路径查找
在自动化系统中,物料流策略通常对吞吐量非常重要,仿真模型通常是为开发和优化这些策略而创建的。我们的库是开放和可扩展的,您可以实现自己的策略。
基础
没有后继或只有一个后继
如果当前路径的末端连接到另一条路径,MU 会自动进入下一条路径。如果没有路径连接,MU 通常会停在当前(未连接)路径的末端。如果 path mover 的 Exit Path 属性设置为 true,MU 将离开路径并自动由物理控制。
多于一个后继
如果路径有多个后继,TryMoveNext 公共方法会在 Path Mover 中被调用。以下策略序列会被调用:
步骤 1:检查 Path Mover 上组件的 SelectNextPath 方法。
- 首先,选择 Path Mover 上实现 ISelectNextPath 接口的所有组件。在所有组件中,SelectNextPath 方法被调用,传入对(Path Mover 中的)所有后继路径列表的引用。
- 实现的 SelectNextPath 方法能够从列表中删除路径(使得该路径肯定不被选为下一个后继)或重新排列列表,使得某个路径处于列表的第一个位置。
步骤 2:检查 Path 引用的 PathStrategy。
- 下一步是检查路径是否有分配的 PathStrategy。如果没有,我们进入步骤 3。PathStrategy 是对继承自 PathStrategy 的组件的引用。在 PathStrategy 中,必须实现公共方法 SelectNextPath。
步骤 3:检查路径本身组件的 SelectNextPath 方法。
- 接下来,调用路径本身上实现 ISelectNextPath 接口的所有组件。您将从步骤 2 获得剩余的后继列表(或者如果在步骤 1 中未找到逻辑,则获得完整的后继列表)。
步骤 4:选择剩余路径并将 MU 移动到下一个路径。
- 现在获取剩余的 NextPaths 列表。如果由于策略已删除所有后继路径而没有内容,则什么也不发生。否则,选择列表中的第一条路径,并将 MU 移动到下一条路径。
此图显示了路径查找的整体逻辑:

实现自定义策略
您可以实现自己的选择下一条路径的策略。您需要做的唯一一件事是创建一个实现 ISelectNextPath 接口的脚本。
如果您在逻辑中从 NextPaths 列表中删除了所有 path movers,path mover 将停在当前路径的末端。一旦系统中发生可能使路径策略成功的更改,您需要在被阻塞的 Path Mover 中调用 TryMoveNext。您可以在下面的选项 2 示例中看到这一点。
选项 1 - 向 Path Mover 或路径添加实现 ISelectNextPath 接口的组件。
以下是 DemoPathsystem_UseCases 演示模型中的一个示例。StrategyRandom 随机选择下一条路径。它作为组件附加到 Line:

策略本身如下所示:
public class StrategyRandom : realvirtual.ioBehavior,ISelectNextPath
{
public int Seed = 1;
public void SelectNextPath(PathMover pathMover,ref List<SimulationPath> Pathes)
{
var max = Pathes.Count-1;
int random = (int)Mathf.Round(Random.Range(-0.4999f, max+0.4999f));
var path = Pathes[random];
Pathes.Remove(path);
Pathes.Insert(0,path);
}
private void Start()
{
Random.seed = Seed;
}
}
选项 2 - 添加对继承自 PathStrategy 的组件的引用。
另一种定义自定义策略的方法是在路径本身中引用一个继承自 PathStrategy 的组件。以下是一个限制某个范围内数量的策略示例。
SelectNextPath 方法从位于路径末端的 Path Mover 被调用。如果范围内的当前数量大于允许的数量,路径列表将被清空。结果,Path Mover 被停止。等待的 Path Mover 通过调用 AddBlocked 被添加到阻塞列表中。
在启动期间,事件监听器被添加到所有进入或离开范围�路径上,引用 OnPathExit 或 OnPathEntered 方法。在仿真期间,这些方法递增或递减计数器。如果计数低于定义的阈值,则调用 AwakeBlocked。AwakeBlocked 在 PathStrategy 基类中实现。它在所有被阻塞的 path movers 中调用 TryMoveNext。
public class PathStrategyLimitNumber : PathStrategy
{
[Header("Settings")]
public int MaxNumber;
[ReorderableList] public List<SimulationPath> AreaEnterPathes;
[ReorderableList] public List<SimulationPath> AreaExitPathes;
[Header("Status")]
[realvirtual.io.ReadOnly] public int CurrentNumber;
public override void SelectNextPath(PathMover pathMover,ref List<SimulationPath> pathes)
{
if (CurrentNumber >= MaxNumber)
{
AddBlocked(pathMover);
pathes.Clear();
}
}
public void OnPathEntered(SimulationPath path, PathMover pathMover)
{
CurrentNumber = CurrentNumber + 1;
}
public void OnPathExit(SimulationPath path, PathMover pathMover)
{
CurrentNumber = CurrentNumber - 1;
if (CurrentNumber < MaxNumber)
AwakeBlocked();
}
void Start()
{
CurrentNumber = 0;
foreach (var enterpath in AreaEnterPathes)
{
enterpath.OnPathEntered.AddListener(OnPathEntered);
foreach (var pred in enterpath.Predecessors)
{
pred.PathStrategy = this;
}
}
foreach (var exitpath in AreaEnterPathes)
{
exitpath.OnPathExit.AddListener(OnPathExit);
}
}
}
© 2025 realvirtual GmbH https://realvirtual.io - All rights reserved. No part of this publication may be reproduced, distributed, or transmitted in any form or by any means, including printing, saving, photocopying, recording, or other electronic or mechanical methods, without the prior written permission of the publisher.