Class GatheringNode
Gathering node interactable that grants items from a loot table when gathered. Tracks remaining uses and despawns when depleted. Configured via a GatheringNodeTemplate ScriptableObject asset.
[RequireComponent(typeof(SceneObjectNamer))]
public class GatheringNode : Interactable, ISpawnable, IGatheringNode, IInteractable, ISceneObject
- Inheritance
-
ObjectComponentBehaviourMonoBehaviourNetworkBehaviourGatheringNode
- Implements
- Inherited Members
-
NetworkBehaviour.IsSpawnedNetworkBehaviour.ComponentIndexNetworkBehaviour.NetworkObjectNetworkBehaviour.MAXIMUM_NETWORKBEHAVIOURSNetworkBehaviour.UNSET_NETWORKBEHAVIOUR_IDNetworkBehaviour.ToString()NetworkBehaviour.Reset()NetworkBehaviour.OnValidate()NetworkBehaviour.IsBehaviourReconcilingNetworkBehaviour.ClearReplicateCache()NetworkBehaviour.CreateReconcile()NetworkBehaviour.Reconcile_Reader<T>(PooledReader, ref T)NetworkBehaviour.OnStartServerCalledNetworkBehaviour.OnStartClientCalledNetworkBehaviour.OnStartNetwork()NetworkBehaviour.OnStopNetwork()NetworkBehaviour.OnStopServer()NetworkBehaviour.OnOwnershipServer(NetworkConnection)NetworkBehaviour.OnSpawnServer(NetworkConnection)NetworkBehaviour.OnDespawnServer(NetworkConnection)NetworkBehaviour.OnStartClient()NetworkBehaviour.OnStopClient()NetworkBehaviour.OnOwnershipClient(NetworkConnection)NetworkBehaviour.ClearBuffedRpcs()NetworkBehaviour.ExcludeOwnerFromUnbufferedObserversRpcsNetworkBehaviour.IsClientOnlyNetworkBehaviour.IsServerOnlyNetworkBehaviour.IsHostNetworkBehaviour.IsClientNetworkBehaviour.IsServerNetworkBehaviour.IsDeinitializingNetworkBehaviour.NetworkManagerNetworkBehaviour.ServerManagerNetworkBehaviour.ClientManagerNetworkBehaviour.ObserverManagerNetworkBehaviour.TransportManagerNetworkBehaviour.TimeManagerNetworkBehaviour.SceneManagerNetworkBehaviour.PredictionManagerNetworkBehaviour.RollbackManagerNetworkBehaviour.NetworkObserverNetworkBehaviour.IsClientInitializedNetworkBehaviour.IsClientStartedNetworkBehaviour.IsClientOnlyInitializedNetworkBehaviour.IsClientOnlyStartedNetworkBehaviour.IsServerInitializedNetworkBehaviour.IsServerStartedNetworkBehaviour.IsServerOnlyInitializedNetworkBehaviour.IsServerOnlyStartedNetworkBehaviour.IsHostInitializedNetworkBehaviour.IsHostStartedNetworkBehaviour.IsOfflineNetworkBehaviour.IsNetworkedNetworkBehaviour.GetIsNetworked()NetworkBehaviour.IsManagerReconcilingNetworkBehaviour.ObserversNetworkBehaviour.IsOwnerNetworkBehaviour.IsControllerNetworkBehaviour.HasAuthorityNetworkBehaviour.OwnerNetworkBehaviour.OwnerIdNetworkBehaviour.ObjectIdNetworkBehaviour.LocalConnectionNetworkBehaviour.OwnerMatches(NetworkConnection)NetworkBehaviour.Despawn(GameObject, DespawnType?)NetworkBehaviour.Despawn(NetworkObject, DespawnType?)NetworkBehaviour.Despawn(DespawnType?)NetworkBehaviour.Spawn(GameObject, NetworkConnection, Scene)NetworkBehaviour.Spawn(NetworkObject, NetworkConnection, Scene)NetworkBehaviour.RemoveOwnership()NetworkBehaviour.GiveOwnership(NetworkConnection)NetworkBehaviour.GetInstance<T>()NetworkBehaviour.TryRegisterInstance<T>(T)NetworkBehaviour.UnregisterInstance<T>()NetworkBehaviour.CanLog(LoggingType)MonoBehaviour.IsInvoking()MonoBehaviour.CancelInvoke()MonoBehaviour.StopCoroutine(Coroutine)MonoBehaviour.StopAllCoroutines()MonoBehaviour.destroyCancellationTokenMonoBehaviour.useGUILayoutMonoBehaviour.didStartMonoBehaviour.didAwakeMonoBehaviour.runInEditModeBehaviour.enabledBehaviour.isActiveAndEnabledComponent.GetComponent<T>()Component.TryGetComponent<T>(out T)Component.GetComponentInChildren<T>()Component.GetComponentsInChildren<T>()Component.GetComponentInParent<T>()Component.GetComponentsInParent<T>()Component.GetComponents<T>()Component.GetComponentIndex()Component.CompareTag(TagHandle)Component.transformComponent.transformHandleComponent.gameObjectComponent.tagObject.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.nameObject.hideFlags
Fields
AchievementTemplate
Achievement to increment when a player gathers from this node.
public AchievementTemplate AchievementTemplate
Field Value
Template
Template defining the drop table and gather parameters.
public GatheringNodeTemplate Template
Field Value
Properties
RemainingUses
Remaining uses before the node is depleted. Initialized from MaxUses on awake.
public int RemainingUses { get; set; }
Property Value
Remarks
Server state, and deliberately not on the wire. It used to ride the spawn payload — four bytes per node per observer — to answer a question a client cannot ask honestly: nothing refreshes it after the payload, so partial depletion was invisible to anyone already watching, and the only client use was a "> 0" test whose answer is implied by the node still existing (GatheringNodeAction despawns it on reaching zero). See AllowsGathering(int, bool).
Title
Display title shown above the gathering node.
public override string Title { get; }
Property Value
TitleColor
Title color for the gathering node UI label.
public override Color TitleColor { get; }
Property Value
- Color
Methods
AllowsGathering(int, bool)
The charge half of the gathering rule, as a pure function so it can be reasoned about and tested without a NetworkManager.
public static bool AllowsGathering(int remainingUses, bool chargesAreAuthoritative)
Parameters
remainingUsesintThe node's remaining charges.
chargesAreAuthoritativeboolTrue when this peer owns the charge count.
Returns
Remarks
Truth table:
- not authoritative, any count → true (the server answers)
- authoritative, count > 0 → true
- authoritative, count <= 0 → false
A peer that does not own the count does not get to answer with it. The count is not replicated — it moves whenever anyone gathers, and there is no message that carries the new value — so a client asking it would be asking a number frozen at whatever it held when the node was spawned.
CanInteract(IPlayerCharacter)
Returns true if the specified player character may interact with this object.
public override bool CanInteract(IPlayerCharacter character)
Parameters
characterIPlayerCharacterThe player character attempting to interact.
Returns
- bool
True if interaction is allowed, false otherwise.
Remarks
A pure question with no side effects. It used to stamp the character's interact rate-limit as part of answering, which made it unusable as a check: the scene server, the quest system and the client's input handler all call it, and each call silently consumed a limiter meant for one of the others. A quest accepted within the limiter's window of the interaction that opened the dialogue was refused by a debounce nobody intended to spend, and the refusal path sends nothing back — so the player saw a dead keypress. Spend the limiter explicitly with TryConsumeInteractRateLimit(IPlayerCharacter).
OnAwake()
Called when the object is awakened. Override to implement custom initialization logic.
public override void OnAwake()
ResetState(bool)
Restores the node's charges when this instance returns to the pool.
public override void ResetState(bool asServer)
Parameters
asServerboolTrue when the reset is for the server instance.
Remarks
OnAwake() is where RemainingUses is seeded, and Unity calls Awake once per instance — not once per spawn. A pooled node therefore came back out of the pool with the zero its previous life ended on, and CanInteract(IPlayerCharacter) refuses a node with no uses left: every gathering node in a scene became permanently depleted the first time it was exhausted, for the remaining life of the server process.