Context
A contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. is Saneject's way of saying "this object belongs to this serialized boundary".
Saneject uses contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. during editor injection to answer two questions:
- Which transforms participate in the injection walk?
- Which potential dependency candidatesDependency candidateObject considered during resolution before qualifiers, filters, and assignment determine whether it becomes the final injected dependency. can be injected in this component?
Context types
For GameObject hierarchies, Saneject uses these contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. types:
Scene object: a regular object in a scene.Prefab instance: a prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. in a scene or nested inside another prefab.Prefab asset: the prefab assetPrefab assetReusable prefab definition in the Project window. in the Project window.
Context equalityContext equalityRule for determining whether two objects are in the same context. Equality is instance-specific and based on context identity, not just context type. is instance-specific, not type-based. Saneject assigns a contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. ID and uses that ID to compare context equalityContext equalityRule for determining whether two objects are in the same context. Equality is instance-specific and based on context identity, not just context type.. The same rule applies to scenes, prefab instancesPrefab instanceInstantiated prefab placed in a scene or nested inside another prefab., and prefab assetsPrefab assetReusable prefab definition in the Project window..
Example:
- Scene A and Scene B are different contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..
- Prefab instancesPrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. of the same prefab assetPrefab assetReusable prefab definition in the Project window. are different contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..
- Each prefab assetPrefab assetReusable prefab definition in the Project window. is its own contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..
Each contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. also belongs to a containing serialized boundary:
- Scene objectsScene objectNon-prefab
GameObjectin a scene. and prefab instancesPrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. placed in a scene belong to that scene. - Prefab assetPrefab assetReusable prefab definition in the Project window. objects and nested prefab instancesPrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. inside a prefab assetPrefab assetReusable prefab definition in the Project window. belong to that prefab assetPrefab assetReusable prefab definition in the Project window..
This matters because with context isolationContext isolationProject setting (UseContextIsolation) that controls whether dependency resolution can cross context boundaries. disabled, Saneject still does not treat every contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. as compatible with every other one.
It only relaxes boundaries inside the same containing scene or prefab assetPrefab assetReusable prefab definition in the Project window..
Why contexts exist
Unity already enforces some serialization boundariesSerialization boundaryBoundary that determines which objects belong to the same serialized context for resolution and injection.. For example, scene objectsScene objectNon-prefab GameObject in a scene. cannot serialize direct references to prefab assetPrefab assetReusable prefab definition in the Project window. objects, and vice versa.
However, edit-time injection can still create dependencies across boundaries where Unity technically allows references, like between a scene objectScene objectNon-prefab GameObject in a scene. and prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. within the same scene. That can make a prefab depend on the scene where it was authored, making it less modular and portable to other contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..
Saneject addresses this with two controls:
Context isolation: controls whether dependency resolution can cross contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..Context filtering: controls which contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. are included in a specific injection runInjection runOne execution of the injection pipeline for a chosen selection, context walk filter, and active set of targets..
Context isolation
Context isolation is a project settingProject settingsSaneject settings shared at project scope, stored in ProjectSettings/Saneject/ProjectSettings.json and available from Saneject/Settings -> Project Settings..
- UI path:
Saneject/Settings/Project Settings/Use Context Isolation - File path:
{ProjectRoot}/ProjectSettings/Saneject/ProjectSettings.json
Because it is in ProjectSettings, teams can version control and share the same behavior. It is important that the entire project uses the same isolation setting so injection stays deterministic for everyone.
What isolation changes
When Saneject resolves an [Inject] member, there are two relevant steps:
- Find a matching bindingBindingInstruction declared in a
Scopethat tells Saneject what to resolve, how to inject it, and where to search. by walking scopesScopeMonoBehaviourthat declares bindings for a part of your hierarchy. upward. - Locate dependency candidatesDependency candidateObject considered during resolution before qualifiers, filters, and assignment determine whether it becomes the final injected dependency. from the chosen bindingBindingInstruction declared in a
Scopethat tells Saneject what to resolve, how to inject it, and where to search..
With isolation enabled:
- Step 1 only considers scopesScope
MonoBehaviourthat declares bindings for a part of your hierarchy. in the same contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. as the injection targetInjection targetComponentwith injected fields, properties or methods. component. - Step 2 rejects dependency candidatesDependency candidateObject considered during resolution before qualifiers, filters, and assignment determine whether it becomes the final injected dependency. from other contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..
With isolation disabled:
- Step 1 can walk across scene objectScene objectNon-prefab
GameObjectin a scene. and prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. boundaries inside the same containing scene or prefab assetPrefab assetReusable prefab definition in the Project window.. - Step 2 can also accept dependency candidatesDependency candidateObject considered during resolution before qualifiers, filters, and assignment determine whether it becomes the final injected dependency. across those boundaries.
Values resolved through asset bindingsAsset bindingBinding declared with BindAsset... or BindAssets... that resolves UnityEngine.Object assets from project content instead of scene or hierarchy components. are a separate case. They are treated as contextless for resolution purposes, so they are not filtered by scene or prefab contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. boundaries in the same way hierarchy-bound candidates are.
Practical effect
UseContextIsolation = true: Strict boundaries. A component can only get injected into other components from its own contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility., e.g., a component on a prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. cannot be injected into a component on a scene objectScene objectNon-prefabGameObjectin a scene..UseContextIsolation = false: Relaxed boundaries inside the same containing scene or prefab assetPrefab assetReusable prefab definition in the Project window.. Components can be injected across contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. within that boundary, e.g., a component on a prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. can be injected into a component on a scene objectScene objectNon-prefabGameObjectin a scene. in the same scene.
Context filtering
Context filtering decides which injection targetsInjection targetComponent with injected fields, properties or methods. are included in an injection runInjection runOne execution of the injection pipeline for a chosen selection, context walk filter, and active set of targets., meaning which components are processed for injection.
Saneject builds the injection graphInjection graphHierarchy model built from selected root hierarchies. It contains transform, component, scope, binding, and injection-member information used by the edit-time pipeline. first, then applies the selected ContextWalkFilter.
Only the filtered transforms become active, and only components under those transforms are processed.
What filtering does not do: it does not change context isolationContext isolationProject setting (UseContextIsolation) that controls whether dependency resolution can cross context boundaries. rules, and it does not directly filter dependency candidatesDependency candidateObject considered during resolution before qualifiers, filters, and assignment determine whether it becomes the final injected dependency. returned by an active bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search..
So if an active bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. searches into another contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility., those candidates can still be found. Whether they are accepted is still decided by UseContextIsolation.
Example: run with SceneObjects filter, and a scene Scope bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. uses FromDescendants.
If that hierarchy contains a prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. child, the bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. can still find components on that prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab..
UseContextIsolation = false: those cross-context candidates can be injected.UseContextIsolation = true: those cross-context candidates are rejected.
Why use filters
Filters are most useful as a focused debugging and iteration tool in large hierarchies.
For example, in a large scene, SceneObjects lets you validate scene-object wiring without processing prefab instancesPrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. in the same pass.
A common workflow is:
- Use filters selectively while developing or debugging.
- Run a full injection pass (
AllContextsor normal full scene/prefab injection) before final validation.
Filter options
AllContexts: process all transform nodes in the graph.SameContextsAsSelection: process only nodes that match the selected object contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..SceneObjects: process only scene objectScene objectNon-prefabGameObjectin a scene. contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..PrefabAssetObjects: process only prefab assetPrefab assetReusable prefab definition in the Project window. contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..PrefabInstances: process only prefab instancePrefab instanceInstantiated prefab placed in a scene or nested inside another prefab. contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility..
Where filters are used
You can pick run filters from:
- Injection context menuInjection context menuEditor command under
Saneject/Inject Scene/...,Saneject/Inject Selected Scene Hierarchies/...,Saneject/Inject Prefab Asset/..., or the matchingGameObject/Saneject/...paths that start an injection run with a selected target andContextWalkFilter. items. Batch Inject Selected Assetsmenu items underAssets/Saneject/Batch Inject Selected Assets/...andSaneject/Batch Inject Selected Assets/....- The
ContextWalkFilterdropdown in the Batch InjectorBatch InjectorEditor window for preparing and running batch injection with per-asset enable state, status, andContextWalkFilter. window for supported scene and prefab assetPrefab assetReusable prefab definition in the Project window. runs.
Isolation vs filtering
These features solve different problems:
- Context filteringContext filteringInjection-run prefilter that decides which transforms and injection targets are active for a run. decides what enters the run.
- Context isolationContext isolationProject setting (
UseContextIsolation) that controls whether dependency resolution can cross context boundaries. decides what gets injected where inside that run.
So you can run AllContexts and still keep strict boundaries by enabling context isolationContext isolationProject setting (UseContextIsolation) that controls whether dependency resolution can cross context boundaries..
Or you can run a narrow filter and still allow cross-context resolution by disabling context isolationContext isolationProject setting (UseContextIsolation) that controls whether dependency resolution can cross context boundaries..
Pipeline summary
At a high level, Saneject applies contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. rules in this order:
- Build the injection graphInjection graphHierarchy model built from selected root hierarchies. It contains transform, component, scope, binding, and injection-member information used by the edit-time pipeline. from the selected start roots.
- Apply
ContextWalkFilterto select active transforms. - Build active components, scopesScope
MonoBehaviourthat declares bindings for a part of your hierarchy., and bindingsBindingInstruction declared in aScopethat tells Saneject what to resolve, how to inject it, and where to search. from those transforms. - Resolve bindingsBindingInstruction declared in a
Scopethat tells Saneject what to resolve, how to inject it, and where to search. and dependency candidatesDependency candidateObject considered during resolution before qualifiers, filters, and assignment determine whether it becomes the final injected dependency.. - Apply context isolationContext isolationProject setting (
UseContextIsolation) that controls whether dependency resolution can cross context boundaries. rules while resolving.
Cross-context dependencies
If a dependency must cross a hard boundary (for example scene to prefab assetPrefab assetReusable prefab definition in the Project window.), use a runtime proxyRuntime proxyScriptableObject placeholder asset (RuntimeProxy<TComponent>) injected into interface members at editor time and swapped to the real instance during scope startup..
That is the intended pattern for cross-context wiring.
See Runtime proxy for details.
Visual examples
flowchart TB
subgraph Iso["Context isolation"]
EM["EnemyManager<br/>(scene object)"] -->|"Injected into GameManager"| GM["GameManager<br/>(scene object)"]
P["Player<br/>(prefab instance)"] --> Q{"UseContextIsolation?"}
Q -->|"true"| B["Not injected<br/>into GameManager"]
Q -->|"false"| A["Injected<br/>into GameManager"]
A --> GM
B -.-> GM
end
flowchart LR
subgraph Fil["Context filtering"]
R["Scene injection run"] --> F{"ContextFilter"}
F --> A["AllContexts"]
F --> S["SceneObjects"]
F --> P["PrefabInstances"]
A -->|"Processed"| AGM["GameManager<br/>(scene object)"]
A -->|"Processed"| AP["Player<br/>(prefab instance)"]
S -->|"Processed"| SGM["GameManager<br/>(scene object)"]
S -.->|"Not processed"| SP["Player<br/>(prefab instance)"]
P -.->|"Not processed"| PGM["GameManager<br/>(scene object)"]
P -->|"Processed"| PP["Player<br/>(prefab instance)"]
end