WIP 01 | Conveyor System Simulation
Goal: Learn how to use Conveyors in the simulation
In this tutorial we learn how to use Conveyor in the simulation. Conveyors can manage Actors on a Spline and control their velocities. This can make sure that all Actors on a Spline move at the exact same velocity at all times.
In the scene we are using we have a single Spline with three different Cues and Instructors. There are Cues and Instructors for spawning Actors, destroying Actors and for the Conveyor, which will manage the Actors.
ConveyorInstructor script
#if PRESPECTIVE_SOURCE || ALPHA
using System.Collections.Generic;
using u040.prespective.math.doubles;
using u040.prespective.prescripted.des;
using u040.prespective.prescripted.des.activities.motiontensor;
using u040.prespective.prescripted.des.buffers.materialbuffer;
using u040.prespective.prescripted.des.events;
using u040.prespective.prescripted.des.instructors;
using u040.prespective.prescripted.des.participant.actor;
using u040.prespective.prescripted.des.participant.cue;
namespace u040.prespective.tutorials.desintermediate
{
/// <summary>
/// Demo script to show how a Conveyor controls the velocity of all Actors on a Spline
/// </summary>
public class ConveyorInstructor : DESInstructor
{
/// <summary>
/// The velocity at which the Conveyor moves Actors
/// </summary>
public double ConveyorVelocity = 1d;
/// <summary>
/// The Conveyor Material Buffer controls the velocity for all Actors on the Conveyor
/// </summary>
private ConveyorMaterialBuffer materialBuffer;
/// <summary>
/// OnSimulationStart is run once at the start of the simulation. Any preparations necessary for the simulation can be done here.
/// </summary>
/// <param name="_resultingEvents">Container for the events that are calculated during start (they are invoked after the start on all simulated objects are completed)</param>
/// <param name="_resultRecords">Container for the records that are created during start (they are processed for events after the start on all simulated objects are completed)</param>
public override void OnSimulationStart(ref List<DESEvent> _resultingEvents, ref List<DESRecord> _resultRecords)
{
// Create a new Conveyor Material Buffer. This will manage the velocities of Actors within the Material Buffer. Since Material Buffer spans the entire Spline length, this covers the entire Conveyor.
materialBuffer = new ConveyorMaterialBuffer("Conveyor Material Buffer", SimulationController, Cues[0].OwnerSpline, new DVector2(0d ,1d), null, null);
base.OnSimulationStart(ref _resultingEvents, ref _resultRecords);
}
/// <summary>
/// OnSimiluationFrameUpdate is called once every frame pass update
/// </summary>
/// <param name="_passedFrameTime">The passed time in the current frame</param>
/// <param name="_totalFrameTime">The total time of a single frame</param>
/// <param name="_frameID">The ID of the current frame</param>
/// <param name="_framePass">The current frame pass count</param>
/// <param name="_resultingEvents">Container for the events that are calculated during start (they are invoked after the start on all simulated objects are completed)</param>
/// <param name="_resultRecords">Container for the records that are created during start (they are processed for events after the start on all simulated objects are completed)</param>
public override void OnSimulationFrameUpdate(double _passedFrameTime, double _totalFrameTime, long _frameID, int _framePass, ref List<DESEvent> _resultingEvents, ref List<DESRecord> _resultRecords)
{
// If the Conveyor velocity does not match the Material Buffer current velocity, set the Material Buffer velocity to match the Conveyor velocity
if (materialBuffer.CurrentVelocity != ConveyorVelocity)
{
materialBuffer.SetConveyorVelocity(ConveyorVelocity, _passedFrameTime);
}
base.OnSimulationFrameUpdate(_passedFrameTime, _totalFrameTime, _frameID, _framePass, ref _resultingEvents, ref _resultRecords);
}
/// <summary>
/// Add an Actor to the Conveyor
/// </summary>
/// <param name="_actor">The intersecting Actor</param>
/// <param name="_cue">The intersecting Cue</param>
/// <param name="_intersectionEvent">Detailed information about the intersection</param>
/// <returns>Whether this Instructors' response was breaking, thus requiring the simulation to recalculate behavior in this simulation frame from this point in time in the simulation</returns>
public override bool ApplyInstruction(ADESActor _actor, ADESCue _cue, ActorCueIntersectionEvent _intersectionEvent)
{
// Only apply instructions for Actors that enter this Cue
if(_intersectionEvent.IntersectionType != ActorCueIntersectionEvent.CueIntersectionType.Enter && _intersectionEvent.IntersectionType != ActorCueIntersectionEvent.CueIntersectionType.ForcedEnter)
{
return false;
}
// Actors that have entered the Conveyor will be added to the Conveyor as a result. This means that their velocities are now controlled by the Material Buffer.
materialBuffer.AddActorToConveyor(_actor, _intersectionEvent.EventTime, _intersectionEvent.ActorCenterMotionIntersection, _removeAllCurrentMotionTensorsOnActor: true);
return true;
}
}
}
#endif
public class ConveyorInstructor : DESInstructor
{
/// <summary>
/// The velocity at which the Conveyor moves Actors
/// </summary>
public double ConveyorVelocity = 1d;
/// <summary>
/// The Conveyor Material Buffer controls the velocity for all Actors on the Conveyor
/// </summary>
private ConveyorMaterialBuffer materialBuffer;
...
The Conveyor Instructor is a DESInstructor. This was it will receive the simulation events such as OnSimulationStart
and OnSimulationFrameUpdate
.
It has a public property ConveyorVelocity
. This is the velocity at which all Actors on the Conveyor will move. The private property materialBuffer
is the underlying code that will actually manage those Actors and their velocities.
public override void OnSimulationStart(ref List<DESEvent> _resultingEvents, ref List<DESRecord> _resultRecords)
{
// Create a new Conveyor Material Buffer. This will manage the velocities of Actors within the Material Buffer. Since Material Buffer spans the entire Spline length, this covers the entire Conveyor.
materialBuffer = new ConveyorMaterialBuffer("Conveyor Material Buffer", SimulationController, Cues[0].OwnerSpline, new DVector2(0d ,1d), null, null);
base.OnSimulationStart(ref _resultingEvents, ref _resultRecords);
}
During the OnSimulationStart
the Conveyor Material Buffer is generated. It requires parameters to describe on which Spline it should operate, where on that Spline to operate and how to handle certain events. This is the most simple setup which simply describes to manage an entire Spline without any event handling.
During the OnSimulationFrameUpdate
the Conveyor Instructor checks whether its Conveyor Velocity still matches the velocity set for the Conveyor Material Buffer. If this is not the case, it will make sure to update this value to match the two. Doing this forces the Conveyor Material Buffer to update the velocity for all Actors currently within the range of operation.
The ApplyInstruction
method only applies instructions to (forced) enter events.
As soon as an Actor enters die Cue area, this Instructor tries to apply its instruction. The Actor is then added and registered to the Conveyor. From this point on the Conveyor (Material Buffer) controls the velocity of the Actor.
Play Mode
When we press play, Actors will be spawned on the Spline. Upon spawning, they are immediately registered to the Conveyor at which point the Conveyor will control their velocities. The Conveyor is set to a Conveyor Velocity of 0.3 m/s, so Actors will move over the Spline at that velocity. Changing the Conveyor Velocity value will also change the velocity at which Actors will move over the Spline.
Prespective Documentation