Script API Updates

Script API updates

Latest update

Update: September 10, 2019

Script updates

  • AgentPrivate.IgnoresCollisionWith(RigidBodyComponent)

    • Specifies that a particular user will ignore collisions with a particular body. Additionally, some interactions like sitting, camera collision, and teleporting coming from that user will also ignore the body.

  • AgentPrivate.IsCollisionIgnoredWith(RigidBodyComponent)

    • Returns whether a specified RigidBodyComponent has been set to be ignored by the Agent.

  • AgentPrivate.SetSpeedFactor(float)

    • An agent can now have a multiplier applied to its movement speed from script. This will also affect locomotion animations to prevent foot sliding.

  • AgentPrivate.GetSpeedFactor()

    • Returns the applied speed multiplication factor. Will return 1.0f by default.


Updated articles

Previous updates

Update: September 3, 2019

Script updates

Quest API Updates

  • New quest states have exposed to the script api:

    • QuestState.ObjectivesComplete

    • QuestState.SelectRewards

  • Added ObjectiveDefinition.InitialState to get the state an objective will have when the quest is started.

  • Objectives stay in the state ObjectiveState.None when they are offered, and go into their initial state when the quest offer is accepted

General Script Updates

  • Maximum parameters increased from 20 to 50. (List<> max size remains 20)

  • Http Request/Response max body size increased from 16k to 64k

  • Http request throttle rate increased from 10/second to 20/second

  • Added ObjectUp, ObjectDown, ObjectForward, ObjectBack,ObjectLeft and ObjectRight to Vector.

    • The old Up, Down, Left, Right, Forward, and Back were not properly aligned with Sansar objects and are now deprecated.

  • Fixed an elusive bug that could cause weird behavior when using lots of the same script in a scene.

  • ScenePrivate.CreateCluster will now wait for scripted clusters to start all scripts before the callback event is sent.

Script Library Updates

  • Special tag {object} can be used in Library Script Group fields to create groups that are unique to the object the script is on. This can be used to prevent cross communication when duplicating scripted objects.

  • Debugger

    • Debug Enabled renamed to Debug Events, outputs detailed Library script event message information to the script debug console (ctrl-d)

    • Debug Memory option to output memory usage to script debug console any time it changes by +/-10%

    • -> Memory Report to output memory usage to script console when an event is received from another Library script

    • -> Subscription Report outputs Library event subscriptions by object to script console, for R36 and later library scripts only. Subscriptions by other scripts are not counted.

  • Light and Light On/Off

  • New parameter Lights to set multiple lights in the scene to be controlled by the same script.

  • If no Lights are added to the Lights parameter the script behaves as before, using the first scripted light on the same object the script is on. If any lights are set it will not automatically use the first light on the object.

  • Hint Text

    • New parameter VR Text can be set to an alternate string to show different hints to users in VR. If left empty, VR users will see the same text as desktop users.

    • Text substitutions added for {Player.Name} {Object.Name} and {Data.Source}. Details on using these are in the Hint Text parameter tooltip.

  • HotKey

    • New Parameter ExtraCommands to set up to 20 additional hotkeys with a single script. Usage in tooltip.

    • Added support for key combos. CSVs of multiple hotkeys in any command property work as key combos. Example: Modifier, PrimaryAction will only trigger by holding both Shift+F

    • Interaction

    • -> Reset fixed so the next event sent is the first event in the field

      • Previous bug would cause the second event to be sent.

    • New parameter -> Next will advance to the next event without sending the events for it. Used to keep buttons in sync if needed.

    • New Parameters Volume 1 through Volume 3 allows setting up to 3 other Interactions (for a total of 4) from a single script.

  • Position Reset

    • New parameter Volumes to set up to 20 objects to reset position. If no volumes are added the script will work on the object the script is on. If any objects are added then the script will not reset the object the script is on automatically.


New articles

Updated articles

Update: July 30, 2019

Script updates

  • New ability for scripts to have references to other components, whether the components are in the same object or in another object or location in the scene. For more information, see Referencing scene components with scripts.

  • Renamed a few scripts in the Script Library.

  • Sansar Script Libraries and examples updated to use C# 7.2 language features

    • Vector and Quaternion operations now use in parameters where possible. Scripts may need to remove ref passing arguments when recompiling.

      • old: v.cross(ref x);

      • new: v.cross(x);

Update: July 22, 2019

