3

Upcoming: Cached APIs

This is a very technical feature and requires a good understanding of how Sansar’s APIs work. The extremely high level view is that scripts should throw “NullReferenceException("Null internal reference.")” much less often when accessing AgentInfo data.

Every Sansar API has two parts - a C# interface and an internal C++ “backing”. While the lifetime of the C# interface is managed by C#’s garbage collection, the C++ “backing” is more actively managed. This leads to cases where the C# interface is still alive but the C++ “backing” has been cleaned up. In these cases the script will throw a “NullReferenceException("Null internal reference.")” and, unless caught, will crash the script.

The most common example of this is for users in the scene. Their AgentPrivate and AgentInfo interfaces each have a C++ backing that is gone after the user leaves the scene; however it is quite easy for a script to hold onto either one of these long after the user has left. Calling any property or method on either after the agent has left will throw a NullReferenceException.

At the same time most of the data in AgentInfo does not change, and there is little reason to query the C++ backing on every access. For these APIs we will now cache their values. This means you can hold onto an AgentInfo and use it without throwing an exception even after the user leaves the scene. This should remove the largest case of “Null Internal Reference” errors.

Cached APIs are:

AgentPrivate.AgentInfo
AgentPrivate.Client

AgentInfo.Name
AgentInfo.AvatarUuid
AgentInfo.ObjectId
AgentInfo.SessionId

Client.UI
Client.AgentInfo

SoundResource.GetName()
SoundResource.GetDuration()

Extra details and warnings

As I mentioned above this is a technical feature and there are some important things to note.

  • For the more complex types (Client, UI) any APIs that are not cached will still throw Null Internal Reference exceptions if used. Don't try to send a modal dialog or teleport a logged off user.
  • ObjectId and SessionId are unique to a session. These values are cached and not updated on relog. Once the user logs out their old SessionId and ObjectId are no longer meaningful but referencing them will no longer throw an exception. That said other APIs that take SessionId or ObjectId will not work with their values after the user leaves, even if they return. The script must get a new AgentInfo to get the current ObjectId and SessionId after the user has relogged.
  • All interface objects (AgentPrivate, AgentInfo, etc.) now have an IsValid() member method. This can be used to verify that an interface C++ backing is gone: once an interface C++ backing is gone it is never “coming back” for that interface. Due to timeslicing it is not a 100% guarantee that the interface is still there even on the next line of code after calling IsValid(). Use with caution.
  • In general it is still best practice to wrap Agent related APIs in try/catch blocks, but if all you need to do is get some names or ids it should be safe to do that without worrying about the user leaving the scene mid loop.

0 comments

Please sign in to leave a comment.