WIP 05 | Chain Simulation
Goal: Learn how to use the ChainInstructor.
For convenience there is an example scene which can be used for this tutorial. The scene is called “5. Chain Simulation Start Scene“. This scene is provided with a DES Controller, some ChainLinkObjects, and shots to create a Chain Spline with.
Add ChainInstructor
Firstly, add a ChainInstructor to the scene. In the example scene, there is already a GameObject called “ChainInstructor“, so add the ChainInstructor component to this object. If using your own scene just add an GameObject and add a ChainInstructor component to it. Make sure to parent it under a DESContoller.
Create a ChainSpline
To describe the movement path of the chain, we have to create a Spline. This can be done in several ways, but the preferable one is using the Actor Route Creator. In the example scene, you can find some premade shots which can be used in combination with the Actor Route Creator to generate a Spline. Make sure the Spline is closed.
Prepare ChainLink prototypes (chain-links)
The example scene already provides meshes to use as individual chain-links (prototypes). Make sure to give the prototypes a ChainLink Component. Furthermore, we have to make sure to position the pivot of the prototypes to the wanted position and determine its “Leading” and “Trailing” space to be able to generate the chain later on. Example of how to determine these values are given in the picture below, using the example meshes from the example scene.
In the example scene, Situation 1 is used, with a trailing space of 0 m and a leading space of 0.1023874 m.
Generating the chain
Before we can generate the chain we have to set the values of the ChainInstructor. First we have to set the ChainSpline by selecting the created spline from the previous step. Secondly, we have to set the Chain Link Prototypes. Here we select our prototypes with their leading and trailing spaces. Lastly, we have to define a Chain Link Pattern. This is done by setting a List of integers, where 0, 1 and 2 correspond respectively to Element 0, Element 1 and Element 2 of the selected Chain Link Prototypes. Setting these fields for our example scene results in the following Inspector.
When we press the “Reinstantiate Chain Links”, this results in the following chain.
If we now press play and toggle the “Start Chain“ in the ChainInstructor inspector, we see we already have a moving chain.
Finetuning the chain
If we look closer, we see that the last chain link sequence is incomplete and not realistically linked with the starting link. To correct this, we have to make sure the length of the Chain Spline is a multiple of the sum of all the Leading and Trailing spaces in the Chain Link pattern. In the above case this will mean a multiple of (4 x 0.1023874 =) 0.4095496 meters. By first removing the previously generated chain by pressing the “Remove Chain Links“ button, we can alter the lengths of the straight sections of the Chain Spline. Moving spline point 1 to 8 -2.4966 m over the x-axis results for instance in the chain shown below.
Interacting with the chain
Interacting with the chain can be simply done by adding a Cue to the Chain Spline with an owner Instructor. Lets check the claim that the DES simulation can run with a precision of 1e-10 seconds. We create a cue somewhere on the Chain Spline and add the following instructor as owner instructor.
using System.Collections.Generic;
using u040.prespective.prescripted.des.activities.motiontensor;
using u040.prespective.prescripted.des.buffer;
using u040.prespective.prescripted.des.instructors;
using u040.prespective.prescripted.des.participant.actor;
using u040.prespective.prescripted.des.participant.cue;
using UnityEngine;
public class ChainRoundTimeInstructor : DESInstructor
{
public struct ParticipantPassingTime
{
public int ParticipantID;
public double Time;
public ParticipantPassingTime(int _id, double _time)
{
ParticipantID = _id;
Time = _time;
}
}
private List<ParticipantPassingTime> passingTimes = new List<ParticipantPassingTime>();
public override bool ApplyInstruction(ADESActor _actor, ADESCue _cue, ActorCueIntersectionEvent _intersectionEvent)
{
if (_intersectionEvent.IntersectionType != ActorCueIntersectionEvent.CueIntersectionType.Center || (!(_actor is ChainLink)))
{
return false;
}
double _currentSimTime = (SimulationController.TotalSimTimePassed + _intersectionEvent.EventTime);
int timeIndex = passingTimes.FindIndex(_passingTime => _passingTime.ParticipantID == _actor.ParticipantID);
if (timeIndex != -1)
{
ParticipantPassingTime passingTime = passingTimes[timeIndex];
double _laptime = _currentSimTime - passingTime.Time;
Debug.Log("Lap Time for Chain Actor [" + _actor.name + "] = " + _laptime);
passingTimes.RemoveAt(timeIndex);
}
passingTimes.Add(new ParticipantPassingTime(_actor.ParticipantID, _currentSimTime));
return false;
}
}
After Pressing play and toggling the “Start Chain“ Button, we see the following logs in our console.
Comparing these values with the spline length of 6.55320689739471 (since the default chain velocity was 1 m/s), we see a precision of 1e-12.
Here we created a separate DESInstructor to link to the cue. To keep the chain instructor packed together you can also inherit from the ChainInstructor itself. Then you can use your own custom chain instructor to set things up. In this tutorial we chose to create a new separate instructor.
Optimizing performance
When making chains, you can quickly get a lot of chain link instances and thus a lot of DESActors in your scene. This can hamper the performance of your simulation. Not all chain links have to interact with something. For instance, you can determine that you actually only need interaction with the red links. So, to increase performance one can toggle on the “Transform Only“ options by the Chain Link Prototypes of the Chain Instructor for the wanted links. Make sure to reinstantiate the chain after altering the prototype settings. Toggle the Transformation Only for the inner and outer link prototypes, as shown below. If we now rerun the previous test, we only see the logs from the “Tow” links.
You can also change the Fixed Timestep of the Unity simulation to increase performance. It can be found under Edit → Project Settings → Time.
Prespective Documentation