Writing Custom Sequencer for Movement
-
- Posts: 111
- Joined: Mon Apr 08, 2019 8:01 am
Writing Custom Sequencer for Movement
Hi,
I'm looking at trying to make a cutscene with Dialogue System now and had a couple of questions regarding sequencer commands.
1.
I'm trying to write a custom sequencer command that will interact with the game's physics engine to enable an NPC to walk to a certain point in the middle of a conversation I'm not sure how to do this- I understand from the documentation that there is a GetParameter command but I'm not really sure how to use it. I know I need to get a reference to a input component in the NPC that controls its movement.
2.
I haven't really looked into getting this working yet, but I'd like to play/loop two different animation states within one dialogue node. For example, the NPC says a line, then starts mining or something. The two animation states I need is a 'windup' or preparatory animation that transitions into a looping mining animation. I've managed to get animations to play using the AnimatorPlay function but haven't really done any research on getting this to work aside from looking at the documentation.
Any wisdom you might have on this is appreciated. Thanks!
I'm looking at trying to make a cutscene with Dialogue System now and had a couple of questions regarding sequencer commands.
1.
I'm trying to write a custom sequencer command that will interact with the game's physics engine to enable an NPC to walk to a certain point in the middle of a conversation I'm not sure how to do this- I understand from the documentation that there is a GetParameter command but I'm not really sure how to use it. I know I need to get a reference to a input component in the NPC that controls its movement.
2.
I haven't really looked into getting this working yet, but I'd like to play/loop two different animation states within one dialogue node. For example, the NPC says a line, then starts mining or something. The two animation states I need is a 'windup' or preparatory animation that transitions into a looping mining animation. I've managed to get animations to play using the AnimatorPlay function but haven't really done any research on getting this to work aside from looking at the documentation.
Any wisdom you might have on this is appreciated. Thanks!
Re: Writing Custom Sequencer for Movement
Hi,
I'll answer #2 first, since you can do that without writing a custom sequencer command. Let's say the animations are in an animator controller, and the animation states are named "MiningWindup" and "Mining".
You could always create a transition in your animator controller from MiningWindup to Mining. Then you'd simply need to play MiningWindup with a Sequence like this:
I added {{default}} so it would include the Dialogue Manager's Default Sequence, which typically delays for a duration. You can add something else if you want.
Let's say you have a Boolean animator parameter named "IsMining". When it's true, the animator controller transitions to the MiningWindup state, which then automatically transitions to Mining. When IsMining is false, the Mining state transitions back to Idle. In this case, you'd use a Sequence like this:
However, if you have neither animator paramters nor transitions, you can control both animations from the Sequence itself:
The first command plays the MiningWindup state and waits for it to finish. When it's finished, it sends an arbitrary message ("ReadyToLoop") to the sequencer. The second command waits for the sequencer to receive the message "ReadyToLoop"; then it plays the Mining state.
You can also send messages to the sequencer from your own C# code. Let's say you want the NPC to stay on that node until they mine a gold nugget. You can set the Sequence to something like:
In this example, the first command plays MiningWindup; I'll assume it transitions automatically to the Mining loop. I'll explain the second command in a moment. The third command waits for the sequencer to receive the message "GotNugget". Then it plays an animator state named "Celebrate". At this point the sequence ends, so the conversation can proceed to the next node.
The second command uses Unity's SendMessage method to call any method named StartMining() on any scripts on the NPC. Let's say you have a script with a StartMining() method that delivers a gold nugget after a random duration. When it delivers the gold nugget, use Sequencer.Message("GotNugget") to tell the sequencer. The C# method might look like:
This is total aside: (Even more than the asides above! )
If you want to get super fancy, let's say the NPC cycles through several jobs (mining, hauling, stretching, etc.). You could put the job's animator state name in a Dialogue System variable. Let's say that variable is named "currentJob". Then you can use a Sequence like this:
The special tag [var=currentJob] will be replaced by the value of the currentJob variable. You can get even more elaborate and use the [lua(code)] tag to replace it with the result of any Lua code, even your own C# methods that you've registered with Lua.
I'll answer #2 first, since you can do that without writing a custom sequencer command. Let's say the animations are in an animator controller, and the animation states are named "MiningWindup" and "Mining".
You could always create a transition in your animator controller from MiningWindup to Mining. Then you'd simply need to play MiningWindup with a Sequence like this:
Code: Select all
AnimatorPlay(MiningWindup); {{default}}
Let's say you have a Boolean animator parameter named "IsMining". When it's true, the animator controller transitions to the MiningWindup state, which then automatically transitions to Mining. When IsMining is false, the Mining state transitions back to Idle. In this case, you'd use a Sequence like this:
Code: Select all
AnimatorBool(IsMining, true); {{default}}
Code: Select all
AnimatorPlayWait(MiningWindup)->Message(ReadyToLoop);
AnimatorPlay(Mining)@Message(ReadyToLoop);
{{default}}
You can also send messages to the sequencer from your own C# code. Let's say you want the NPC to stay on that node until they mine a gold nugget. You can set the Sequence to something like:
Code: Select all
AnimatorPlay(MiningWindup);
SendMessage(StartMining);
AnimatorPlayWait(Celebrate)@Message(GotNugget)
The second command uses Unity's SendMessage method to call any method named StartMining() on any scripts on the NPC. Let's say you have a script with a StartMining() method that delivers a gold nugget after a random duration. When it delivers the gold nugget, use Sequencer.Message("GotNugget") to tell the sequencer. The C# method might look like:
Code: Select all
public void StartMining()
{
Invoke("GenerateNugget", Random.Range(1, 5);
}
void GenerateNugget()
{
// <your code here to spawn a gold nugget>
PixelCrushers.DialogueSystem.Sequencer.Message("GotNugget");
}
If you want to get super fancy, let's say the NPC cycles through several jobs (mining, hauling, stretching, etc.). You could put the job's animator state name in a Dialogue System variable. Let's say that variable is named "currentJob". Then you can use a Sequence like this:
Code: Select all
AnimatorPlay([var=currentJob]); {{default}}
Re: Writing Custom Sequencer for Movement
To answer #1:
To make a custom sequencer command, copy the template from Plugins / Pixel Crushers / Dialogue System / Templates / Scripts. Fill in your code where indicated.
These functions are available in your script: SequencerCommand
Skip past all the "Inherited by" text until you get to the "Protected Member Functions" section.
If you want to get the first parameter as a string:
If you want to get it as an integer:
If you want a reference to the node's speaker GameObject, it's the speaker property.
To make a custom sequencer command, copy the template from Plugins / Pixel Crushers / Dialogue System / Templates / Scripts. Fill in your code where indicated.
These functions are available in your script: SequencerCommand
Skip past all the "Inherited by" text until you get to the "Protected Member Functions" section.
If you want to get the first parameter as a string:
Code: Select all
string firstParameter = GetParameter(0);
Code: Select all
int firstParameter = GetParameterAsInt(0);
-
- Posts: 111
- Joined: Mon Apr 08, 2019 8:01 am
Re: Writing Custom Sequencer for Movement
Hey Tony,
I was able to generate the custom command using the template but I'm still a little bit confused about the parameters right now. How do they work in particular? I'm not really understanding how I can generate parameters and use them to interface with the component I need. Actually, I'm not really sure what a parameter is right now :V
Could you go into a bit more detail as to what I need to do?
Thanks
I was able to generate the custom command using the template but I'm still a little bit confused about the parameters right now. How do they work in particular? I'm not really understanding how I can generate parameters and use them to interface with the component I need. Actually, I'm not really sure what a parameter is right now :V
Could you go into a bit more detail as to what I need to do?
Thanks
Re: Writing Custom Sequencer for Movement
Hi,
When you enter a command like this in the Script field of a node:
The values "ForceField" and "true" are parameters. "ForceField" is parameter 0 and "true" is parameter 1.
The C# implementation of the SetActive sequencer command looks a bit like this:
The actual implementation is different. I simplified it above for clarity.
When you enter a command like this in the Script field of a node:
Code: Select all
SetActive(ForceField, true)
The C# implementation of the SetActive sequencer command looks a bit like this:
Code: Select all
void Awake()
{
string subjectName = GetParameter(0); // Get parameter 0 as a string.
bool value = GetParameterAsBool(1); // Get parameter 1 as a bool.
GameObject subject = GameObject.Find(subjectName);
subject.SetActive(value);
}
-
- Posts: 111
- Joined: Mon Apr 08, 2019 8:01 am
Re: Writing Custom Sequencer for Movement
Hey Tony,
Thanks for clearing that up. I think I understand how to use parameters now. I had issues with getting the controller component to reference properly but moving the script into a different folder fixed it for some reason.
Thanks!
Thanks for clearing that up. I think I understand how to use parameters now. I had issues with getting the controller component to reference properly but moving the script into a different folder fixed it for some reason.
Thanks!
Re: Writing Custom Sequencer for Movement
Strange that moving the file got it to reference properly, but maybe it just needed a recompile. Anyway, glad it's working now!
-
- Posts: 111
- Joined: Mon Apr 08, 2019 8:01 am
Re: Writing Custom Sequencer for Movement
Just a couple more questions regarding the sequencer, I've managed to get the character to walk as required. I also turned the dialogue panel off with SetDialoguePanel(false) while they were walking and it was great to see that the conversation didn't end when the panel went away.
However I'd like to progress it to the next node of the conversation once they have finished walking and restore the panel once this is done. I tried using the messages as covered in the documentation. The sequencer command looks like this.
However when the message sends Unity throws an error: Coroutine couldn't be started because the the game object 'Subtitle Panel' is inactive!
Do you have any ideas?
However I'd like to progress it to the next node of the conversation once they have finished walking and restore the panel once this is done. I tried using the messages as covered in the documentation. The sequencer command looks like this.
Code: Select all
WalkToPoint(Owen, 1, 4, true);
SetDialoguePanel(false);
SetDialoguePanel(true)@Message(FinishedWalking);
Continue()@Message(FinishedWalking)
Do you have any ideas?
Re: Writing Custom Sequencer for Movement
Hi,
If you're not using version 2.2.4, please back up your project and update. I believe that was fixed in 2.2.4.
If you're not using version 2.2.4, please back up your project and update. I believe that was fixed in 2.2.4.
-
- Posts: 111
- Joined: Mon Apr 08, 2019 8:01 am
Re: Writing Custom Sequencer for Movement
Hey,
I've updated to 2.2.4 as required. The debug error went away but the issue persists. I can see that the next node of the conversation is indeed highlighted, it's just not showing up.
I've updated to 2.2.4 as required. The debug error went away but the issue persists. I can see that the next node of the conversation is indeed highlighted, it's just not showing up.