Table of Contents
Expressions in RAIN are fairly similar to what you might see in C#, C++, and C. They are used throughout RAIN behavior trees in Constraint and Expression nodes and on any field that is marked with an e.
Variables are words (always starting with a letter or
_ with no spaces) that can store values to be referenced later. They are stored in the AI Basic Memory and can be set and accessed throughout all of your components.
To speed up development in a behavior tree, variables can represent any type of value at any time (float, int, GameObject, etc), and can be created at any time just by using them. This can lead to a few problems to watch out for:
- It is possible to call operators that don't make sense, like
myTarget += 1where
myTargetis a GameObject. If this happens RAIN will just ignore the expression.
- If you misspell a variable name it will create a new variable at that moment and use it, giving you results that may not make sense.
- If variables are used before they are assigned they will take on a default value. Depending on the equation they are in this will change.
Use the Behavior Tree debugging and watch the AI BasicMemory during playback to help figure out what is going on with your expressions. Good naming habits will also help you keep track of variables better.
To negate a boolean you can use a
! (bang) and to negate a float or integer you can use a
shouldJump = !shouldJump
x = -y * deltaTime()
For assignment you can use
+= (addition assignment),
-= (subtraction assignment),
*= (multiplication assignment), and
/= (division assignment).
movementSpeed = 10
movementSpeed += 100
For logical operations you can use
|| (OR), or
shouldJump = x || y
x ^ y
For relation operations you can use
!= (not equal),
!~ (not approximately),
> (greater than),
>= (greater than or equal),
< (less than), and
<= (less than or equal).
!~ only apply to decimal numbers (in any useful way at least) and means that the two values are pretty much equal (within a small amount).
shouldJump = x ~~ 10
x < 10
For arithmetic you can use
* (multiplication), or
x = y + 10
x = (y + 10) * deltaTime()
To increment or decrement you can use
++ (increment) and
-- (decrement). Currently RAIN only supports pre-increment and pre-decrement (vs. post-increment and post-decrement).
shouldJump = ++x == 10
You can use
; (separator) to execute multiple statements.
x = 5; y = 10
x = false; ++y
Built in Functions
There are also several built in functions for use in your expressions:
- deltaTime: Behavior trees are evaluated every Update step, so deltaTime will return whatever UnityEngine.Time.deltaTime would have been in the Update call.
x = 5 * deltaTime()
y += deltaTime()
- currentTime: currentTime will return whatever UnityEngine.Time.time would have been in the Update call.
x = currentTime()
x > currentTime()
- clamp: Similar to the Mathf.Clamp function in Unity.
x = clamp(x, 0, 1)
x = clamp(x, 0.5, 10.0)
- min: Similar to the Mathf.Min function in Unity.
x = min(0, 1)
x = min(x, 10)
- max: Similar to the Mathf.Max function in Unity.
x = max(0, 1)
x = max(10, x)
- debug: Similar to Debug.Log function in Unity.
debug("My value is: " + x)
- random: Similar to Random.value property and Random.Range function in Unity.
x = random()
x = random(0, 10)
- gameobject: Finds a game object in the scene and returns it.
x = gameobject("Player")
- waypoints: Returns a Waypoint Route or Waypoint Network with the given name.
x = waypoints("Patrol Route")
x = waypoints("Walkable Path")
- position: Returns the Vector3 position associated with an object. The object can be a GameObject, Transform, RAINAspect, NavigationTarget, MoveLookTarget, or Vector3.
x = position(enemy)
- navigationtarget: Returns a Navigation Target with the given name.
x = navigationtarget("SpawnPoint1")
Within any expression you can use the following keywords:
null: Useful when assigning to or checking a variable that contains a GameObject.
true: Useful when assigning to or checking a variable that contains a boolean.
false: Useful when assigning to or checking a variable that contains a boolean.
- int: Short types will be used as ints. Any whole number in an expression will be treated as an int.
- long: Only settable from code.
- float: Any decimal number in an expression will be treated as a float.
- double: Only settable from code.
- bool: Usually represented by a
falsekeyword. Any number can be treated as a bool as well, where 0 is
falseand everything else is
- string: Anything in
""in an expression will be treated as a string.
- Vector2: Represented by
(x, y)in an expression.
- Vector3: Represented by
(x, y, z)in an expression.
- Vector4: Represented by
(x, y, z, w)in an expression.
- GameObject: Cannot be represented in an expression directly, but can be assigned to a variable in code.
In the event that a variable is used but is undefined it will take on the default value required for the equation. Some examples:
myVariable + 1will be 1 (
myVariableis changed to
"Hello" + myVariable + "World"will be
myVariableis changed to
myVariableis changed to
The default values are as follows:
- Vector2: Vector2.zero
- Vector3: Vector3.zero
- Vector4: Vector4.zero
Not all operators work with all types. Most of the Unary Operators won't attempt a conversion because they lack any hints. In most cases this results in a return value of
null (or whatever default type you try to convert it to).
On the other hand, some operators and functions will attempt to do a conversion no matter what. For instance, almost any type can become a string. Some examples:
++isn't compatible with strings
"someString" + 0.55returns
debug(prettyMuchAnyVariable)prints the string representation of that variable to the log
min("one string", "another string")will return
""because it isn't compatible with strings