Object Identifier
Use Object Identifier to give a GameObject a stable numeric role when UCC must find it within a runtime hierarchy, or when a Detect Object ability should accept only a particular kind of target.
An Object Identifier is a passive marker. It does not register the GameObject globally, make an ID unique, or save and synchronize the object. A consumer such as an ID/Object field or Detect Object ability decides where and when to look for the marker.
Choose when to use an identifier
| Goal | Recommended reference |
|---|---|
| A component always uses one object in the same scene or prefab | Assign the object reference directly when that field supports it. |
| A reusable item prefab must find a spawn point, holster, muzzle, or another role on the character’s active model | Give the role an Object Identifier and select the same ID in the item’s ID/Object field. |
| Several interchangeable character models expose the same role | Put the same semantic ID on the equivalent GameObject in each model. Keep only one match within each searched model hierarchy. |
| Interact, Look At, Pickup, Drive, Ride, or another Detect Object ability should accept a narrower set of targets | Put the identifier on the detected GameObject or one of its parents and set the ability’s Object ID to match. |
| A system needs a scene-wide lookup, persistent save identity, or network identity | Use a project-level registry or persistence/network identifier. Object Identifier does not provide those behaviors. |
Some UCC fields intentionally force an ID search so they can follow the active model. For example, a Third Person Perspective Item resolves Spawn Parent and Holster Target by ID. Follow the owning feature’s page instead of assuming that its adjacent object-reference field overrides the ID.
Create a project ID
- Create a project-owned map with Assets > Create > Opsive > Ultimate Character Controller > Utility > NameIDMap. Keep this asset in version control so every team member uses the same names and numbers.
- Open Tools > Opsive > Ultimate Character Controller > Utility > Object Identifiers.
- Assign the project asset to Name Map. The packaged map remains available for the demo, but project roles should live in the project’s map.
- Select the target GameObject and add the Object Identifier component.
- Select the dropdown beside ID, enter a descriptive role such as
Rifle Spawn Parent, and select Add. The editor assigns the next unused ID beginning at10000; values below10000are reserved for Opsive demo content.
The first Add to a new NameIDMap asks where to save its editable CSV file. Save that CSV beside the map and version both files; the map reads its editable entries from the CSV. - Select the new name in the dropdown. The name is an editor aid; the component serializes and compares the numeric ID at runtime.
- In the consuming ability or ID/Object field, select or enter the same ID. For an ID/Object lookup, clear an old direct object reference unless the owning feature explicitly documents that it uses both.
- Save the scene or prefab. If this is a model-specific role, repeat the same name and ID on the equivalent GameObject in every model prefab.
An ID/Object field uses the same searchable popup. Select an existing entry, enter a valid name and choose Add, or choose Open Editor for the complete NameIDMap. In the utility window, Order By offers ID Ascending, ID Descending, Name Ascending, and Name Descending. Names and IDs must each be unique; sorting changes only their editor presentation.

