Parallel Action

The ParallelAction is used to instantiate two or more Actions simultaneously. Then the user can decide which one to complete first.

Additionally, ParallelAction can modify the Scenegraph tree according to the user’s decisions. ParallelActions are usually linked with critical errors. For example, we may implement a ParallelAction which has a correct and a wrong Action to Perform. If the user decides to complete the correct Action, then the simulation will continue as usual. However, if the user completes the wrong Action (for instance inserting an object in a wrong place) then this behavior will trigger the alternative path and the scenegraph will be modified runtime by adding or removing specific Actions.

For instance, if the user causes damage to a human bone, the scenegraph will populate a new stage that forces the user to correct their mistake by repairing the fracture. In another example, if the user paints a car with the wrong color, scenegraph can add new Actions in order to repaint it.

You can read here a detailed article on ParallelActions.

In this example, we will implement a ParallelAction where the user needs to decide whether to assemble the Knossos model or the Sponza model. This Action is part of the SampleApp level named AssembleKnossosORSponzaAction

Note

The “normal” path involves the assembly of Knossos and the “alternative” path the assembly of Sponza.

As a result, if the user decides to assemble the Knossos, the scenegraph will move to the next Action. However, if they assemble the Sponza, the alternative path will trigger to add a new Lesson node to the scenegraph runtime.

Action Blueprint

The graph below implements the action:

../../../_images/parallel_action_00.png

Blueprint Walk-through

Initially, the two actions which will determine the path are created and configured. They are both InsertActions, and are stored as temporary variables for use later on when the ParallelAction is set-up.

../../../_images/parallel_action_01.png

The next step is to set a different event listener for each action. The first action will listen to the (automatically assigned) default event, so the remaining actions will need to listen to different events. In this case we only have one alternative action, so we will have it listen to “SponzaPart”.

../../../_images/parallel_action_02.png

The final step is to configure the number of the alternative path that each action will trigger upon completion. In our example, the Assemble Knossos action will trigger the default path (making no change to the scene graph) which is -1. If the user chooses to assemble Sponza, it will trigger the alternative path 0

../../../_images/parallel_action_03.png

SceneGraph Configuration

Now we will generate the Lesson node that will be added to the scenegraph in case the user triggers the alternative path.

Note

The next version of MAGES for Unreal (1.0) will include a visual scene-graph editor, but we can still configure the scene-graph manually.

Create a new file named AlternativeLessons.xml and fill it with the following contents:

<?xml version="1.0"?>
<ArrayOfLessons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Lessons>
        <Lesson_Name>Sponza Restoration</Lesson_Name>
        <Stages>
            <Stage_Name>Sponza Stage</Stage_Name>
        </Stages>
    </Lessons>
</ArrayOfLessons>

In order to convert this lesson node into an alternative one, we will need to tell the scene-graph which action would trigger this node.

<?xml version="1.0"?>
<ArrayOfLessons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Lessons>
        <Lesson_Name>Sponza Restoration ADD(0|1|0-0|0|0)</Lesson_Name>
        <Stages>
            <Stage_Name>Sponza Stage</Stage_Name>
        </Stages>
    </Lessons>
</ArrayOfLessons>

The syntax used here can be described as follows:

<Alternative Type> ( <Trigger Action ID> - <Additional Node> )

  • Alternative Type: The type of this alternative path (ADD, DEL, RPL). In this case, it is set to ADD since we want this lesson to be added to the scene-graph.

  • Trigger Action ID: The action that can trigger the alternative path. In our case, the action AssembleKnossosORSponzaAction will have an LSA ID of 010 (Lesson 0, Stage 1, Action 0).

  • Additional Node: In case of an ADD AlternativeType this variable sets the left sibling of our added node. In this example, if we set the AdditionalNode to 000, our new node will be added as a sibling next to 000 meaning that it will be the 100 node (the second Lesson)

We add the Stage and Action nodes to the alternative lesson in the usual way

In our example, if the user inserts the Sponza instead of the Knossos, then this lesson node will be added as the second lesson of the operation. This node contains additional Actions for the Sponza (UseAction and ToolAction) and finally the OperationEnd Action.

In our example, if the user inserts the Sponza instead of the Knossos, then this lesson node will be added as the second lesson of the operation. This node contains additional Actions for the Sponza (UseAction and ToolAction) and finally the OperationEnd Action.

Below you can see the final alternative lesson scenegraph.

<?xml version="1.0"?>
<ArrayOfLessons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Lessons>
        <Lesson_Name>Sponza Restoration ADD(0|1|0-0|0|0)</Lesson_Name>
        <Stages>
            <Stage_Name>Sponza Stage</Stage_Name>
            <Actions>
                <Action>Clean Sponza</Action>
                <ActionClassName>UseAction</ActionClassName>
                <ActionType>Simple</ActionType>
                <AverageActionTime>10.0</AverageActionTime>
                <IsDemoApplicable>y</IsDemoApplicable>
            </Actions>
            <Actions>
                <Action>Burn Sponza</Action>
                <ActionClassName>UseWithToolActionBP</ActionClassName>
                <ActionType>Simple</ActionType>
                <AverageActionTime>10.0</AverageActionTime>
                <IsDemoApplicable>y</IsDemoApplicable>
            </Actions>
            <Actions>
                <Action>Operation End (Alternative)</Action>
                <ActionClassName>OperationEndAlternative</ActionClassName>
                <ActionType>Simple</ActionType>
                <AverageActionTime>10.0</AverageActionTime>
                <IsDemoApplicable>y</IsDemoApplicable>
            </Actions>
        </Stages>
    </Lessons>
</ArrayOfLessons>

The final step is to register the AlternativeLessons.xml file to our training module. From Unreal, open the SceneGraphPathDefinitions asset of the operation:

../../../_images/parallel_action_04.png

Parallel Action Explanation

Now lets see what happens when we start the application. The scenegraph loads the LSA graph at the Scene Graph actor on the hierarchy. Additionally, our alternative lesson will be added under a separate actor, the AlternativePathBucket. Here is where all the alternative nodes are saved, waiting to be spawned in the scenegraph.

../../../_images/parallel_action_05.png

You can see here that the “Sponza Restoration” lesson has the ADD-0 opcode next to the lesson name, signifying that it will be added next to the first lesson.

Now lets move to the AssembleKnossosORSponzaAction Action that will trigger the alternative path. As you can see both Actions are Initialized simultaneously, the user should decide which one will complete. To trigger the alternative path we have to insert the Sponza model.

../../../_images/parallel_action_06.png

Upon performing the action by choosing to assemble Sponza, the alternative lesson we created will be inserted into the graph.

Note

Unreal does not record the sibling indices of actor attachments; we use our internal method to keep track of this

../../../_images/parallel_action_07.png

As a result, the next actions that the user will execute, will be the alternative actions we specified in the AlternativeLessons.xml file.

Note

Both alternative Actions will Perform() when completing the ParallelAction.

If you Undo() and come back to the ParallelAction, the alternative lesson will be deleted from the scenegraph hierarchy (reset).