Script updates

  • Script API for authoring user-generated quests:

    • Quest definitions authored in the quest creator tool can be accessed by scripts using the [QuestDefinition]( class. When this is added as a public property in a script, the quest definition it refers to can be selected from a drop-down list in the editor. The QuestDefinition holds information about the quest that is shared between all users, for example:

      • QuestDefinition.Title

      • QuestDefinition.Description

      • QuestDefinition.ObjectiveDefinitions

    • Information about an individual user’s progress in a quest is handled by the Quest class. A [Quest]( instance for a user is obtained from a QuestDefinition with the async methods:

      • QuestDefinition.GetQuest(SessionId) or

      • QuestDefintion.GetQuest(AgentPrivate)

    • Quest instances are used to offer quests to users, using:

      • Quest.Offer()

    • Quest instances can query and set the state of the quest for the user they are associated with:

      • Quest.GetState()

      • Quest.SetState(QuestState)

    • The QuestState enum has the following values:

      • None - the user has not been offered the quest

      • Offered - the user has been offered the quest but hasn’t yet accepted it

      • Active - the user is on the quest

      • Completed - the user has completed the quest

    • Quest instances can subscribe to Quest state changes with

      • Quest.Subscribe(QuestState state, Action<QuestData> callback) - The callback will execute whenever the quest instance enters the specified state

  • Script API for authoring objectives for quests:

    • Quests are generally completed by completing all of their objectives. Quest objectives are handled in a very similar way to quests. Each objective has an ObjectiveDefinition class that can be assigned as a script property and selected with a drop down list in the editor. Each QuestDefinition also contains an array of its ObjectiveDefinitions. Also, each Quest instance contains an array of its [Objective]( instances

    • The Objective class represents an individual user’s progress in an objective. Just like Quest instances, an Objective instance for a specific user is obtained from an ObjectiveDefinition with the async methods:

      • ObjectiveDefinition.GetObjective(SessionId) or

      • ObjectiveDefintion.GetObjective(AgentPrivate)

    • Objective instances can get and set the state of the objective for the user they are associated with:

      • Objective.SetState(ObjectiveState)

      • Objective.GetState()

    • The ObjectiveState enum has the following values:

      • None - the objective state is not set, the user is not on the quest

      • Locked - the objective is locked for this user and cannot be completed

      • Active - the user is on the quest and the objective can be completed

      • Completed - the objective has been completed for this user

    • Objective instances can subscribe to objective state changes with

      • Objective.Subscribe(ObjectiveState state, Action<ObjectiveData> callback). The callback will execute whenever the objective enters the specified state.

  • Quest Script Library

    • Uses the quest api to provide drag-and-drop “SimpleScript” style scripts for common use cases:

    • QuestGiver

      • Offer a quest to users in response to simple script events

      • Sends simple script events when quest state changes

      • Can be set to automatically offer the quest when a user enters the scene

    • QuestGiverInteraction

      • Offers a quest to users when they interact with the object

      • The interaction is automatically enabled when the quest can be offered and disabled when it is accepted.

      • Sends simple script events when quest state changes

    • QuestGiverTriggerVolume

      • Offers a quest to users when they enter a trigger volume

    • QuestObject

      • Controls the state of a quest objective with simple script events

      • Sends simple script events when objective state changes

      • Can be set to automatically complete the objective when the user enters the scene.

    • QuestObjectInteraction

      • Completes a quest objective when a user interacts with the object

      • The interaction is automatically enabled when the objective is active, and disabled when it is not.

      • The object visibility can also be linked to the objective active state.

      • Sends simple script events when objective state changes

    • QuestObjectTriggerVolume

      • Completes a quest objective when a user enters a trigger volume

      • Sends simple script events when objective state changes

Documentation updates



Update: July 4, 2019

Script updates

  • New script API for per user gravity factor, which allows scripts to define the gravity factor for individual users.

Update: June 26, 2019

Script updates

  • Upgraded Mono runtime

    • New script compiler supports most C# language features: C# 7.0 , C# 7.1, C# 7.2, C# 7.3.

    • Added System.MathF namespace for float math (some overlap with Sansar.Mathf).

  • MeshComponent and visibility api - Creators can now author meshes to show different mesh states to different users through scripts. For example, this will allow two different users to see different states of a door in an experience, wherein one user may see the door open and another may see the door - closed.

    • If you wish to author a mesh that can have its visibility adjusted at runtime using scripts, then you must turn on the new scriptable property on meshes in the editor. All mesh component “set” functions will throw an exception if they are called on a mesh component that is not scriptable.

    • Sansar.Simulation.MeshComponent

      • New component to allow script control of mesh visibility.

    • GetIsVisible()returns true if the mesh is currently visible.

    • SetIsVisible(bool isVisible) sets the visibility state of a mesh.

    • SetIsVisible(AgentPrivate, bool)

    • SetIsVisible(SessionId, bool)

    • Mesh visibility can be updated temporarily on a per-user basis. Any of the following will override and reset the user specific settings:

      • The user leaving the scene.

      • The user logging out of Sansar.

      • Any calls on that mesh to SetIsVisible(bool)

    • New example script, MeshVisibilityExample.cs, in the installer folder: Program Files > Sansar > Client > Script API > Examples

  • Hint text - When set, it will display text on the user’s screen.

    • New string property: Client.UI.HintText - When set it will display the text on the user’s screen. The text is limited to 80 characters in length.

  • Scripts may be copied and pasted in the Object Structure panel.

API Documentation updates



Update: May 30, 2019

Script updates

  • New functions in Client.UI to show an on-screen progress bar:

  • AddProgressBar() adds a progress bar to the user's screen

  • GetProgressBars() returns a list of the progress bars that are being shown (currently only one progress bar can be shown at a time).

    • These fuctions return UIProgressBar objects which control the progress bar:

      • UIProgressBar.Start(string label, float duration Color color) starts the bar with the provided label, duraction and color.

      • UIProgressBar.Cancel() removes the progress bar.

      • UIProgressBar.Start can take a completion event of the form

      • Action. The completion event’s ‘Success’ field will be true if the progress bar sucessfully completed, and false if it was canceled.

    • The ‘Progress bar’ Scene Library script can be used to quickly add progress bars to experiences.

  • The ‘Mover’ Library script now uses the Movement API, and can be used with any object with the ‘MoveableFromScript’ flag set in the editor. The new version of the script does not support the pivot point offset- if you need this functionality the old version of the script is still available in the script library as ‘KeyframedMotion’

Update: April 30, 2019

Script updates

  • New Object Movement API

    • ObjectPrivate now has a Mover member responsible for moving the object from script.

    • A Movable From Script flag now appears on all Scene Objects in the editor. When checked, the Mover for that ObjectPrivate will be non-null.

    • ObjectPrivate.IsMovable should be used to determine if an Object can be moved. The object of a player agent and objects that contain a Rigid Body with Motion Type set to Static or Dynamic cannot be moved.

    • Mover has the following API. All Mover commands are enqueued automatically and executed in sequence on the Object:

      • Mover.AddTranslate() overloaded to support moving directly to a position or moving to a position over time. When WaitFor is used with this function, WaitFor will return once the command has executed and completed.

      • Mover.AddRotate() overloaded to support rotating directly to an orientation or rotating to an orientation over time. When WaitFor is used with this function, WaitFor will return once the command has executed and completed.

      • Mover.AddMove() overloaded to support translating and rotating an object or translating and rotating an object over time. When WaitFor is used with this function, WaitFor will return once the command has executed and completed.

      • Mover.AddPause() supports enqueuing a waiting time for the object before it executes its next movement command. When WaitFor is used with this function, WaitFor will return once the command has executed and completed.

      • Mover.StopAndClear() clears all enqueued movement commands and stops the Mover at its current position and orientation.

    • Additionally Mover has the following properties:

      • Mover.IsMoving returns true if a movement command is currently being executed (including when a Pause is being executed).

      • Mover.MoveCount returns the number of movement commands on the Mover including the currently active command and any Pauses.

    • See MoverExample1, 2 & 3 for sample scripts to help you get started!

  • Scripts can now rez objects with scene scripts on them. This means dynamically created objects now work with both ObjectScript and SceneObjectScript types.

    • More specifically, SceneObjectScript scripts will now work on objects created through ScenePrivate.CreateCluster.

  • ScenePublic now also includes the FindObject(ObjectId) interface previously only available on ScenePrivate.

  • New ObjectPrivate.FindScripts<T>() function to find all scripts on an object that match the Interface T, regardless of class name.

  • New overloads for Wait and Timer.Create that take a double seconds instead of a Timespan.

    • Wait(double seconds)

    • Timer.Create(double seconds, double repeatSeconds, Action)

  • New functions to trigger Tutorial hint UI:

    • Client.ShowTutorialHint(TutorialHint hint) to show the tutorial hint specified in the TutorialHint enum

    • Client.ClearTutorialHint()

    • Client.EnableAutomaticTutorialHints(bool enabled) to disable or enable the automatic (non-scripted) tutorial hints

  • RigidBodyComponent.ReleaseHeldObject can be used with WaitFor, and can be given a completion callback that is called when the object has been released.

Update: March 28, 2019

Script updates

  • List<> support in script parameters - Allows passing multiple values to a script as a single parameter. This means that creators can now assign multiple values such as a sound, object, a position point to one parameter. This eliminates the old behavior that forces the creator to utilize a parameter per value. 

    • Lists support 0 to 20 entries by default. The minimum can be raised and the maximum lowered with the [MinEntries()] and [MaxEntries()] attributes if desired.

    • [Entries()] attribute can be used to set default values for multiple entries: [Entries(1,2,3,4,5)] or [Entries(0,0,0)]

    • [AddEntry()] attribute can be used to add a single default value entry and can be used multiple times on the same parameter.

  • Interaction behavior on a per user basis - Creators can now set interactions to update and change behavior on a per-user basis. This enables creators to disable content once a user interacts with it. For example, a glowing chest in a treasure hunt could stop glowing once the user interacts with it.

    • Interaction.SetEnabled(AgentPrivate, bool)

    • Interaction.SetPrompt(AgentPrivate, string)

    • This is a temporary change. Any of the following will override and reset the user specific settings:

      • Any calls on that Interaction to SetEnabled(bool) or SetPrompt(bool)

      • The user leaving the scene

      • The user logging out of sansar

  • SceneInfo.MaxUsers - The maximum users allowed in the scene. This value is currently hard set and cannot be changed.

  • SceneInfo.InstanceRole - Usually set to "unset", will return "broadcaster" or "clone" in scenes configured for avatar broadcasting.

  • Bug Fixes

    • Teleports sent as soon as a user logs in will now work.

Update: February 28, 2019

Script updates

  • Overriding audio streams - The audio stream channel URL can now be overridden using the following APIs, ScenePrivate.OverrideAudioStream(url) and AgentPrivate.OverrideAudioStream(url).

    • As part of this change, we are deprecating Audio Streams 2/3/4 and they have been removed from Scene Settings. AudioChannel1 has been updated to “AudioChannel”.

  • Setting up a scene to broadcast voices - We’ve deprecated the old VoiceBroadcast API and have replaced it with the Megaphone API.

    • To enable/disable megaphone on a user as part of the scene setup, use ScenePrivate.SetMegaphone(personaId, bool).

  • Teleporting within the same experience - The new API AgentPrivate.Client.TeleportTo(position, forward) teleports the avatar within the current scene to a specified position, facing the specified forward direction.

    • Because avatars always remain upright, the up component of the forward direction will be ignored.

  • Force drop - The RigidBodyComponent.ReleaseHeldObject method forces any agent holding the rigidbody to immediately drop it.

  • Sit points update - SitObjectInfo data has been updated to include the position, forward direction, exit position and exit forward direction for sit points.

  • Script Library source reorganization - The Script Libraries in Sansar’s install folder have been reorganized. These scripts can be found in Program Files > Sansar > Client > ScriptApi > Examples > ScriptLibrary by default.

  • Bug Fixes

    • This release fixes several script crashes relating to memory bloat and coroutines that were introduced in R29.1.

    • Setting playback range on non-looping animations while they are playing works as expected.

Update: February 6, 2019

  • Sit Event API

    • Scripts can perform actions when an avatar starts or stops sitting on a rigidbody using the api: RigidBodyComponent.SubscribeToSitObject.

    • This method returns information about the agent performing this action and sit position relative to the objects origin.

  • Haptic Pulse API

    • Using the AgentPrivate.Client.VibrationPulse api lets a script fire a haptic vibration. It pulses the vibration motor for a control point at a given intensity (0 to 1) for a given duration in ms (0 to 1000). As an example, you can use this method to trigger haptic vibrations on the touch controllers when a gun is fired.

  • Media Action API

    • Some Twitch streams are marked as mature and require the user to click on a "Start Watching" button before viewing the stream in Sansar. Using the API: AgentPrivate.PerformMediaAction(MediaAction.TwitchMaturityClick), you can make the screen interactable and then call the above function on an agent once they’re taken an action to accept mature streams.

  • Simple Script updates

    • Simple scripts is now called Scene Script Library and it contains all scripts that only work in content built into the scene.

    • We've added a new Object Script Library, which contains all scripts that will work on objects that have been created by other scripts

    • The two libraries are compatible with each other and can send messages to each other.

    • This release includes several improvements to efficiency in script event routing and in the Script Libraries themselves.

  • New Scripts in the Script Libraries:

    • StoreListing: Show a Sansar Store listing to a user

    • AudioStream: For starting or stopping audio streams

    • TimeCountdown: For triggering events at specific times in a countdown

    • Timer has been renamed to TimedEvents

    • The Teleport scripts have been removed. The Teleport script in Scene Script Library now has options to Teleport on collision.

  • Reflective updates

    • New advanced Reflective features to give more control over how Reflective interfaces are found and registered.

    • ScenePublic.FindReflective added to find reflective interfaces that have been registered specifically for use on the ScenePublic API. By default scripts are not registered to this API with Reflective.Register() or [RegisterReflective], it is opt-in.

    • Scripts and Reflective classes can determine what contexts they are registered in by overriding ReflectiveContexts. Overriding ReflectiveContexts will automatically register the class when it is created (or the script when it is started), making the [RegisteredReflective] attribute redundant. protected override Context ReflectiveContexts => Context.ObjectPrivate;

    • Reflective.Contexts enum with available contexts: ObjectPrivate, ScenePrivate, ScenePublic.

      • Existing scripts, and all scripts that do not override ReflectiveContexts, will register only with ScenePrivate and ObjectPrivate with Reflective.Register and [RegisterReflective]

      • ObjectScript type scripts can only register with ObjectPrivate

      • SceneObjectScript type scripts can register with all contexts

      • Note: Only scripts can be found in the ObjectPrivate context, through the FindScript and FindScripts APIs. Non-script Reflective classes can not yet be found through ObjectPrivate even if their context is set.

    • The name registered Reflectives are found with can be overriden as well by overriding ReflectiveName. protected override string ReflectiveName => "Simple.Debug";

Update: December, 12 2019

  • Simple Scripts are now a single inventory item - but all the scripts are still there! Add the Simple Script Library to an object and use the second drop down menu to select which simple script to use.

  • Script Projects: You can now bundle multiple scripts, or include multiple files, into a single script upload using a .json project file. The bundled scripts will show as a single inventory item and when applied to an object a second drop down will let you choose which script from the bundle to apply.

    • Use [EditorVisible(false)] on a class in a script project to hide that class from the drop down shown when choosing a script, mainly useful for base classes. Abstract classes are hidden automatically.

    • The .json file should be a json object containing a "source" entry with an array of file names: { "source": [ "File1.cs", "File2.cs", ] }

    • The paths may be absolute or relative to the json file. The [DisplayName] attribute can be used on script classes to change how they show in the script selector.

    • The [DefaultScript] attribute can be used to control the script which is applied when first adding the project to an object.

  • Drag and Drop behavior change: When dragging a script from inventory onto an object it will now ADD the script to the object and will no longer replace the existing script if there is one.Script properties and script projects can now have tooltips. Use the [Tooltip("Helpful text")] attribute to give your script properties tool tips. All Simple Script properties have tooltips now!

    • Use [assembly: Tooltip("Script project description")] to add a script project tooltip.

  • Cast Ray APIs phase two: CsCscene now has CastCapsule, and non-axis-aligned CastBox. GetXXXClosestPoints for Box, Capsule and Sphere expand a simple shape and return collisions, useful for placing objects without overlapping and effects like explosions.

  • Relaxed throttles on CreateCluster, SendChat, MessageAllUsers, OverrideMediaSource and HttpClient.Request

  • AgentInfo.Handle to get a user's handle.

  • Added RightVector and UpVector to ObjectPrivate and ObjectPublic

  • Grab points now have an option to be "sticky" where they will not be released when the grab button is released.

    • In desktop mode mouse clicking on a grabbable object will pick it up. Regular grabbable objects will be dropped or thrown when the mouse button is pressed a second time or the F button is pressed. Sticky objects can be dropped or thrown by pressing F. In both cases holding the button longer on drop/throw will increase the distance it is thrown.

    • On Oculus Touch the Grip trigger can be used to pick up objects. Regular grabbable objects will release when the Grip trigger is released. Sticky objects can be dropped or thrown by pressing the Grip trigger a second time.

    • On Vive wands the trigger will pick up objects. Regular grabbable objects will release when releasing the trigger. Sticky objects can be dropped or thrown by pressing the Grip button.

  • New "Trigger" command for SubscribeToCommand. This command is sent on mouse click and VR triggers.

    • "PrimaryAction" (Grip), "SecondaryAction" (A/X), "Confirm" (B) and "Cancel" (Y) have been mapped to oculus touch controllers.

    • "PrimaryAction" (Grip) and "SecondaryAction" (Center Click) have been mapped to Vive wands

  • CommandData from SubscribeToCommand now contains Targeting data. Targeting data is sent for all commands. If the command is from the keyboard or mouse then targeting data is what the mouse is targeting. If the command is from VR then targeting data is from the device or hand used.

    • TargetingPosition: The point in world space that was targeted.

    • TargetingOrigin: The origin of the action. In desktop this is the camera position; in VR it is the center of the hand used.

    • TargetingNormal: The surface normal of the object at the point that was targeted.

    • TargetingComponent: The component id of the object part that was targeted.

    • SimulationFrame: The simulation frame the action was done, according to the client.

    • ControlPoint: The device used for the command. For VR compare to HeldObjectInfo.ControlPoint to determine if the hand holding something was the same hand the object is held in.

    • MouseLookMode: True if the user was in mouselook mode when the command happened. Mouselook mode ties the camera to the mouse cursor. Some game types are trivial outside of MouseLook Mode in desktop and this flag can be used to ignore inputs from that mode.

    • CameraControlMode can be FlyCam, FirstPerson or ThirdPerson and can be used to further restrict game play by ignoring or warning if the command is received in an undesired mode. Creators should also consider the recently added options to disable flycam and restrict teleports in their game experiences.

Update: November 7, 2019

  • Simple Scripts update:

    • SimpleGrabRelease - Send simple events when the object is picked up or dropped.

  • CastRay API

    • CsScene.CastRay projects a line segment between two points and returns all physics objects that intersect.

    • CsScene.CastSphere and CastBox cast an axis-aligned shape between two points and returns all physics objects that intersect.

    • Coming in a future release: CastCapsule and non-axis aligned version of CastBox and methods that expand a primitive shape to get the closest collisions.

  • AgentPrivate.Client.TeleportToUri(string uri) - Teleports to a scene URI.

  • RigidBodyComponent.GetInverseInertia/SetInverseInertia(Vector) - This API allows script to control the inertia of the object on different axes. For example an object can be set to only spin around the z-axis by giving it a vector with zero’s in the x and y components.

Update: October 9, 2019

  • Simple Scripts

    • All SimpleScripts now have a Group property to control which scripts communicate with each other. Setting a Group is optional, if left blank the script will behave as before. If a Group is set, then that simple script will only send events to and receive events from other scripts in the same Group by default. There are a couple of advanced features added as well:

      • To send a message to a different Group append @othergroup to the event - for example to send an on message to the radio group a SimpleInteraction script could send on@radio.

      • To send a message to ungrouped simple scripts specifically, even if a Group is set on this script, append @ to the end of the event like: on@

    • Advanced Optional Sequencing for events to emit or receive events in order, using >> as a separator. This is an entirely optional and complex feature that will likely require some experimentation.

      • For simple scripts that send events the >> separator can be used to send different events on subsequent actions. For example a SimpleInteraction that sets "On 1st Click ->" to one>>two>>three will send one the first time it is clicked, two the second, three the third and one the fourth etc. If sequencing is used with SimpleScripts that have other sequencing options like SimpleInteraction's 1st/2nd/3rd/4th click it is recommended to use one or the other and not both styles. The behavior of setting 1st click to one>>two>>three is identical to setting 1st click to one, 2nd click to two and 3rd click to three.

      • For simple scripts the receive events they will only respond to the current event in the sequence. If the sequence is one>>two>>three then until a one event is received the two and three events will do nothing. When one is received the action will happen and then the script will wait for two and ignore one and three.

  • Rigidbody grab/Release callbacks API

    • Scripts can perform actions when a rigidbody is grabbed or release by an avatar, using the API RigidBodyComponent.SubscribeToHeldObject. This method returns information about who has grabbed/released the object, and what hand they are grabbing it with.

    • Scripts have access to the RigidBodies that an avatar is currently holding, using the API AgentPrivate.GetHeldRigidBodies.

    • Scripts can control at runtime whether or not an object can be grabbed by avatars, using the API RigidBodyComponent.SetCanGrab.

Update: September 10, 2018

  • Json serialization API

    • Sansar.Utility.JsonSerializer can be used to Serialize and Deserialze Json strings to/from C# objects.

    • Sansar.Utility.JsonSerializerOptions can control the serialization process (more options to come!)

    • Sansar.Utility.JsonSerializationData is available in a generic and non-generic form and contains both the C# object and the json string on a successful serialize or deserialize.

  • Sansar HTTP request headers added to outgoing http requests:

    • x-sansar-experienceid

    • x-sansar-experiencehandle

    • x-sansar-instanceid

    • x-sansar-experienceowner

    • x-sansar-experienceuri

    • x-sansar-grid

    • x-sansar-scriptid

    • x-request-id

  • Bug fixes:

    • SAN-8335 Default user script ('CannonScript') sometimes fails to load when first user joins certain experience

    • SAN-8344 Some script error messages fail to be sent on RegionServer init

Update: Aug 16, 2018

  • Increased Parameter Limit:

    • SceneObjectScripts can now have up to 20 parameters

  • ObjectPrivate.AddInteraction:

    • Add an Interaction to an object dynamically. Used to add Interactions to rezzed objects or when it isn't desired that the Interaction prompt be a script parameter.

  • New Simple Scripts:

    • SimpleDispenser to rez objects

    • SimpleMedia to change the streaming media

    • SimpleObjectReset to reset an object's position

  • SimpleCollision has been revamped to better handle TriggerVolumes

  • Improved syntax for [DefaultValue] on vectors, quaternions and colors.

    • They no longer need to be specially formatted strings, simply list 2 to 4 values: [DefaultValue(1.2, 3.4, 5.6)]

  • New base script class: ObjectScript.

    • In anticipation of rezzable scripts (not yet enabled), this base class only has access to ScenePublic and a maximum of 10 parameters. SceneObjectScript scripts will not run on rezzed content; ObjectScript scripts can run on scene content or rezzable content.

  • SimpleScript base class deprecated.

    • Not to be confused with the new Simple scripts. Scripts that use this base class will still compile with a warning. Support for new compiles will be disabled in a future release.

Update: July 18, 2018


    • HttpClient property added to the ScenePrivate class.

    • HttpClient.Request can be used to make request to external web services. Only text content types are currently supported. Request/response size limits also apply.

    • HttpRequestOptions can be used for more control, including specifying the method, query parameters and headers.

    • Take note that the personal data may be shared with external services. This data includes:

      • Avatar name

      • A user's unique avatar identifier

      • When an avatar visits the experience

      • When an avatar leaves the experience

      • Where in the experience 3D space the avatar exists whilst in the experience

      • Public chat of avatars whilst in the experience

  • Multiple Animations on Objects support

    • Fbx files containing multiple animation clips can be imported.

    • Added AnimationComponent.GetAnimations() and AnimationComponent.GetAnimation(string animationName) to access these animations

    • Calling Animation.Play() will then transition to that animation, with a transition time specified by the new parameter AnimationParameters.BlendDuration.

  • Simple Scripts

  • Error Handling and Throttled APIs update:

    • Methods with callbacks that used to return a useless UInt64 now have a void return type.

    • If an API takes an Action<OperationCompleteEvent> handler, and a handler is provided, then any exceptions thrown by that API will be passed to the handler. OperationCompleteEvent.Success will be false, .Message will be the name of the exception and a new .Exception field will hold the thrown exception.

    • Passing any potentially throttled API to a WaitFor will now return immediately with a ThrottleException in the OperationCompleteEvent instead of throwing the exception.

    • All throttled APIs now take an Action<OperationCompleteEvent> handler. The default handler will log exceptions and return instead of throwing.

Update: June 1, 2018

  • Interaction API
 - Adding a script with a public or [EditorVisible] Interaction property will make the object clickable and allow a prompt to be shown on hover. The Interaction can be enabled and disabled, and the prompt can be updated by the script.

    • Interaction.SetEnabled(bool enabled) - To enable or disable the Interaction

    • bool Interaction.GetEnabled()
 - Returns true if the Interaction is currently enabled.

    • Interaction.SetPrompt(string prompt)
- Sets the prompt text for the Interaction.

    • string Interaction.GetPrompt()
 - Gets the current prompt text for the Interaction.

    • See the example script, InteractionExample.cs
, from the Script API root folder in the installer.

  • Advanced Script Feature: Coroutine handling - 
StartCoroutine now returns an ICoroutine interface that can be used to control coroutines and communicate between coroutines.

    • ICoroutine.Abort()
- Force the coroutine to stop running.

    • bool ICoroutine.IsAlive { get; }
 - Returns true if the coroutine has not finished.

    • bool ICoroutine.IsWaiting { get; } - 
Returns true if the coroutine is waiting on time or an event.

    • ICoroutine.Signal()
- Send a signal to the coroutine that will wake it up if it is in WaitForSignal();

    • void ICoroutine.ResetSignals()- Clear signals sent to the coroutine

    • string ICoroutine.Name { get; set; }
 - Get or set the name of the coroutine. Defaults to the name of the method or delegate passed to StartCoroutine.

    • ScriptBase.WaitFor(ICoroutine other)
 - Wait for coroutine other to finish before resuming this coroutine.

    • int ScriptBase.WaitForSignal()
 - Wait for at least 1 signal to be received, through ICoroutine.Signal(). Returns the number of signals received while waiting.

    • ICoroutine ScriptBase.CurrentCoroutine
 - The coroutine that is currently running.

    • IReadOnlyList<ICoroutine> ScriptBase.GetAllCoroutines()- 
All coroutines for this script.

    • See the example script, InteractionExample.cs
, from the Script API root folder in the installer.

  • Advanced Script Feature: Lock - 
For use with library style scripts that respond to calls from other scripts through Reflective. The Lock allows a script to declare a "critical section" that can only be accessed by 1 coroutine at a time.

  • Bug Fixes:

    • Object Animations

      • Animation.Reset() now resets to the end frame of the animation if it is playing backwards.

      • Changing animation ranges now maintains the paused animation frame if the paused frame is within the new range.

      • We fixed the bug where sequential animation commands would override previous commands so you no longer need to wait for Animation.Reset() to finish before playing the next animation, for example.

    • RigidBodyComponent.SetMotionType now throws an exception when attempting to set the motion type of an object beyond its maximum permissive motion type.

    • Fixed ScenePrivate.OverrideMediaSource() being ignored for late joiners.

    • OverrideMediaSource() fails to set the media URL back to the built-default URL

  • New known issues:

    • ScenePrivate.SceneInfo.ExperienceName which was returning an empty string will now return "unset". In a future release this will be updated to return the full experience name as shown in the atlas.

Updated: May 7, 2018

  • Animation control on objects

    • Animated objects now have two new properties in the editor:

      • BeginOnLoad - set this to false to prevent an animation from automatically playing

      • PlaybackMode - configure the animation to play once, loop or ping-pong back and forth from start to finish.

    • The AnimationComponent for an object now exposes a new DefaultAnimation member of the type Sansar.Simulation.Animation.

    • Sansar.Simulation.Animation

      • This is the interface to access data on the animation as well as for controlling object animation playback from script. It has methods to Play, Pause, Reset and JumpToFrame on the animation.

      • Sansar.Simulation.AnimationParameters can be used to configure animation playback for a limited window of frames, or to adjust the playback speed or playback mode. This can be applied with Get/SetParameters or by using the alternate Play/Reset methods.

      • GetFrameCount returns the object’s total number of frames of animation.

        • Note that Sansar imports animations at 30fps and will resample your animation if it was authored at a different frame rate.

    • Sansar.Simulation.AnimationParameters

      • RangeStartFrame, RangeEndFrame

        • Start and end frame numbers

      • ClampToRange

        • Set this to true to clamp animation playback to the specified start and end frames

      • PlaybackMode

        • Loop - The animation plays from the start frame to the end frame and then repeats from the start frame again.

        • PingPong - The animation plays from the start frame to the end frame and then backwards from the end frame to the start frame and then repeats that process.

        • PlayOnce - The animation plays one time from the start frame to the end frame then pauses at the end.

      • PlaybackSpeed

        • Set this to a number greater than 1.0 to speed up animation playback. Set this to a number less than 0.0 to reverse the animation.

  • New API to override the media url in a scene:

    • AgentPrivate.OverrideMediaSource(url, [width, height])

      • Will override the media url for the particular user only.

    • ScenePrivate.OverrideMediaSource(url, [width, height])

      • Will override the media url for all users.

    • Example script: MediaOverrideExample.cs

    • Sansar.Color now supported as a script property at edit time, e.g.,

      • public Sansar.Color myColor;

      • This will present a color picker and RGB values in the editor.

  • Added visibility on container properties for local position and rotation in the property editor. This is helpful for understanding why some objects come with a non-identity ObjectPrivate.InitialRotation and also gives increased control for fine tuning placement in the scene.

    • Objects that have their container transforms driven by animation do not show or allow this same local position and rotation manipulation.

  • Wait and WaitFor work outside of coroutines. They do not work in script constructors but should work everywhere else.

  • Fixed number pad Enter key to work with the Client.SubscribeToCommand API.

  • Script Debug Log: increased maximum rate by 4x to 256 logs per 30 seconds.

  • Whitelisted several more C# exceptions so catching specific exceptions should work.

Updated: April 9, 2018

The most significant updates to the script API in R20 are the addition of the new Sansar.Simulation.LightComponent and the new properties on Sansar.Simulation.RigidBodyComponent. Almost all physics properties that can be adjusted in Havok are now exposed through script APIs.

The import process now allows the specification of a motion type which creates an inventory cluster resource with a baked in motion type. This is a powerful feature when combined with the ScenePrivate.CreateCluster script API as it allows runtime creation of user-created dynamic objects. In addition, objects that are imported as dynamic can be changed to and from other motion types at runtime allowing dynamic objects to become keyframed, and vice versa. See SetMotionType() below for more details.

Here are the new script features:

  • Lights

    • If you wish to author a light that can have its properties adjusted at runtime from script, then you must turn on the new “scriptable” property on lights in the editor. All light component “set” functions will throw an exception if they are called on a light component that is not “scriptable”.

    • Sansar.Color

      • New, similar to Sansar.Vector but with RGBA components

      • Expected range of each component is 0.0 to 1.0. The Alpha component is 1.0 by default.

    • Sansar.Simulation.LightType enumeration for the type of light

      • Directional, Point, Spot

    • Sansar.Simulation.LightComponent

      • New component to allow script control of lights

      • IMPORTANT: All properties are read-only unless the “scriptable” property is enabled on the light in the editor. ▪ IsScriptable is a read-only property that allows a script to check to see if a light can have its properties adjusted at runtime.

      • NOTE: Directional lights can not be script controlled at this time.

      • LightType is a read-only property that indicates if a given light is a directional, point or spotlight. All properties can be adjusted on all light types but only certain properties apply to each type.

    • Color and Intensity

      • These two properties are intertwined. The Sansar renderer does not differentiate between a bright gray light and a dim white light so they are coupled in the API to reflect this.

      • SetColorAndIntensity(Sansar.Color, float)

        • This API allows you to set the color of the light and its brightness. The color is mapped into sRGB space and then the specified intensity is applied to it.

      • GetNormalizedColor()

        • This returns the color of the light based on one of its components having a value of 1.0.

      • GetRelativeIntensity()

        • This gets the intensity of the light based on the normalized color from above.

        • GetRange(), SetRange(float)

        • API to get and set the range for point lights and spotlights.

      • The following APIs only apply to spotlights:

        • GetAngle(), SetAngle(float)

          • To get or set the cone angle of the spotlight. Larger numbers indicate a wider, less focused light.

        • GetAngularFalloff(), SetAngularFalloff(float)

        • Angular falloff is the sharpness of the edge of the projected light. Small values will indicate a very clear edge while large values will fade the light smoothly towards the edge of its cone.

        • GetNearClip(), SetNearClip(float)

        • This value indicates the distance between the position of the light and where its light projection actually begins. This is useful for positioning a light within a recessed light socket, for example, without having the shadow of the light bulb or socket projecting into the scene.

        • GetShadowPriority(), SetShadowPriority(int)

        • The renderer supports many shadow casting lights in the same scene but in the event that too many shadow casting lights are competing for resources, the ones with the larger shadow priority will be applied first.

        • GetCastsShadows(), SetCastsShadows(bool)

        • This is an alternate API for shadow priority that matches the property in the editor. It uses a value of 0 or 1 behind the scenes for the shadow priority.

  • Rigid bodies

    • GetMotionType(), SetMotionType(RigidBodyMotionType)

      • The import process now allows the specification of a motion type so dynamic and keyframed objects can be saved to user inventory.

    • IMPORTANT: The imported motion type also specifies the maximum permissive motion type of an object. Objects imported as dynamic can be changed to any motion type in script. Objects imported as keyframed can be changed to static and back to keyframed, but can never be changed to dynamic. Objects imported as static can not have their motion type adjusted from script.

    • GetBounce(), SetBounce(float)

      • The range is from 0 to 1, with smaller numbers being less bounciness and 1.0 being a perfectly elastic collision.

    • GetCenterOfMass(), SetCenterOfMass(Sansar.Vector)

      • The vector points to the center of mass of the object in local space.

    • GetDynamicFriction(), SetDynamicFriction(float)

      • Dynamic friction from 0 to 1 is the friction applied to the object when it is moving across the surface of another object. The simulated friction between two objects is the minimum of the two touching surfaces.

    • GetGravityFactor(), SetGravityFactor(float)

      • Range from 0 to 1 that scales the effect of gravity on this object.

    • GetLinearDamping(), SetLinearDamping(float)

      • Similar to air resistance, with the default value of 0 indicating no resistance.

    • GetStaticFriction(), SetStaticFriction(float)

      • Static friction from 0 to 1 is the friction that affects an object at rest on another object. The simulated friction between two objects is the minimum of the two touching surfaces.

  • SceneInfo.ApiVersionString and ApiVersion return the current script API version.

  • Under the hood changes to script initialization times

  • Bug fixes: See known issues list here.

Updated: March 1, 2018

Detailed summary

  • New ScenePrivate.GetGravity and SetGravity

    • The scene properties now include gravity acceleration which can be set in G’s or m/s^2. These new Script API’s allow adjusting this gravity acceleration at runtime in m/s^2.

    • ScenePrivate.SetGravity(1.622f); // Set to moon gravity

    • float g = ScenePrivate.GetGravity(); // Get scene gravity

    • In addition, there are related constants for scene gravity:

      • ScenePrivate.DefaultGravity; // Default gravity m/s^2

      • ScenePrivate.GravityMinimum; // Lowest gravity (zero)

      • ScenePrivate.GravityMaximum; // Highest gravity (5G)

  • A few new Vector operations were added for convenience, namely:

    • float * Vector is now a supported operation

      • Previously only Vector * float was possible

    • Vector / float is now a supported operation

  • Objects now have a new keyframed motion type which has corresponding script support:

    • Added enumeration RigidBodyMotionType which includes:

      • MotionTypeDynamic

      • MotionTypeKeyframed

      • MotionTypeStatic

    • The RigidBodyComponent has a new API to query for this motion type:

      • RigidBodyMotionType t = rb.GetMotionType();

    • Additionally, the previous IsDyanmic() API has been deprecated.

  • FindScript improvements:

    • ObjectPrivate.FindScript<T>() now supports Reflective if an interface is used for and a script on the object matches that interface.

    • New API ObjectPrivate.FindScripts(string name) to find scripts on an object by their class name.

    • Scripts must be Registered with the Reflective system to be found by either of these APIs.

Update: February 1, 2018

Detailed summary

  • New Unsubscribe pattern for all event subscriptions

    • All Subscribe methods now return an object that implements IEventSubscription with an Unsubscribe() method and an Active property.

    • Timers have been updated to use this as well, named Timers are deprecated.

  • New "SimpleScript" base class to offer a quicker start for simple script writing

    • This class offers methods to be overriden for common subscriptions and takes care of the subscriptions for you.

    • All events are run in a co-routine to support Wait and WaitFor.

    • Attributes can be used to change the behavior of the subscriptions or to register new events.

    • See SimpleScriptExample.cs for a more complete example

A Simple Greeter Example

public class SimpleExample : SimpleScript


// This event occurs when a user enters the scene
protected override void OnAddUser(AgentPrivate agent)
		agent.SendChat($"Welcome to the {ScenePrivate.SceneInfo.ExperienceName} scene!");

} |

  • New Audio API calls for playing a stream.

    • Enum “StreamChannel” corresponds to streams set up in Scene Settings.

      • MediaChannel

      • AudioChannel1, AudioChannel2, AudioChannel3, AudioChannel4

    • Agent:

      • PlayStream(StreamChannel streamChannel)

      • PlayStreamAtPosition(StreamChannel streamChannel, float loudness)

      • PlayStreamOnComponent(StreamChannel streamChannel, AudioComponent* audioComponent, float loudness)

    • Scene:

      • PlayStream(StreamChannel streamChannel)

      • PlayStreamAtPosition(StreamChannel streamChannel, float loudness)

    • Component:

      • PlayStreamOnComponent(StreamChannel streamChannel, float loudness)

  • New Run argument in WaitFor will run code after the subscribe but before the wait to close some race conditions when using coroutines and cross script events.


// It is possible for a script to respond to the "Message" event before the WaitFor, in which case the response could be lost.


WaitFor(SubscribeToScriptEvent, "Response");

// Instead this is guaranteed to do PostScriptEvent after being set up to receive the response.

WaitFor(SubscribeToScriptEvent, "Response", () => { PostScriptEvent("Message") });

  • New limits on number of pending events on a script to prevent memory blowout

    • Use PendingEventCount to get number of pending events.

    • Events queued when there are already 256 pending events will be discarded

  • Coroutine operations (start/wait) always apply to active script to work better in cross script cases.

  • Removed "AllChannels" option for chat subscriptions. Scripts that were set to listen on all channels will now listen on the default 0 channel.

  • Fixed script stub dlls to not crash and created examples.csproj file for the example scripts, which is set up to use the stub dlls.

  • Fixed broken hyperlinks on script API help index.

  • More consistent behavior of user join/leave events in scripts.

  • Some optimizations to script memory tracking performance.

Have more questions? Ask in our Discord!

Last updated