Spatial Awareness System
The Spatial Awareness System is used as part of the Seamless world implementation.
Overview
A spatial awareness system is a server-side system that is used to track the relative position and awareness of entities in 3D space. Entities specify a range at which they become "aware" of other entities. For example, a player keeps track of which other players and creatures/NPCs are close by. Ones beyond that range are ignored to reduce bandwidth and other resource burdens.
The system is created by creating a node of the class _SpatialAwarenessSystem
in the GOM. This class has the required fields which control what entities are in the system, where they are, and which nodes receive events as each becomes cognizant of an entity entering or leaving its awareness.
The Spatial Awareness System is an integral component of the replication system, but can also be used independently of it for your own needs. One example might be a creature spawn system where "spawners" go to sleep when no players are close enough to warrant introducing new creatures in that region.
What problem(s) does this solve?
- High speed "awareness" for entities based on positions in 3D space
- Provides the Dude Server with positional information for use in prioritizing and shaping traffic via Replication
What problems does this not solve?
- Is Not AI, being "aware" does not translate into actions without additional code
Concepts
- A spatial awareness system is represented as a node in an area's GOM, providing an easy to use and familiar interface from HSL
- Entities in an awareness system are abstract concepts, they may represent a particular player or npc but they might also represent less concrete things. The ID of an Entity may be the same as the ID of a node, but does not have to be.
- The fundamental awareness system for areas is the system node $SPATIALAWARENESS_AREA, this awareness is by default in charge of managing the introduction of players and npcs to a client. This awareness system replaces behaviors formerly implemented in the C++ Character Command Center.
- There are four types of events generated by the Spatial Awareness System
- Appeared - Entity is within the subject's awareness at the time it is added to the system
- Entered - Entity has entered the awareness range of the subject
- Disappeared - Entity disappeared from the subject's awareness by virtue of being removed from the awareness system
- Departed - Entity has left the awareness range of the subject
- $SAS is a system node supporting some useful utilities for working with spatial awareness systems
Update frequency
An awareness system has an update frequency specified during initialization, which may be as low as the server's frame. This means that changes to entity position are slightly delayed until the next time the awareness system processes any updates and issues notification to script. A consequence of the update frequency is that it is possible for an entity to enter and leave a subject's awareness without any events being generated if the entity travels fast enough to go through the entire range of awareness between updates.
Awareness range
When an entity is added to an awareness system, a range (in units) may be specified for the entity. This is the "awareness range" for that entity. Entities that have awareness ranges specified will generate spatial awareness related events to the nodes specified to receive those events. It is valid for an entity to have an awareness range of zero, in which case other entities will be aware of it but it will be unaware of them.
Hysteresis
One of the common issues for awareness mechanics in any engine is that users will invariably perform actions (top right image: the following events would be raised; leave, enter, leave, enter, leave) that will result in repeatedly entering and leaving awareness range resulting in unnecessary processing and communication traffic. There are a variety of methods devised to minimize the effects from the introduction of latency to the system to the addition of a secondary range that must be exceeded before the user is considered to have "left" an entity's awareness.
For HeroEngine's implementation of awareness, hysteresis refers to the secondary range solution to the problem. The hysteresis value expresses a range in units beyond the inner awareness range that must be exceeded for a "leave" event to trigger.
With the addition of a hysteresis range (bottom right image), no additional events are generated by the player as their path moves in/out of the awareness range because they never exceed the hysteresis range.
Latency
Latency can be thought of as a secondary level of hysteresis that instead of being distance based is time based. Events that would generally be generated are instead delayed by a period of time specified by the latency and if a subsequent event would result in a net no-change then no events are generated.
For example, assume a latency of 0.5 seconds and a player that moves infinitely fast. The entity (starting from outside the subject's awareness) can enter/leave the awareness as often as it wanted to do so and as long as they ultimately end up outside the awareness at the end of the latency period no events would be generated.
Usage
Creating an Awareness System
Spatial Awareness Systems are represented as nodes in the local Server's GOM which are created from a class _SpatialAwarenessSystem or is a child of that class and which is of the Archetype SPATIAL_AWARENESS_SYSTEM
. Instantiation of the spatial awareness system is accomplished either by explicit instantiation at runtime (i.e. CreateNodeFromClass() etc) or via the system node mechanics. The MMO Foundation Framework uses the system node route for the fundamental awareness system for areas $SPATIALAWARENESS_AREA.
Create a custom awareness system:
- Using the DOM Editor Create a server class FooAwareness
- set the Archetype to
SPATIAL_AWARENESS_SYSTEM
- add the class _SpatialAwarenessSystem as a parent
- set the Archetype to
- Instantiation of a awareness node
- Call $SAS's _createSASFromClass method
- OR Create as a System Node
// Note the variables are declared explicitly for the purposes of illustration // normally you could just pass the values into the method directly... sasName as string = "Foo" sasClass as string = "FooAwareness" updateRate as float = 1.0 active as boolean = true hysteresis as float = 1.0 latency as float = 0.03 var mySAS = $SAS._createSASFromClass( sasName, sasClass, updateRate, active, hysteresis, latency )
Adding an Entity to an Awareness System
An entity for the purposes of spatial awareness is represented by a class of information (_SAS_EntityInformation) mapped to a unique ID containing the following information:
- _SAS_EI_position
- _SAS_EI_awareness
- _SAS_EI_event_receiving_nodes
- optionally _SAS_EI_hysteresis_factor
Entities in an awareness system do not necessarily represent a physical object, nor even a node in the local GOM. As a general rule, it is useful to use the same ID for an entity as the node (when one exists) for which the entity represents a spatial position. Once added to an active awareness system, the entity's event receiving nodes will recieve script callbacks for any events that occur.
// assume you have a reference to your spatial awareness system // assume a noderef wantsEvents has a reference to a node that wants to receive // events related to this entity e as class _SAS_EntityInformation e._SAS_EI_position = thePos e._SAS_EI_awareness = 6.0 add back wantsEvents to e._SAS_EI_event_receiving_nodes mySas._SAS_AddEntity( entityID, e )
If a node exists with the same ID as the entityID specified for addition, that node will receive a call to the method SAS_OnAddEntityToAwarenessSystem if it is implemented.
// Event generated by the _SpatialAwarenessSystem's _SAS_AddEntity method _SAS_OnAddEntityToAwarenessSystem( awarenessSystem as NodeRef of Class _SpatialAwarenessSystem ) // Parameters: // awarenessSystem - reference to the awareness system to which an entity representing this node (using its ID) has been added .
Update Entity Position
Entity positions in awareness systems do not update automatically when the position of a node for which the entity is acting proxy changes. A system must explicitly update the entity position in all of the awareness systems in which the entity exists (if it matters...).
// assume you have a reference to your spatial awareness system mySAS._SAS_UpdateEntityPosition( entityID, newPos )
The $SAS system node has a utility function to update the position of a particular entity ID in all spatial awareness systems in which it exists. However, for high frequency updates it is greatly preferred that you update the awareness systems that require the updates at that frequency directly rather than use the shotgun approach of the method _SAS_UpdateEntityPositionForAllAwarenesses()
$SAS._SAS_UpdateEntityPositionForAllAwarenesses( entityID, newPos )
Remove Entity From an Awareness System
Removing an entity from the awareness system is quite simple.
sas._SAS_RemoveEntity( entityID )
If a node exists with the same ID as the entityID specified for removal, that node will receive a call to the method _SAS_OnRemoveEntityFromAwarenessSystem if it is implemented.
// Event generated by the _SpatialAwarenessSystem's _SAS_RemoveEntity method _SAS_OnRemoveEntityFromAwarenessSystem( awarenessSystem as NodeRef of Class _SpatialAwarenessSystem ) // Parameters: // awarenessSystem - reference to the awareness system to which an entity representing this node (using its ID) has been removed .
Querying Spatial Awareness
Spatial awareness systems expose a variety of querys for working with their understanding of 3D space and the entities contained therein. While the queries are all available via external functions, we recommend you use the methods exposed on the spatial awareness node itself instead of calling the external function.
For the purposes of the naming of these functions:
- Subjects are targets of awareness, entities are aware of subjects. This means that when you ask a question:
- Who all am I aware of, you are asking as an entity what subjects are known to me. (_SAS_QueryByEntity)
- Who is aware of me, you are asking as a subject what entities know about me. (_SAS_QueryBySubject)
List Entities that are Aware of a Subject
This method will provide a list of the entities that are aware of a subject (i.e. the specified entity), it does not include the subject as being aware of itself.
// Populate a list passed by reference with the entities that are aware of me (based on the entity representing the _playerAccount node) entitiesThatAreAwareOfIt as list of id $SPATIALAWARENESS_AREA._SAS_QueryBySubject( myAccountID, entitiesThatAreAwareOfIt )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for external function _SAS_Query_By_Subject // From the perspective of a subject entity, List all entities that are aware of it. Results do not include the supplied entity. // i.e. Who all knows about me method _SAS_QueryBySubject( subject as ID, entitiesThatAreAwareOfIt references List of ID ) as Integer // Parameters: // subject - ID of the entity for whom we wish a list of entities that are aware of it // Returns: // entitiesThatAreAwareOfIt - (by reference) list of entities that are aware of entityID, does not include subject // count - number of entities that are aware of it return _SAS_Query_By_Subject( me, subject, entitiesThatAreAwareOfIt ) .
List Subjects Known to an Entity
This method will provide a list of the entities known to a specified entity, it does not include the entity as being aware of itself.
// Populate a list passed by reference with the entities of which I am aware (based on the entity representing the _playerAccount node) subjectsKnownToIt as list of id $SPATIALAWARENESS_AREA._SAS_QueryByEntity( myAccountID, subjectsKnownToIt )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Query_By_Entity // List all subject entities that are known to a particular entity // i.e. Who all do I know about method _SAS_QueryByEntity( entity as ID, subjectsKnownToIt references List of ID ) as Integer // Parameters: // entity - ID of the entity for whom we wish a list of subjects that are known to it // Returns: // subjectsKnownToIt - (by reference) list of subject entities that are known to the entity, does not include entity itself // count - number of entities that are known to it return _SAS_Query_By_Entity( me, entity, subjectsKnownToIt ) .
Are all Subjects Known to an Entity
Given a list of subjects, test whether an entity is aware of all of them. During game play, you might use this capability to only send information to the client if the client is aware of all of the parties(subjects) involved.
// assume myGroup contains a list of group memebers and that I only want to execute Foo when all of my group // is within my awareness if $SPATIALAWARENESS_AREA._SAS_TestSubjectList( myGroup, myAccountID ) account.Foo() .
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Test_Subject_List // Are all of the subjects known to the entity, for the purpose of this query it considers the entity aware of itself method _SAS_TestSubjectList( subjects as List of ID, entity as ID ) as Boolean // Parameters: // subjects - list of subject entities for which you wish to know if tne specified entity is knows about all of them // entity - entity whose knowledge of subjects you wish to test // Returns: // knowsAll - boolean indicating whether or not all subjects are known return _SAS_Test_Subject_list( me, subjects, entity ) .
List Entities Aware of Two Subjects
Given two subjects, gather a list of entities that are aware of both subjects. This query is often used to transmit visual results only to clients that are aware of both subjects, as the visualization would not make sense if only one subject was known.
entitiesAwareOfBoth as list of id $SPATIALWARENESS_AREA._SAS_QueryByTwoSubjects( target1, target2, entitiesAwareOfBoth )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Query_By_Two_Subjects // What entities know about both subjects. Commonly used to know who can "see" the interaction between two spatial entities. Considers // each subject aware of itself. method _SAS_QueryByTwoSubjects( subject1 as ID, subject2 as ID, entities references List of ID ) as Integer // Parameters: // subject1 - first subject for whom we wish to test which entities are aware of it // subject2 - second subject for whom we wish to test which entities are aware of it // Returns: // entities - (by reference) list of entities aware of both subject1 and subject2 // count - number of entries in the entities list return _SAS_Query_By_Two_Subjects( me, subject1, subject2, entities ) .
Example
Often when an interaction occurs between two characters, the clients that can see the interaction need to be notified. The method _SAS_QueryByTwoSubjects serves this purpose by providing the list of entities that can see both characters.
function attack( attacker as id, victim as id ) observers as list of id $SPATIALAWARENESS_AREA._SAS_QueryTwoSubjects( attacker, victim, observers ) foreach obs in observers oClient as NodeRef of Class _PlayerAccount = obs if oClient != None call client oClient example:ShowAttack( attacker, victim ) . . .
When an interaction occurs between more than two characters, notification becomes more complicated. Various approaches can be taken, but here is one that uses _SAS_ExcludeUnawareByEntity to avoid sending character references to clients that they don't know about.
function ChainLightning( attacker as noderef, victims as list of id) observers as list of id $SPATIALWARENESS_AREA._SAS_QueryBySubject( attacker, observers) foreach obs in observers oClient as NodeRef of Class _PlayerAccount = obs if oClient != None var seen = victims if $SPATIALAWARENESS_AREA._SAS_ExcludeUnawareByEntity( obs, seen) call client obs example:ShowChainLightning( attacker, seen ) . . . .
List Entities that are Aware of All Subjects
Assemble a list of all entities that are aware of all of the specified subjects.
// assume you have a list of subject ids entitiesThatAreAwareOfAllSubjects as list of id $SPATIALAWARENESS_AREA._SAS_QueryBySubjectsList( subjects, entitiesThatAreAwareOfAllSubjects )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Query_By_Subject_List // What entities know about all of the subjects. Considers each subject aware of itself method _SAS_QueryBySubjectList( subjects as List of ID, entitiesThatAreAwareOfAllSubjects references List of ID ) as Integer // Parameters: // subjects - list of subject entities for whom we wish to test which entities are aware of all of them // Returns: // entitiesThatAreAwareOfAllSubjects - (by reference) list of entities aware of all subjects // count - number of entities in entities list return _SAS_Query_By_Subject_list( me, subjects, entitiesThatAreAwareOfAllSubjects ) .
List Subjects Known By all Entities
For a list of entities, assemble a list of subjects that are known in common by all of those entities.
// assume you have a list of entities for which you wish to know the intersection of known subjects subjectsKnownByAllentities as list of id $SPATIALAWARENESS_AREA._SAS_QueryByEntitiesList( entities, subjectsKnownByAllentities )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Query_By_Entities_List // What subjects are known by all of the entities. This is the complement to _SAS_QueryBySubjectList method _SAS_QueryByEntitiesList( entities as List of ID, subjectsKnownByAllEntities references List of ID ) as Integer // Parameters: // entities - list of entities for whom we wish to test what subjects are known to all of them // Returns: // subjectsKnownByAllEntities - (by reference) list of all subjects known by all of the entities // count - number of entries in the subjectsKnownByAllEntities list return _SAS_Query_By_Entities_List( me, entities, subjectsKnownByAllEntities ) .
Exclude from a List any Entities that are Unaware of a Subject
Given a list of entities, remove any entities that are unaware of the subject.
// Given a list of group members, remove any that are unaware of me $SPATIALAWARENESS._SAS_ExcludeUnawareBySubject( myAccountID, myGroupMembers )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Exclude_Unaware_By_Subject // Remove entities from the entities list that don't know about the subject. Considers the subject to be aware of itself. method _SAS_ExcludeUnawareBySubject( subject as ID, entities references List of ID ) as Boolean // Parameters: // subject - subject entity for which we wish to remove any entities from the entities list that are not aware of it // entities - list of entities we wish to test for knowledge of the subject. The list is modified to remove any entities // unaware of the subject // Returns: // anyoneAware - boolean indicating if any entities remain return _SAS_Exclude_Unaware_By_Subject( me, subject, entities ) .
Exclude from a List any Subjects of Which an Entity is Unaware
Given a list of subjects, remove any subjects in that list of which the entity is unaware.
// Given a list of group members, I want to remove any group members of which I am not aware $SPATIALAWARENESS_AREA._SAS_ExcludeUnawareByEntity( myAccountID, myGroupMembers )
The implementation found in _SpatialAwarenessSystemClassMethods is detailed below:
// Wrapper for the external function _SAS_Exclude_Unaware_By_Entity // Removes any subjects in the subject list of which the entity is not aware. Considers the entity aware of itself method _SAS_ExcludeUnawareByEntity( entity as ID, subjects references List of ID ) as Boolean // Parameters: // entity - entity for which we wish to remove any subjects of which the entity is not aware // subjects - list of subjects for which we wish to test knowledge of them for the specified entity. The list is modified to remove // any subjects of which the entity is unaware // Returns: // awareOfAny - boolean indicating whether or not any subjects remain in the list that the entity is aware of return _SAS_Exclude_Unaware_By_Entity( me, entity, subjects ) .
MMO Foundation Framework Usage
The MMO Foundation Framework has been updated to replace functionality previously supported by the C++ Character Command Center related to the introduction and awareness of characters/npcs by a client. Consequently, there are numerous hooks throughout the framework code that manipulate the basic spatial awareness system $SPATIALAWARENESS_AREA to update entity information including introduction/removal and positional updates. In combination with Replication, it is these mechanics that support the ability of a client to visualize characters.
This section will address how the MMO Foundation Framework handles:
- Instantiation of a Spatial Awareness System
- Introduction
- Updates
- Removal
Instantiation of a Spatial Awareness System
The MMO Foundation Framework uses the mechanics of System Nodes to handle the instantiation of the fundamental spatial awareness system for areas ($SPATIALAWARENESS_AREA). The system node mechanic was used primarily for ability to easily reference the awareness system in script and the automatic instantiation of the awareness from a prototype (as a singleton) with default values set (such as the update frequency and the active boolean set to true so it is immediately live).
Introduction
The MMO Foundation Framework handles the introduction of a new player entity to the $SPATIALAWARENESS_AREA awareness in two stages. Stage one determines the entities the player is aware of before they become aware of the player. Stage two introduces the now ready player to any entities that should be aware of him/her.
Stage One - Introduction of a Dummy Entity
Stage one introduces a dummy entity to act as a proxy for the account allowing the client to be notified (via replication) of the data that it will need to know immediatley upon completion of the login process (i.e. the entities closest to them). Due to the fact a dummy is used, other entities are notified of the addition of a dummy to their awareness but because the dummy is not an account or character they ignore it.
This stage occurs during the _AccountClassMethods callback method _ClientReady once the client has indicated it is now ready for replication and remove call traffic. The dummy entity mechanics are supported by the _SAS_Entity class, a parent of the _playerAccount class.
account._SAS_AddProxyEntityToAwarenessSystem( $SPATIALAWARENESS_AREA, 7.0, account.GetPosition())
Stage Two - Introduction of the Player
Once the client has indicated it is ready to activate the character, the dummy entity is replaced by an entity for the player which ultimately results in interested clients adding themselves to the player's replication group. This functionality is found in the _AccountClassMethods callback _CharacterActivated.
During this call:
- Register an entity for the player
- Remove the dummy entity from stage one
Asynchronously following addition of the player entity:
- Interested entities representing other players add themselves as client destinations to the new player's replication group
Register an entity for the player
The _ACCControllerOwner class is told to register a spatial entity in the system for the player.
// _accountClassMethods // Activate the character in spatial awareness char._RegisterACCCWithSpatialAwareness()
The default behavior of the _ACCControllerOwner implement is to add an entity to the awareness system using the accountID (for players) as the entityID with an awareness range of 70 meters. This entity has the _playerAccount node as the node that will receive spatial awareness related events.
// _accControllerOwnerClassMethods // Add this character to the previously specified spatial awareness system method _RegisterACCCWithSpatialAwareness() if me._acccSpatialAwareness <> None e as Class _SAS_EntityInformation // Use the range of 70 meters as the awareness range e._SAS_EI_awareness = 7.0 e._SAS_EI_position = me.GetPosition() // The entity ID and the event receiver node is the npc node or the _playerAccount node if me is kindof _playerCharacter add back me.getmyAccount() to e._SAS_EI_event_receiving_nodes me._acccSpatialAwareness._SAS_AddEntity( me.getmyAccount(), e ) else add back me to e._SAS_EI_event_receiving_nodes me._acccSpatialAwareness._SAS_AddEntity( me, e ) . . .
Interested Client Entities Add Themselves as Replication Destinations
Upon addition of the player's entity to the awareness system, nearby entities will receive notification (asynchronously due to the latency imposed by the update frequency of the awareness system) them of the appearance of a new entity. For those entities representing players, they add themselves to the new player's replication group causing that player's character data (appearance) to be replicated to them.
// _playerAccount class methods script method _SO_appeared( awarenesssystem as ID, entity_ID as ID, subject_ID as ID) handled as Boolean if HasMethod(me,"HE_SO_appeared") handled = me.HE_SO_appeared(awarenesssystem, entity_ID, subject_ID) . sas as NodeRef of Class _SpatialAwarenessSystem = awarenessSystem if not handled subject as NodeRef = subject_ID if subject <> None where subject is kindof _playerAccount subject._getReplicationGroup(true)._addClientDestination(me,me) . // some _nonPlayerCharacter related code removed... . . . .
By default, the addition of a client destination results in the replication of the new player's _playerAccount, _playerCharacter, _accController and _characterAppearance nodes to the client causing the character to appear.
Entity Updates
The major update performed on entities of a spatial awareness system is to the position of the entity. The MMO Foundation Framework performs this update when the Advanced Customizable Character Controller HeroEngine_ACCController updates its position via the _setACCControllerPosition method. This results in an method call to _UpdatePosition on the controller's owner (the _playerCharacter or _nonPlayerCharacter node) to update the entity in the $SPATIALAWARENESS_AREA awareness and the _characterAppearance node's position.
// _ACCControllerOwner class methods // Updates the position in the previously specified spatial awareness system method _UpdatePosition(position as Vector3) me.getMyVisibleCharacter().character_position = position // The entity ID is either this node in the case of npcs, or the account node in the case of player characters spatialEntity as ID = me if me is kindof _playerCharacter spatialEntity = me.getMyAccount() . // This notification will not add this character to spatial awareness, only update the position if me._acccSpatialAwareness <> None me._acccSpatialAwareness._SAS_UpdateEntityPosition( spatialEntity, position ) . .
Removal
During the _ExitingArea callback to the $ACCOUNT system node, the _ACCControllerOwner class receives a call to its _UnregisterACCCFromSpatialAwareness method to remove the entity representing the account from the $SPATIALAWARENESS_AREA awareness system. It is important to understand that the disappear event will be asynchronous called later to notify any entities that were aware of the player that the player is gone, at the time of the callback the _playerAccount node has already been unloaded so you can not access it. In addition to removing the entity representing the player, a call is made to remove any dummy proxy entities that might have been created for the _playerAccount.
// _AccountClass Methods in _ExitingArea method // Remove the character from the spatial awareness system char._UnregisterACCCFromSpatialAwareness() // Remove any proxies that were created account._SAS_RemoveAllProxyEntities()
Advanced Usage
Debugging
Spatial awareness systems support some generic debugging capabilities that are generally accessed via $SAS's chat command /hesas.
Displaying Entity Position
/hesas debug [sasName|sasID] subscribe
Spatial awareness systems support a basic level of debugging that displays the position of entities in the system as semi-translucent spheres. Each sphere represents a single entity in the system which may or may not correspond to characters that are being visualized on your client. Each sphere is color coded based on whether or not the entity representing you is aware or unaware of them.
- Red - You are unaware of this entity
- Blue - That's you
- Green - You are aware of this entity
To display the default area level spatial awareness simply type in the chat panel:
/hesas debug area subscribe
Proxy (Dummy) Entities
![]() |
We often call proxy entities dummys because while they exist as entities (and in this implementation nodes), they don't themselves actually listen for or respond to events from spatial awareness. They exist purely to provide an additional position and awareness range for which event receiving nodes can get spatial awareness events |
There are a variety of engine and game mechanics that might require that a particular entity have more than one area of awareness in a spatial awareness system. Additional areas of awareness are represented by the addition of proxy or sometimes call dummy entities to the spatial awareness system.
Examples of this functionality can be found in the HeroBlade when in "EDIT" mode, the _playerAccount creates a dummy entity to represent the position of the FLY camera. Without the existence of a dummy entity, characters/npcs are not introduced to the client if the user flys the camera beyond the range of the awareness based on their character's location.
Dummy entities do not normally respond to events from the spatial awareness system (i.e. the dummy node itself is not normally added as an event receiving node), rather they exist merely to represent an alternate position in the awareness system and forward events to their "owner".
A helper class _SAS_Entity supports the functionality for the creation and use of dummy(proxy) entities, and is a parent class of _playerAccount.
Creating a Proxy Entity
Assuming you are using the _SAS_Entity implementation, dummy entities are created from the class _SAS_DummyEntity by calling the _SAS_AddProxyEntityToAwarenessSystem method. The creation method returns a reference to the dummy entity which you may choose to store for future reference.
// assume a reference to the _SAS_Entity, most commonly used for the _playerAccount node var dummy = account._SAS_AddProxyEntityToAwarenessSystem( $SPATIALAWARENESS_AREA, 7.0, account.GetPosition())
Listing Proxy Entities
Assuming you are using the _SAS_Entity implementation, listing all dummy entities for an entity is a simple method call to _SAS_ListProxyEntities().
// assume a reference to the _SAS_Entity, most commonly used for the _playerAccount node account._SAS_ListProxyEntities()
Removing Proxy Entities
Assuming you are using the _SAS_Entity implementation, two methods expose the functionality of removing proxy entities for a particular entity. One to remove a specific proxy, and the other to remove all proxies. During the callback _ExitingArea to the $ACCOUNT system node, a call is made to remove all of the proxy entities for the _playerAccount node.
Remove Specific Proxy
// assume a reference to the _SAS_Entity, most commonly used for the _playerAccount node account._SAS_RemoveProxyEntityFromAwarenessSystem( $SPATIALAWARENESS_AREA, dummy )
Remove all Proxy Entities
account._SAS_RemoveAllProxyEntities()
Updating Proxy Position
Proxy entities have a method intended for use in updating their position as well as their position in any spatial awareness systems in which they exist as an entity.
// Assuming you kept a reference to the proxy dummy._setSASDummyEntityPosition( pos )
Reference
External Functions
Various external functions are available on the server to query the state of entities in the spatial awareness system, it is however recommended that you not call these directly and instead use the wrapper methods implemented in the _SpatialAwarenessSystem class methods script instead.
// Who all knows about me. The results do not include the subject. external function _SAS_Query_By_Subject( SAS as NodeRef, subject_ID as ID, entity_list references List of ID) as Integer // Who all do I know about. The results do not include the entity. external function _SAS_query_by_Entity( SAS as NodeRef, entity_ID as ID, subject_list references List of ID) as Integer // Not intended for production use. Dumps total awareness state in parallel lists. external function _SAS_query_all( SAS as NodeRef, entity_list references List of ID, subject_list references List of ID) as Integer // List all Spatial Awareness Systems external function _SAS_System_List( sasList references List of ID ) as Integer // Are all of the subjects known to the entity. Considers the entity aware of itself. external function _SAS_Test_Subject_list( SAS as NodeRef, subject_list as list of ID, entity_ID as ID) as Boolean // What entities know about both subjects. It is common to need to know who can see the interaction between two // spatial entities. Considers each subject aware of itself. external function _SAS_Query_By_Two_Subjects( SAS as NodeRef, subject1 as ID, subject2 as ID, entity_list references List of ID) as Integer // What entities know about all of the subjects. Considers each subject aware of itself. external function _SAS_Query_By_Subject_List( SAS as NodeRef, subject_ID as List of ID, entity_list references List of ID) as Integer // What subjects are known about by all of the entities. This is the complement of _SAS_Query_By_Subject_List. external function _SAS_Query_By_Entities_List( SAS as NodeRef, entity_list as List of ID, subject_list references List of ID) as Integer // removes elements from the entity_list which don't know about the subject. Considers the subject aware of // itself. Returns true if any know about the subject. external function _SAS_Exclude_Unaware_By_Subject( SAS as NodeRef, subject_ID as ID, entity_list references List of ID) as Boolean // removes elements from the subject_list which the entity doesn't know about. Considers the entity aware of // itself. Returns true if the entity knows about any. external function _SAS_Exclude_Unaware_By_Entity( SAS as NodeRef, entity_ID as ID, subject_list references List of ID) as Boolean
Spatial Awareness Events
The following methods are called on the event receiving nodes in response to conditions detected by the spatial awareness system.
HSL | Description |
method _SO_entered(awarenesssystem as ID, entity_ID as ID, subject_ID as ID) |
Called on nodes in the list field _SAS_EI_event_receiving_nodes when the entity is informed that a subject has entered its awareness. In the case of an entity suddenly appearing (just added to the system, logged in, was just created etc) the appeared event is called instead. |
method _SO_departed(awarenesssystem as ID, entity_ID as ID, subject_ID as ID) |
Called on nodes in the list field _SAS_EI_event_receiving_nodes when the entity is informed that a subject has departed (left) from its awareness. In the case of an entity suddenly disappearing (deleted, removed from the system, logged off) the disappeared event is called instead. |
method _SO_appeared(awarenesssystem as ID, entity_ID as ID, subject_ID as ID) |
Called on nodes in the list field _SAS_EI_event_receiving_nodes when the entity is informed that a subject has appeared (just added due to node creation, login etc) suddenly in its awareness range. |
method _SO_disappeared(awarenesssystem as ID, entity_ID as ID, subject_ID as ID) |
Called on nodes in the list field _SAS_EI_event_receiving_nodes when the entity is informed that a subject has disappeared suddenly from awareness (node deletion, logoff etc) |
method _SAS_FailedEventNotificationForNodeID(entity_ID as ID, nodeID as ID) |
Called when a notification for an entity failed because the node that wished to receive notification does not exist. Provides the opportunity to remove from the list of event receiving nodes, toss an error, etc. |
Class _SpatialAwarenessSystem
Field name | Field type | Description |
_SAS_update_period | Float | Minimum time (in game seconds) between checks to update. As the area server can be configured to have a resolution of frame time, this time is adjusted to be at least that long, and rounded up in the general case. If there is a long frame, cie la vie, the update will occur beyond this minimum time. if a value of zero is chosen, then effectively the update might occur every frame. |
_SAS_latency | Float | Latency (in seconds) of event delivery. |
_SAS_hysteresis | Float | The amount of distance an entity must be "outside" the awareness before an event is generated that the entity has left the build. |
_SAS_active | Boolean | Controls whether the events and updates will be processed. |
_SAS_entities | LookupList indexed by ID of Class _SAS_EntityInformation | Information about each entity in the system. |
_SAS_name | String | Name of the system for debugging purposes. |
_SAS_DebuggingEnabled | Boolean | Controls if debugging is enabled. |
_SAS_DebuggingTimer | Timer | Timer used to initiate debugging events. |
Class _SAS_EntityInformation
Field name | Field type | Description |
_SAS_EI_position | Vector3 | Current position of entity. |
_SAS_EI_awareness | Float | Range of awareness of entity. |
_SAS_EI_event_receiving_nodes | List of NodeRef | List of nodes receiving the events about awareness state changes |
_SAS_EI_Hysteresis_Factor | Float | Entity-specific granularity of hysteresis. The entity's change in hysteresis from the default (as a multiplicative factor where -1.0 = no hysteresis, 0 = default hysteresis, fulfilling the equation 'effective_hysteresis = (hysteresis_factor + 1)*default_hysteresis |