The `Mind`, the `Master` and who pulls the strings in SkookumScript


#1

Here is a quick rundown on the Mind class since it’s a special class.

As you may know, coroutines are an important core feature of SkookumScript. Coroutines are blocks of code that exist over time before they complete, i.e. across multiple update frames. So every game frame/update tick, SkookumScript comes around and checks on all its coroutines, and updates their progress as necessary. This is accomplished via Mind objects.

Each coroutine has a dedicated Mind instance that is in charge of updating it. Important to note is that a Mind can update coroutines even when they are not members of that mind or using that mind as a scope (such as a coroutine closure). For example a mind can update a _wait() coroutine running on a game actor.

So if one Mind can do it all, why would you need multiple Mind objects? The reason is that Mind objects have a lifespan. A typical use for such a time limited Mind instance would be a game mission, progression points, ambient world behavior or any chunk of game logic that makes sense to group together and has a begin and end point in time. When the mission starts, that mission’s Mind object gets created, does its thing, and gets deleted when the mission ends. When a Mind destructs, all the coroutines it updates also get terminated. So you can also see a Mind as a “group” of coroutines that belong together and can be terminated simultaneously. This is handy for proper clean-up after some high level task is done as otherwise coroutines could continue running, and actors in your game could keep doing things that you might not want them to do.

There is always a default Mind called the master mind which updates all coroutines that you don’t specifically assign to other Mind objects. It generally acts as the main container for an entire project and is created regardless of the level or progression point of a game. The master mind must be derived from the Master mind class and it can be specified in the project settings file (Scripts\Skookum-project.ini) in the [Project] category in the StartupMind entry. For example in the SkookumDemo project it uses a master mind of the same name - StartupMind=SkookumDemo.

In your SkookumScript project, you can control which Mind starts up first by specifying a Start-up Master Mind Class in the Settings/Project Settings... dialog in the SkookumScript IDE (or by editing the ini file of your project - located inside the Scripts folder - and changing the StartupMind variable).

Ok now how do you control which coroutine runs on which Mind? Whenever you call a coroutine from another method or coroutine, by default it automatically inherits the mind that updates that method or coroutine. There are two exceptions to this rule:

  1. If the coroutine is the member of a Mind class in which case that Mind instance is used as the updater
  2. If you use the change command, e.g. change my_mind my_actor.do_something

Note that rule 1 supersedes rule 2! A member coroutine of a Mind always runs on that Mind even when preceded by a change command.

You can at any point in your code find out which Mind is updating it by calling the this_mind literal. It returns the Mind currently in charge of updating that code.

You can also find out what Mind is updating a particular InvokedBase (such as returned by the branch command) by calling its mind() method.

So hopefully this clarifies some of the mystery surrounding the Mind class! And as usual, please keep asking if you have any questions!


Is there static constructors/initializer in SkookumScript?
Coroutines can't be class member?
What is branch and change and what's the difference between these two?
Is there static constructors/initializer in SkookumScript?
Rotate a cube basic test?
Assigning a coroutine to a Mind
Need help with data initialization before using in race/sync
Great curated posts to learn about SkookumScript
[RESOLVED] When to use the SkookumScript* classes/component?
Concurrency in SK | Single Threaded
SkookumScriptClassDataComponent, SkookumScriptMindComponent and SkookumScriptBehaviorComponent - who is who
Basic Tutorial 2: Spawn cubes dynamically and manipulate them using Skookum
Order of coroutine
'change' command explained
Assigning a coroutine to a Mind
#6

Just mentioning here that we now have the concept of “Mind actors”:

You can instantiate a SkookumScript Mind in a UE4 game by attaching it to an actor using a SkookumScriptComponent. Simply enter the name of your Mind-derived class into the Script Class Name parameter of the SkookumScriptComponent, and an instance of your class will be automatically created and attached whenever that UE4 actor is spawned.

One application is for example a “Level Mind”: Place an empty actor in your level and name it “Level Mind”. Add a SkookumScriptComponent and set the Script Class Name to the name of your Mind class. Your Mind will now be instantiated when that level is loaded, and destroyed when the level is unloaded.


Rotate a cube basic test?
#7

Along with the great information here, could we also be informed on the proper way to remove a Mind from a Level?

For example, assume that one has placed the empty Actor associated with a Mind in the Level, the Mind is now done with all the things it needs to do… time to remove it. What is the recommended method of removal?


#8

Well the recommended way would be to either

  1. place the Mind actor in the level and then unload the level which will destroy the Mind actor, or
  2. spawn the Mind actor then destroy it manually!