Script structure
The main function in a Cloud Code script that acts as the entry point of the runtime takes the form of a CommonJS wrapper.
The following code snippet shows the simplest possible script:
JavaScript
module.exports = async ({ params, context, logger }) => {
// this script does nothing
};
While this script doesn’t actually do anything, it shows the context object and asynchronous nature of the script function.
Note: A script is invalid unless it exports a CommonJS function.
Note: Script names must be unique across the project and environment, only contain letters, numbers, underscores and dashes, and not exceed 50 characters.
Context object
The context object contains these useful objects:
Params
: This is an array of name-value pairs of the input parameters with which a script is called.Context
: This object provides additional context that is useful within a script:projectId
: The project ID to which the caller was authenticated.playerId
: The authenticated player ID.accessToken
: A JWT that can be used to call other Unity game services SDKs as the authenticated player.environmentName
: The name of the currently used Unity environment.environmentId
: The ID of the currently used Unity environment.serviceToken
: A JWT used to call other Unity game services SDKs as an authenticated Cloud Code user.unityInstallationId
: Unique identifier that identifies an installation on the client’s device. The same player can have differentinstallationId
s if they have the game installed on different devices. It is available to all Unity packages that integrate with the Services SDK Core package.analyticsUserId
: A unique string that identifies the player and is consistent across their subsequent play sessions for analytics purposes. It is the primary user identifier and it comes from the Core package.correlationId
: Unique identifier used to correlate requests.
Logger
: An object that allows the script to log info, warnings, and errors.
JavaScript
module.exports = async ({logger}) => {
logger.info('This message confirms that the logging client is functional!');
logger.warning('This is a serious warning that the cheese is about to run out.');
logger.error('Out of cheese :(');
}
Refer to the Logging documentation for more information.
Token authentication
The accessToken
and serviceToken
are JWTs, provided as properties of the context
object.
These tokens authenticate calls to other Unity Gaming Services from Cloud Code.
Token type | Origin | Data access | Usage |
---|---|---|---|
accessToken | Generated by the Authentication service | Restricted to the authenticated player | The accessToken is the JWT the Cloud Code call is authenticated with. It can be passed onto other UGS services to access data for the authenticated player |
serviceToken | Generated by Cloud Code | Allows cross-player data access | The serviceToken is Cloud Code generated token that can be used to call out to other UGS services and interact with cross-player data |
Any configured Access Control rules affect the accessToken
.
Below is an example of how to use the accessToken
to call the Economy SDK to get the player's inventory.
JavaScript
// Player inventory
const { InventoryApi } = require("@unity-services/economy-2.4");
module.exports = async ({params, context, logger}) => {
const { projectId, playerId, accessToken } = context;
const inventory = new InventoryApi({accessToken});
const result = await inventory.getPlayerInventory({projectId, playerId});
return result.data;
}
If you want to use serviceToken
, the same script would look like this:
JavaScript
// Player inventory
const { InventoryApi } = require("@unity-services/economy-2.4");
module.exports = async ({params, context, logger}) => {
const { projectId, playerId } = context;
const inventory = new InventoryApi(context);
const result = await inventory.getPlayerInventory({projectId, playerId});
return result.data;
}
Refer to Service and access tokens for an in-depth explanation of the differences between the two tokens.
Script parameters
Script parameters can be defined outside or inside the script body.
Note: In-script parameters offer a simpler alternative to declaring parameters, but the Unity Cloud Dashboard does not currently parse in-script parameters if you try to update them without using the Deployment package.
In-script parameters
In-script parameters can be added by exporting the params
object, containing each parameter name as a key, and its type as a value.
Important: You must assign the module.exports
property before setting the parameters.
For example:
JavaScript
module.exports.params = { "echo" : "Boolean" }
Alternatively, if you'd like to specify that a parameter is required, you may specify an object containing both the type
and required
properties.
JavaScript
module.exports = async ({ params, context, logger }) => {
return {
"value": params["aParam"]
};
};
module.exports.params = { "aParam" : { "type": "String", "required": true } }
By default, parameters are not required.
Both formats can be combined as desired:
JavaScript
module.exports = async ({ params, context, logger }) => {
var value = params["echo"] ? params["aParam"] : "default";
return {
"value": value
};
};
module.exports.params = {
"echo" : "Boolean",
"aParam" : { "type": "String", "required": true }
}
Async/await
The main script function can be an asynchronous function. This means that a function can await promises, which enables the use of other Unity game service SDKs within the script. Check the Mozilla documentation describing promises.
A trivial example looks like the following:
JavaScript
// Player inventory
const { InventoryApi } = require("@unity-services/economy-2.4");
module.exports = async ({params, context, logger}) => {
const { projectId, playerId } = context;
const inventory = new InventoryApi(context);
const result = await inventory.getPlayerInventory({projectId, playerId});
return result.data;
}
Note: Cloud Code client-side calls are always asynchronous, with both regular (synchronous) and asynchronous scripts.
Additional packages
Your scripts can import local scripts or external packages with the import
or require
keywords.
Refer to the Available packages for a full list that can be imported.
JavaScript
const _ = require("lodash-4.17");
module.exports = async () => {
return _.random(1, 6);
};
Note: Required packages must be declared outside of the exported function.
Bundling
Note: The Unity Cloud Dashboard and CLI do not currently fully support bundled scripts.
Script bundling is a feature enabled by using the Deployment package within the Unity Editor to help manage your scripts locally, unlock additional workflows and enables common functionality to be shared across multiple scripts. Refer to the JS bundles documentation for details on how to generate bundled scripts.
JavaScript
const lib = require("./lib");
module.exports = async () => {
return lib.helloWorld();
};
module.exports.bundled = true;
Output
Script output can consist of the following types:
JavaScript
string
module.exports = async () => { return "hello world"; };
boolean
module.exports = async () => { return true; };
number
module.exports = async () => { return 3.14; };
object
module.exports = async () => { return { message: "hello world", success: true }; };
Successful responses are returned from the API as JSON with the following structure:
{
"output": <SCRIPT OUTPUT>
}
Error output
Errors can be thrown by scripts when something causes the invocation to fail for example, a failed service request.
Catching errors within your scripts allows you to determine how the failure should be handled.
JavaScript
module.exports = async ({logger}) => {
try {
let result = service.call("example");
return result;
} catch (err) {
logger.error("Something went wrong!", {"error.message": err.message});
throw err;
}
};
Error responses are returned from the API as JSON with error details containing the error type, error message and a stack trace to help identify the cause of the error.
{
"type": "problems/invocation",
"title": "Unprocessable Entity",
"status": 422,
"detail": "Invocation Error",
"instance": null,
"code": 9009,
"details": [
{
"name": "ReferenceError",
"message": "service is not defined",
"stackTrace": [
"at module.exports (example-test.js:1:26)"
]
}
]
}