SkookumScript has a feature called raw data members that allows script code to elegantly access and modify arbitrary data structures stored in C++ engine/application objects as if they were SkookumScript native data members. For the most part you won’t know the difference because both raw and native data members behave exactly the same in 99.9% of all use cases. But there are some subtle differences that I’d like to point out. Let me first explain how SkookumScript variables and native data members work.
In SkookumScript, every variable is a reference to an object that gets stored and/or passed around. That means data in SkookumScript is not stored in a class instance or a local variable by value, but by reference to an object that contains its value. The following short example illustrates this:
!a : 42
!b : a
a := 7
after which the value of
7. This is because we are creating an object of class
Integer with the value
42 and binding it to the local variable
a, then binding that same object to the local variable
b (i.e. now both
b refer to the same
Integer object). Thus changing its value via
a also affects the value referenced by
Native data members
Native data members work exactly the same way. They store a reference to a SkookumScript object that can potentially be also referenced by other variables. A native data member can also be bound and re-bound to new objects at any time.
Raw data members
Raw data members work differently. They represent memory in which variables are stored by value. We use them to make UE4 properties accessible via SkookumScript. They differ from native data members in the following ways:
Declaration: A raw data member is declared by prefixing it with the annotation
&raw in the script code. At runtime, the engine implementation then provides a callback to SkookumScript which will resolve the data member into two access callbacks and a size and offset in the containing object, allowing it to read and write its value. I am not getting into more detail on how this exactly works at this point - if you are curious check out
SkUEClassBindingHelper::resolve_raw_data() in our plugin source code and/or ask me!
Binding: A raw data member cannot be bound (using the
: operator) to SkookumScript objects like native data members, since it is stored by value. It can only be assigned a value (using the
Modification: You can modify a raw data member’s value in two ways:
- Using the assignment operator
- Invoking a modifying method call on it, for example the
+= operator or
Reading: When you read the value of a raw data member, SkookumScript will under the hood create a new object, assign the raw data member’s value to that object, and return that object - essentially making a copy of the raw data member. Modifying that object after that will not affect the original raw data member! You can imagine reading the value of a raw data member
!a : @my_raw_data_member as equivalent to copying the value of a native data member
!b : @my_native_data_member! (note the exclamation mark after the data member which invokes its copy constructor to make a copy of the object).
Hope this clarifies things a bit. Please ask if something is not clear to you!