The registered legacy image uses ID 106. For new project roles, use the project map’s generated IDs rather than copying an ID from this image or the demo.
Choose IDs and marker locations
Use positive project IDs
The Object Identifier component starts at ID 0. An IDObject<T> field, such as Spawn Parent or Holster Target, starts at -1, which means no ID lookup. Detect Object abilities also use -1 to disable their ID filter.
For new shared roles, use the map-generated range from 10000 through 2147483647. Object Identifier stores an unsigned value, but UCC’s ID/Object fields and Detect Object abilities store signed integers, so larger values cannot be represented consistently by every consumer. Avoid negative manual entries: the Object Identifier Inspector converts its integer input to an unsigned value.
The NameIDMap editor rejects a duplicate name or ID when adding or editing a project entry, but the runtime component does not enforce uniqueness. If two markers with the same ID exist in one searched parent or child hierarchy, an IDObject<T> resolves the first one returned by Unity. Reusing one ID on equivalent, mutually exclusive model prefabs is intentional; duplicating it within one active model is ambiguous.
Put the marker on the resolved component
An IDObject<T> finds a matching Object Identifier and then requests component T from that same GameObject. Put both components together. For example, a Transform target needs only the marker because every GameObject has a Transform; a custom component target needs that custom component beside the marker.
The search is limited to the parent or child hierarchy supplied by the consuming feature, including inactive GameObjects. It is not a scene-wide search. Place model-specific markers below the model or Item Slot that the field searches.
Reuse a role across character models
A runtime Character Item prefab can use one Spawn Parent ID to find the corresponding attachment below each model’s matching Item Slot. A Third Person Perspective Item can likewise use one Holster Target ID for an equivalent hip or back target on every model. When the active model changes, these item paths perform a fresh lookup in the new model.
Use the same positive role ID on each alternative model, but verify that each individual model contains exactly one matching marker. This lets the item prefab remain model-independent without storing a reference to one scene instance.
Filter a detected target
On an ability derived from Detect Object Ability Base, leave Object ID at -1 when the ID should not filter candidates. Set it to a project ID when the detected GameObject or one of its parents must contain a matching Object Identifier.
Detect Layers remains the first physics filter. A matching ID does not make a collider detectable when its layer, distance, trigger, angle, or ability-specific requirements reject it. See Detect Object Ability Base for the complete detection workflow.
How resolution runs
Object Identifier itself only exposes its numeric ID. For an ID/Object field, IDObject<T> performs the lookup:
- Unless the caller forces a search, it first returns a previously assigned or cached object.
- ID
-1returns no object. - The caller chooses a parent or child search and provides the root GameObject.
- UCC includes inactive GameObjects, compares marker IDs, and uses the first matching marker.
- It reads component
Tfrom the marker’s GameObject and caches the result. A failed search is cached too.
The cache avoids repeating hierarchy scans, but it also means a non-forced lookup does not notice a later-spawned marker, a changed ID, a replaced model, or a destroyed cached component. Built-in features that expect model changes can force a new search or call ResetValue(). Custom code must do the same when its hierarchy changes.
Detect Object abilities use a separate path: after physics finds a candidate, they check Object Identifier components on that GameObject and its parents. They do not use the generic IDObject<T> cache.
Editor checkpoint
Before entering Play Mode, confirm that:
- the project Name Map contains a descriptive, non-demo ID;
- the target has Object Identifier with the intended numeric ID;
- an ID/Object lookup has the required component on the same GameObject as the marker;
- the marker is inside the parent or child hierarchy searched by the owning feature;
- each active searched hierarchy has only one marker for that role;
- alternate models repeat the same semantic role and ID; and
- a Detect Object target also has a collider on a layer included by Detect Layers.
Verify in Play Mode
- Select the consuming component and enter Play Mode.
- Trigger the workflow that uses the reference. For an item prefab, equip and unequip it and confirm that its visible object uses the intended spawn or holster Transform.
- If the character supports model switching, change to every model and repeat the workflow. The item should resolve the equivalent target rather than remain on the previous model.
- For a Detect Object ability, approach one target with the matching ID and one without it. Confirm that Detected Object selects only the valid target while all other detection requirements are met.
- Disable or temporarily change the intended marker and repeat the test. The workflow should fail or use its documented fallback rather than silently resolve an unrelated duplicate.
Troubleshooting
| Symptom | Check | Fix |
|---|---|---|
| The wrong object is resolved. | Search the relevant parent or child hierarchy for duplicate IDs. UCC uses the first matching marker returned by Unity. | Give each role one match per active hierarchy. Reuse the ID only on alternative model prefabs. |
| The marker is found but the result is null. | The requested component may not be on the same GameObject as Object Identifier. | Move the marker to the component’s GameObject or add the required component there. |
| A runtime-spawned target is never found after an earlier miss. | IDObject<T> caches a failed lookup. |
Call ResetValue() or force the next search after changing the hierarchy. |
| Changing the ID during Play Mode has no effect. | Changing IDObject<T>.ID does not clear its cached value. |
Set the new ID, then call ResetValue() or perform a forced search. |
| An item remains attached to the previous model. | The next model may be missing the matching positive ID, or custom code may be reusing a cached result. | Add the equivalent marker to every model and reset or force the lookup on the model-change event. |
| A Detect Object ability rejects a correctly identified target. | Check Detect Layers, collider/trigger setup, distance, angle, and the concrete ability’s required target component. | Correct the detection setup; Object ID is an additional filter, not a replacement for it. |
| The Inspector shows a large unexpected number. | A negative value may have been entered into the Object Identifier’s integer control and converted to an unsigned ID. | Select a valid entry from the NameIDMap and use a positive value no larger than 2147483647. |
| The ID dropdown is empty or shows the wrong project names. | The Object Identifiers window may still reference the packaged or a deleted Name Map. | Open the utility window and assign the project’s NameIDMap. A deleted selection falls back to the packaged map. |
Related tasks
- Detect Object Ability Base configures layer, cast, trigger, angle, and Object ID filtering.
- Third Person Perspective uses identified spawn and holster targets for runtime Character Item prefabs.
- First Person Perspective explains first-person item objects and their model-specific references.
- Model Switch prepares equivalent slots and attachment roles across interchangeable models.
- Item Creation builds scene items and reusable Character Item prefabs.
Developer reference
ObjectIdentifier.ID is a uint and defaults to 0. IDObjectBase.ID is an int and defaults to -1. IDObject<T> exposes Obj, BaseObject, GetObjectInChildren, TryGetObjectInChildren, GetObjectInParent, TryGetObjectInParent, GetObject, TryGetObject, and ResetValue.
using Opsive.UltimateCharacterController.Objects;
using UnityEngine;
public class ModelAttachmentResolver : MonoBehaviour
{
[SerializeField] private IDObject<Transform> m_Attachment = new IDObject<Transform>();
public Transform Resolve(GameObject modelRoot, bool hierarchyChanged)
{
return m_Attachment.GetObjectInChildren(modelRoot, hierarchyChanged);
}
public void Invalidate()
{
m_Attachment.ResetValue();
}
}
With forceSearch set to false, an assigned object or any previous lookup result is returned from the cache. ResetValue() clears both the cached flag and cached object. Setting BaseObject during Play Mode changes the ID to -1 and marks the direct reference as cached; setting Obj directly does not perform that reset.
In released Version 3.2.0, TryGetObject returns true as soon as an ID matches, even when component T is missing from that marker’s GameObject and the output is null. Check both the Boolean result and the returned object, or use the GetObject... result and test it for null.
Object Identifier has no registration, lifecycle, event, save, or network code. Its serialized ID survives with its scene or prefab, and an ID/Object field can serialize an object assigned in Edit Mode. A reference found by a runtime hierarchy search and its cache are not persistent. Do not use the component as a persistent object key or assume that adding it synchronizes a spawned object.