When working with complex hierarchical models in FlexSim, referencing objects deep inside a structure can quickly become difficult to manage. When not using multiple centre port connections (which gets messy) users often rely on manually created labels and pointers, but that in turn can introduce extra work and inconsistency—especially when deciding whether a label should reference a single object or an array.
This post describes a small set of user commands, packaged as an auto-installing user library, that automatically builds and maintains hierarchical object references based on each object’s role.
The goal is simple: allow users to reference objects using intuitive chains like:
current.printerCell.rewinder.turret
without manually creating or maintaining those labels.
This system automatically:
The functionality is delivered as:
containerReset(current)
Users can drop this container into their model and begin assigning functionname labels to objects. The rest is handled automatically at reset.
Each object declares its role using a label such as:
functionname = "rewinder"
From this, the system builds references dynamically using only the tree hierarchy.
A key point is that this is not limited to containers. Any object, including standard FlexSim fixed resources such as processors, sources, queues, and sinks, can and should also be given a functionname when you want it to participate in the reference structure.
That means this system maps not just structure, but function.
On reset, each relevant container calls:
containerReset(current)
This starts the process of rebuilding all references from the current tree structure.
If an object has a non-empty functionname, it adds a reference to itself on the next relevant level above it.
So if a rewinder contains a turret, the rewinder can gain:
rewinder.turret
If an intermediate object has no functionname, the logic recurses through it rather than making it part of the reference chain.
That means purely structural levels can exist in the tree without cluttering the reference path.
So a structure like:
printerCell
└─ layoutContainer
└─ rewinder
└─ turret
can still produce:
printerCell.rewinder.turret
even though layoutContainer exists physically in the tree.
If an object has:
systemContainer = true
then its own functionname is pushed down to all contained objects.
So if printerCell is marked as a system container, nested objects can directly reference:
current.printerCell
This makes it easy for deeply nested components to find the root system they belong to.
If a label already points to one object and a second different object needs to be stored under the same role name, the value is automatically converted into an array.
So if one rewinder contains multiple turrets, then:
rewinder.turret
becomes an array of turret pointers instead of a single pointer.
Users do not need to decide this in advance.
A useful feature of this approach is that a “system” does not have to mean a single tightly integrated machine.
A system can be:
As long as those objects live under a meaningful tree structure, the same logic works. A printer cell can be used as a standalone system, then placed inside a larger factory container and reset again to gain one more level of functional context.
That makes the approach scalable from machine-level modeling to line-level or factory-level organization.
I’m also including an example printer cell model where the labels are not pre-populated.
You can:
Then you can place that same printer cell inside a factory container, reset again, and inspect the results after the hierarchy changes.
That gives a simple way to see the library working in both a standalone and larger-system context.
Below are the three user commands that make this work.
This is the reset entry point.
It does three things:
So this command seeds both the upward and downward context, then delegates the deeper hierarchy building.
This utility adds a reference safely and automatically handles whether the label should be:
If the label is empty, it stores a single object pointer.
If it already points to a different object, it converts the value into an array.
If it is already an array, it adds the new object only if it is not already present.
This is what removes the need for users to decide ahead of time whether a role is unique or repeated.
This is the recursive traversal function.
It walks downward through the tree under container and looks for objects with a non-empty functionname.
When it finds one, it adds a reference on current using that object’s function name.
When it encounters an object with no functionname, it does not stop. Instead, it recurses further downward through that object’s children.
This is the key to skipping non-functional levels in the tree.
In effect, this command says:
Starting from the current functional object, keep searching downward until you find the next lower functional objects, then create references to them.
That is what allows the reference chain to reflect logical structure rather than every structural level.
This approach gives you:
Instead of writing search logic, you can work with meaningful chains such as:
current.printerCell.rewinder.turret
Set functionname based on what the object does, not its instance name.
Good examples:
printerCell
rewinder
turret
infeedQueue
Less useful examples:
object1
machineA
testNode
If you reuse systems or templates, keep the same functionname values so code remains portable.
Not every object needs one. Use it on objects you want to reference directly in logic.
Do not treat this as a container-only feature. Fixed resources such as processors, sources, queues, and sinks can also participate and often should as these will be the objects your want to setup, load or listen to.
Mark the objects that represent meaningful system roots. That may be a machine, a cell, a line, or a factory-level grouping.
If multiple objects with the same function appear under the same functional parent, that reference will become an array.
Since this works purely from tree structure, the physical organization of the tree should support the logical organization of the model.
If you find yourself repeatedly searching for the same kind of object, that is often a sign that it should have a functionname.
This approach turns the model hierarchy into a self-maintaining functional reference map.
By assigning functionname labels to meaningful objects and rebuilding relationships during reset with containerReset(current), the model can automatically expose useful object references without manual wiring.
That works whether the model represents a single complex machine or a larger factory made up of linked but physically distinct cells.
The result is cleaner code, easier maintenance, and a more consistent way to navigate hierarchical models.