Goal: Learn how to create a MotionWeb for a Crane using the ActorMotionPathGraph tool
Video Tutorial: https://www.youtube.com/watch?v=1ois7rwUZ3Q
Tip: Watch the video on YouTube in FullScreen mode and use HD quality (settings) to read the script clearly!
https://www.youtube.com/watch?v=1ois7rwUZ3QIntroduction
This tutorial explains how you can create an ActorMotionPathGraph to control a crane where the Horizontal, Vertical and Rotator actors are dependent on each other. This ActorMotionPathGraph will be used in the next tutorial called “CranePickupAndDropoff” (https://unit040.atlassian.net/wiki/spaces/PAD/pages/2099216385)
Scene
The scene hierarchy consists of the following components:
DES Controller: Controls the simulation and therefore has to be at the top of the hierarchy
CraneInstructor: Controls the three crane actors according to the sequence in the CraneInstructor script and is of type MotionWebInstructor.
CraneRotatorActor: The top part of the crane that will rotate (vertical tower and horizontal boom) and that sits on the base. It has two children, the CraneVerticalActor and CraneHorizontalActor and is of type MotionWebActor.
CraneVerticalActor: The fixed horizontal boom with its child the CraneHorizontalActor. This child is the moving telescopic horizontal boom. Is of type MotionWebActor.
CraneHorizontalActor: The moving telescopic horizontal boom with its child the VacuumGripper. Is of type MotionWebActor.
MotionWebHorizontal: Spline web with cues that the CraneHorizontalActor can move over. Created by the ActorMotionPathGraph.
MotionWebVertical: Spline web with cues that the CraneVerticalActor can move over. Created by the ActorMotionPathGraph.
MotionWebRotator: Spline web with cues that the CraneRotatorActor can move over. Created by the ActorMotionPathGraph.
ActorMotionPathGraph
The following ActorMotionPathGraph is used for this tutorial.
Scripts
CraneInstructor Script
Script 1 The CraneInstructor script that controls the actors in the MotionWeb
using System.Collections.Generic; using u040.prespective.prescripted.des; using u040.prespective.prescripted.des.events; using u040.prespective.prescripted.des.motionweb; using UnityEngine; namespace u040.prespective.demos.actorMotionPathGraph { //Define as MotionWebInstructor to use the ActorMotionPathGraph public class CraneInstructor : MotionWebInstructor { //Used to start the sequence only once bool started = false; //Function that runs every frame public override void OnSimulationFrameUpdate(double _passedFrameTime, double _totalFrameTime, long _frameID, int _framePass, ref List<DESEvent> _resultingEvents, ref List<DESRecord> _resultRecords) { //Exit if simulator is not running or sequence has already started if (_framePass <= 0 || started) { return; } //Make sure sequence is only started once started = true; //Look up MotionWebActors in the scene CraneRotatorActor _rotator = this.GetMotionWebActorsByType<CraneRotatorActor>()[0]; CraneVerticalActor _vertical = this.GetMotionWebActorsByType<CraneVerticalActor>()[0]; CraneHorizontalActor _horizontal = this.GetMotionWebActorsByType<CraneHorizontalActor>()[0]; Debug.Log("START STATEMACHINE"); //Statemachine Sequence MotionWebInstructionSequence _sequence = new MotionWebInstructionSequence() { SequenceID = "CraneSequence", OnSequenceComplete = null, Verbose = false, InstructionSteps = new List<MotionWebInstructionStep>() { //1: To VerticalTop MotionWebInstructionStep.GetStepWithMotionVelocity( "1_VerticalTop", //Name .1d, //Velocity _vertical, //Actor "CUE_VerticalTop" //Target cue ), //2: To HorizontalIn MotionWebInstructionStep.GetStepWithMotionVelocity( "2_HorizontalIn", //Name .1d, //Velocity _horizontal, //Actor "CUE_HorizontalIn", //Target cue new List<string>(){ "1_VerticalTop" } //Previous step ), //3: To RotationPickup MotionWebInstructionStep.GetStepWithMotionVelocity( "3_RotateToPickup", //Name .5d, //Velocity _rotator, //Actor "CUE_RotatePickup", //Target cue new List<string>(){ "2_HorizontalIn" } //Previous step ), //4: To HorizontalOut MotionWebInstructionStep.GetStepWithMotionVelocity( "4_HorizontalOut", //Name .1d, //Velocity _horizontal, //Actor "CUE_HorizontalOut", //Target cue new List<string>(){ "3_RotateToPickup" } //Previous step ), //5: To VerticalBottom (PICKUP) MotionWebInstructionStep.GetStepWithMotionVelocity( "5_VerticalBottom", //Name .1d, //Velocity _vertical, //Actor "CUE_VerticalBottom", //Target cue new List<string>(){ "4_HorizontalOut" } //Previous step ), //6: To VerticalTop MotionWebInstructionStep.GetStepWithMotionVelocity( "6_VerticalTop", //Name .1d, //Velocity _vertical, //Actor "CUE_VerticalTop", //Target cue new List<string>(){ "5_VerticalBottom" } //Previous step ), //7: To HorizontalIn MotionWebInstructionStep.GetStepWithMotionVelocity( "7_HorizontalIn", //Name .1d, //Velocity _horizontal, //Actor "CUE_HorizontalIn", //Target cue new List<string>(){ "6_VerticalTop" } //Previous step ), //8: To RotationDropoff MotionWebInstructionStep.GetStepWithMotionVelocity( "8_RotateToDropoff", //Name .5d, //Velocity _rotator, //Actor "CUE_RotateDropoff", //Target cue (one exit) new List<string>(){ "7_HorizontalIn" } //Previous step ), //9: To HorizontalOut MotionWebInstructionStep.GetStepWithMotionVelocity( "9_HorizontalOut", //Name .1d, //Velocity _horizontal, //Actor "CUE_HorizontalOut", //Target cue new List<string>(){ "8_RotateToDropoff" } //Previous step ), //10: To VerticalBottom (DROPOFF) MotionWebInstructionStep.GetStepWithMotionVelocity( "10_VerticalBottom", //Name .1d, //Velocity _vertical, //Actor "CUE_VerticalBottom", //Target cue new List<string>(){ "9_HorizontalOut" } //Previous step ), //11: To VerticalTop MotionWebInstructionStep.GetStepWithMotionVelocity( "11_VerticalTop", //Name .1d, //Velocity _vertical, //Actor "CUE_VerticalTop", //Target cue new List<string>(){ "10_VerticalBottom" } //Previous step ), //12: To HorizontalIn MotionWebInstructionStep.GetStepWithMotionVelocity( "12_HorizontalIn", //Name .1d, //Velocity _horizontal, //Actor "CUE_HorizontalIn", //Target cue new List<string>(){ "11_VerticalTop" } //Previous step ), //13: To RotationPickup MotionWebInstructionStep.GetStepWithMotionVelocity( "13_RotateToPickup", //Name .5d, //Velocity _rotator, //Actor "CUE_RotatePickup", //Target cue new List<string>(){ "12_HorizontalIn" } //Previous step ) } //InstructionSteps }; //Sequence //Register the sequence InstructionSequences.Add(_sequence); //Start the sequence _sequence.StartSequence(this, _passedFrameTime); //NOT NEEDED //base.OnSimulationFrameUpdate(_passedFrameTime, _totalFrameTime, _frameID, _framePass, ref _resultingEvents, ref _resultRecords); } //OnSimulationFrameUpdate } //class } //namespace
CraneRotatorActor Script
Script 2 The CraneRotatorActor script that defines this actor to be a MotionWebActor so it can move around in the MotionWeb
using u040.prespective.prescripted.des.motionweb; namespace u040.prespective.demos.actorMotionPathGraph { //Must be of MotionWebActor class to be used in the ActorMotionPathGraph public class CraneRotatorActor : MotionWebActor { } }
CraneVerticalActor Script
Script 3 The CraneVerticalActor script that defines this actor to be a MotionWebActor so it can move around in the MotionWeb
using u040.prespective.prescripted.des.motionweb; namespace u040.prespective.demos.actorMotionPathGraph { //Must be of MotionWebActor class to be used in the ActorMotionPathGraph public class CraneVerticalActor : MotionWebActor { } }
CraneHorizontalActor Script
Script 4 The CraneHorizontalActor script that defines this actor to be a MotionWebActor so it can move around in the MotionWeb
using u040.prespective.prescripted.des.motionweb; namespace u040.prespective.demos.actorMotionPathGraph { //Must be of MotionWebActor class to be used in the ActorMotionPathGraph public class CraneHorizontalActor : MotionWebActor { } }
Playmode
Watch the video above to see what happens when we press play. The CraneInstructor starts moving the three crane actors according the statemachine sequence and stops at the end of the sequence.