Verse Wiki — the Verse handbook for Blueprint authors
Advanced · EXTRA

How Components Find Each Other: Communication Inside One Entity

In an inheritance-first world, a subclass that wants a parent's ability just calls it — the compiler guarantees it exists. Composition offers no such guarantee: your component that wants a mesh has to find the mesh, and not finding it is a perfectly legal outcome. This page covers how to look, when to look, and why looking is considerably more dangerous than calling.

1. GetComponent: Finding One by Type

The most-used entry point is GetComponent on entity: hand it a component type and it hands back that entity's component of that type. The official API describes it as: succeeds and returns the component of type component_type if it exists and is accessible from the calling context.

Note the "if" — this is a function carrying the <decides> effect, i.e. an expression that can fail, so it is called with square brackets and must live inside a failure context:

find_mesh.verse
# ✓ Correct: square brackets, wrapped in an if
if (Mesh := Entity.GetComponent[mesh_component]):
    Mesh.Disable()

# ✗ Wrong: a bare call. Compile complains the decides effect
#   is not allowed by this context
# Mesh := Entity.GetComponent[mesh_component]

You have drilled this shape endlessly in Lessons 12 and 18: an action that can fail must live somewhere failure is allowed. The only new thing here is what failure means — "this entity doesn't have that component attached".

The API also states an easily skimmed but important guarantee: when invoked during the AddedToScene or BeginSimulation phases, it ensures the returned component has reached the corresponding phase too. In plain terms: a component you find inside your own OnBeginSimulation has definitely begun simulating; you will never be handed a half-awake object. That guarantee is how Scene Graph solves initialization order for you — considerably more explicit than guessing which Component's BeginPlay fires first in Blueprint.

2. Finding a Batch: GetComponents and Searching Up or Down

Beyond fetching one by exact type, there are three broader routes:

Method What you get Typical use
Entity.GetComponents() Every component on this entity When you don't know the types, cast each one to probe
FindDescendantComponents Downward: components of a given type on descendant entities A parent component conducting a pile of child parts (lights, particles, sounds)
FindAncestorComponents Upward: components of a given type on ancestor entities A child part looking back to ask "which whole do I belong to?"

GetComponents() is the odd one out: since your code doesn't know in advance what it will get, Epic's recommended approach is casting each one to probe — if the cast succeeds, that component has the ability you were after (for example, it implements the "can be enabled" interface), so you can handle them uniformly. In Blueprint that's the familiar "get a list of Components, Cast To some class on each".

There is also a cheaper route: tags. Entities expose AddTag / ContainsTag and friends, and Epic recommends using them to pick out the entities you care about rather than relying on which components they carry or where they sit in the scene — both of which change on you. Same instinct as tagging Actors and using Get All Actors With Tag in Blueprint.

3. Epic's Discipline: Look Once, Then Stop Looking

Epic's Scene Graph Best Practices compresses component communication into what reads almost like an order: on begin simulation, find the needed child components once; store the references or subscribe to their events; then react to events instead of searching the graph again each time.

In code that takes two shapes. The first is subscribing — look once, hang a callback, then wait to be called:

subscribe_once.verse
watcher_component<public> := class<final_super>(component):

    OnBeginSimulation<override>():void =
        (super:)OnBeginSimulation()
        # Look exactly once here, then attach the callback
        if (Mesh := Entity.GetComponent[mesh_component]):
            Mesh.EntityEnteredEvent.Subscribe(OnEntityEntered)

    OnEntityEntered(Other:entity):void =
        Print("Something bumped into me")

The second is caching — look once, store it in your own field, use it directly thereafter:

cache_once.verse
blinker_component<public> := class<final_super>(component):

    # An empty box, ready (the option from Lesson 18)
    var CachedMesh:?mesh_component = false

    OnBeginSimulation<override>():void =
        (super:)OnBeginSimulation()
        if (Mesh := Entity.GetComponent[mesh_component]):
            set CachedMesh = option{Mesh}

    OnSimulate<override>()<suspends>:void =
        loop:
            Sleep(1.0)
            # Use the cache; never search the graph again
            if (Mesh := CachedMesh?):
                Mesh.Disable()
            Sleep(1.0)
            if (Mesh := CachedMesh?):
                Mesh.Enable()

Why be so strict? Because "search the graph" costs more as the project grows. Epic adds a specific warning: avoid sending events through large portions of the Scene Graph when a more localized approach will work; if prefab structure and tags can narrow the search, don't scan the whole graph. This all reads like premature optimization now; when your scene holds two thousand entities, it's the line between running and not.

One lighter communication route is worth knowing: scene events. Entities expose SendUp / SendDown to pass a message up or down the hierarchy; components override OnReceive to respond, returning true to mean "I consumed this, stop passing it along". This suits "a parent layer telling a batch of child parts to act" — you don't even need to know which components are hanging below; whoever wants it takes it.

4. Why Looking Is More Dangerous Than Calling

Now the question in the title. In Blueprint's inheritance world, calling Jump inside a Character subclass is underwritten by the compiler — it's declared on the parent, it isn't going anywhere. In a composition world, your component calls "another component on the same entity", and that component was attached by someone in a panel. Three new risks follow:

Hold those three next to Blueprint's GetComponentByClass and you'll find the risks are identical — Blueprint can also return None, also has initialization-order problems, also carries the implicit "this Blueprint requires you to attach component X" contract. The difference: Blueprint lets you defer discovering all of it until runtime (the classic Accessed None warning), while Verse forces you to write down "what happens when it's missing" at compile time. The cost is a few more lines; the return is one entire class of production incident.

A directly usable rule of thumb to close: prefer event subscription over polling lookups, prefer a parent conducting its children over children finding each other, and prefer freezing dependencies into a prefab over letting people assemble them by hand in a panel. Composition's freedom is its greatest strength and its greatest trap — your engineering discipline has to supply the guarantees the compiler no longer provides.

Per Epic's best practices, when a component needs long-term use of another component on the same entity, what should you do?

Sources

Compiled from Epic's official documentation and Verse API reference:

The Scene Graph API is still evolving; treat the official API reference of the day as authoritative for exact signatures and available events.