Forum rules - please read before posting.

Skipping two action lists that (supposedly) run sequentially = issues.

edited July 2018 in Technical Q&A
Hi there,

Let's say I have two action lists that run sequentially. That is, the second one is called by the first one with a Run ActionList action at the end of it. Also, that action doesn't have the option "wait until finished" checked on, so I'm taking for granted that the first one is already ended when the second one starts.

In short, my problem is that when I skip the second one, it actually re-executes all the actions of the first action list.

That shouldn't be happening, right? Or it's me not understanding how this actually works?

Thank you.

Comments

  • In which AC version?

    If both the ActionLists have a When running field of Block Gameplay, and Is skippable? is checked, then that's the expected behaviour.  The "skippable block" isn't determined by the ActionList being run at the time, but instead the period during which the game is considered in "Cutscene" mode.

    The re-execution of Actions through skipping should largely be a non-issue if they've already run - the exceptions being variable increments etc for which there are failsafes built-in.  What's the actual problem you're experiencing as a result of this?
  • Oh sorry, I didn't notice there's no profile signature anymore. I have Unity 5.5.3f1 and AC 1.60.7. Last time I tried to update, issues ensued, so I'd prefer to stay in there unless really needed.

    The difference I see is that "Block Gameplay" is called "Pause Gameplay" in my version. I don't know if that matters or not.

    At any rate, what you say about the "skippable block not determined by the current action list explains why I'm experiencing this problem, but let me elaborate on my scenario.

    First of all, and very important, is the fact that I'm using Dialogue System 1.8.4 with its AC third-party module running. It adds some special actions to AC, such as running LUA scripts and starting conversations (DS ones, not AC).

    My typical cutscene flow consists of...:
    1. Interaction (skippable): player character walks from point A to point B
    2. Cutscene (non-skippable): a Dialogue System convo takes place at point B
    3. Cutscene (skippable): player character continues from point B to point C
    4. Player regains control
    Mind that this is a VERY simplified version of what they actually are. Nevertheless, the common point is that a "DS convo start" action is always in the middle of the cutscene flow.

    You could say there's a "pre-conversation" cutscene (an interaction, actually) and a "post-conversation" one. And each of those should be skippable on their own. That is, pressing the skip key during 1 should skip to 2, and skipping in 3 should only skip to the end of 3.

    Another thing to note is that the conversation is not skippable, not in AC nor in Dialogue System, so we're talking about two skips for actually skipping the whole cutscene.

    Now, I've been experimenting for some time with this.

    In my first test, I've put some simple actions in ONE interaction action list...:
    1. Walk to a marker
    2. Fade out 1 sec
    3. Fade in 1 sec
    4. Run a DS conversation
    1-3 ran ok when skipping, but 4 didn't, so the conversation never starts.

    I suspect not all third-party actions are fully supported for skip logic... (?)

    Then I opted to make another cutscene (non-skippable) with just the conversation start action, and put a "Run action list" (wait until finished disabled) action at the end of the first, pointing to the second. That worked and the conversation was executed.

    Third test. I marked the conversation start action in the second action list to "wait until finished" and added another (non-waiting) "run action list" action pointing to the third (skippable) action list that makes the character to walk to a point again.

    Okay, that was when things went to hell: the whole thing was run again, so the conversation was started again and I obviously don't want that.

    I thought at first that when you pressed "skip" only the current action list was skipped. But now that you said it's not like that, what I imagine it's happening is that AC needs to detect it is no longer in Cutscene mode to "forget" about the past cutscene it has been executing. And that's something it can't happen if all cutscenes are executed sequentially.

    So, I devised a solution consisting in marking the second action list start convo action as non-waiting...:

    image

    ...so the dialogue can be started and immediately after the action list ends and the cutscene is deemed as done.

    And for the second part of the action list to actually happen when that conversation is done (now that AC is in Normal state for all purposes), I use a DS sequence command at the end of the conversation...:

    image

    image

    TestAL3 is run and DS doesn't wait for it execute before ending the conversation.

    This works. The second part of the whole event if run and it can be skipped with another key press without the first and second action lists being re-executed.

    However, it also causes some interface problems I'll need to fix (no need to get into details about those, atm).

    Now, this issue I'm having is due to two design aspects on how AC works when skipping...
    • It skips all action lists (running, or yet to be called) with the 'skippable' flag checked if the method is invoked.
    • It re-executes ALL actions from all of those action lists.
    I can understand the reason for the first behavior. What I don't get is why all of those actions are re-run, regardless of the point in which AC is parsing them.

    In my humble opinion, it would be far more desirable to execute only the remaining actions, instead of repeating the already executed and also the remaining ones. The amount of grief that behavior can generate with custom and third-party actions is unsurmountable and much more problematic than just some variable increments.

    Is there a reason for that design?

    Anyway, now that I understand how AC behaves I've managed to work out a not-so-elegant solution consisting in changing the GameState manually at both the conversation start and end, so AC "forgets" about past cutscenes and future one can be skipped on their own. It's not ideal, I admit, but it's working.

    Now I'd only like to know if you'd consider running only the remaining actions when skipping...? 
    • The difference I see is that "Block Gameplay" is called "Pause Gameplay" in my version.
    Apologies - I did mean Pause Gameplay.

    • I suspect not all third-party actions are fully supported for skip logic... (?)
    Not by default, but it's a simple matter of overriding the base class's Skip method, which should command the Action to "complete itself" instantly.  If left blank, then skipping will have no effect.  If left out, then the Action's Run method will be re-run instead.

    • What I don't get is why all of those actions are re-run, regardless of the point in which AC is parsing them. Is there a reason for that design?
    There is indeed - in fact, the first attempts at creating AC's "skip cutscene" feature involved skipping from the current Action onwards.

    The reason is primarily down to the fact that an Action can be considered "complete" without the effects of it also having been so.  For example, if a character is commanded to move somewhere (with Wait until finish? unchecked), then skipping later on in the list doesn't affect that.  He'll either continue on walking once all else has finished, or end up stuck because the list has other movement commands later on.  By re-running the whole sequence "instantly", there's no confusion about where he's supposed to be at each point.  Such issues get even more complex when e.g. parallel chains of Actions are involved - and the order in which Actions are skipped may be different to the order in which they'd be run "naturally".

    There are, however, some ways to work around this when it's inconvenient as in this case.  First of all, the ActionList: Check running Action can be used to determine if the current ActionList is skipping or not.  This could be used at e.g. the start of your DialogueSystem Cutscene to prevent the Actions that follow from being skipped.

    Secondly, as of v1.63.1, there is a new method that allows you to manually clear all skip-related data:

    AC.KickStarter.actionListManager.ResetSkippableData ();

    Calling this removes all knowledge of what ActionLists would need to be skipped in the event that the player decides to skip the current cutscene - similar in effect to quickly entering/exiting the gameplay state.  If you call it just before running the ActionList you want to isolate (i.e. be the only one that gets skipped out of the chain), then it'll forget about all others.

    This will still limit the skipping to the whole ActionList as opposed to the exact Action that's running at that moment - but its feasible that this could be changed by manually updating the "skip data" through custom script.  When the "EndCutscene" input is invoked, it simply runs:

    AC.KickStarter.actionListManager.EndCutscene ();

    Therefore, you could potentially replace this input with one of your own name, listen to it separately, and then perform modifications to the "skip data" before manually running the above method.

    AC keeps track of what's running, and what needs skipping, via instances of the ActiveList class.  Its "skip data" can be controlled via its inSkipQueue and startIndex variables - the latter of which can be set to the exact Action index you want to skip from.  You could, in theory, work out exactly what Action(s) are running at the time you want to skip, amend the data so that only that list, at that index, will be skipped from, and then manually initiate the process.

    Such classes for scene-based ActionLists are stored as a List within the ActionListManager component, and this List is currently private.  I can consider making this publicly accessible if it would assist you.  Certainly the current release includes ResetSkippableData, so I'd recommend (in a backup/duplicate project) testing that first to see if that or the first method is enough.
  • Hi Chris! Thanks for your comprehensive explanation.

    So there is a valid reason for that behavior. Okay, I'll treat skippable cutscenes as whole entities then.

    That new method you mention could prove very useful to have cleaner code than I have now, no doubt. I'll need to wait, though, until I release a new game version before upgrading AC. It's too risky to do it 1-2 days before launch.

    The workaround I'm using now is to call the conversation an isolated non-skippable ActionList (otherwise it doesn't run if skip is pressed):



    Notice it doesn't wait for anything, so then that FSM is run the Cutscene is about to be finished and the conversation started.

    There's a little delay from AC to declare itself in Normal state so that FSM does this...:



    SetCutsceneMode() simply runs...:

    KickStarter.stateHandler.StartCutscene();

    That is, it waits for a Normal state before putting it again in cutscene mode. I need to do this so you can't click on hotspots and walk around during a DS conversation. There probably a more civilized way to do that, but I didn't find it in all these months.

    Anyway, regardless of that, I'm managing more or less decently with that logic. However, now I'm facing another problem and is a big one if I don't manage to find a workaround.

    I have a Dialogue System conversation that calls various ActionLists that make characters doing things (moving, playing animations, etc). The way DS knows when to move on to the next conversation node is to wait for a "Sequence message", more or less like this...:

    DS node:
    image

    AC ActionList ends with...:
    image

    So...

    AC(TakePotUnder2);

    ...tells AC to execute that ActionList, and...

    Continue()@Message(TakePotUnder2_Done);

    ...makes DS wait before continuing until that message is received back, which only happens at the end of the ActionList.

    Now, my problem is that even if that ActionList is marked as skippable, pressing the skip key (Space in my case) doesn't do anything.

    This only happens inside a conversation, so I guess DS must be "intercepting" that keystroke, or maybe AC considers it's not the moment to skip anything.

    I've tried manually putting the GameState to cutscene mode during those waiting periods, but it still doesn't respond. I'm at a loss here, tbh.

    The only way I can think of to make this work would be to end the conversation when calling the ActionList (what I've done with the other cutscenes), then calling it again at the end of the list, instead of resourcing to DS messages. But if I do that, some serious work would be needed, and the resulting workflow would be utter chaos.

    I use DS for pretty much everything related to logic trees, variables, animation control, etc., so if every time I need one character to move, I need to cut the conversation, run the action/s, then return to the appropriate convo node (which is neither a trivial thing), well... I'll suffer... a lot.

    Do you have any leads of why this is happening?

    Thank you!

    Ps.: By the way, I can't modify any Dialogue System scripts, as they actually run from a DLL.

    In version 2.x they're plain text scripts, but I can't upgrade until I get more things done and running.
  • edited July 2018
    • It's too risky to do it 1-2 days before launch.
    Agreed - though the ResetSkippableData method could likely be safely inserted into an earlier release:

    public void ResetSkippableData ()
    {
        ignoreNextConversationSkip = false;
        foreach (ActiveList activeList in activeLists)
        {
            activeList.inSkipQueue = false;
        }
        foreach (ActiveList activeList in KickStarter.actionListAssetManager.activeLists)
        {
            activeList.inSkipQueue = false;
        }

        GlobalVariables.BackupAll ();
        KickStarter.localVariables.BackupAllValues ();
    }

    • KickStarter.stateHandler.StartCutscene();  I need to do this so you can't click on hotspots and walk around during a DS conversation. There probably a more civilized way to do that, but I didn't find it in all these months.
    One thing to bear in mind is that StateHandler's StartCutscene method needs to be paired with its EndCutscene method, because this control's AC's knowledge of a "user-scripted" cutscene state.  It's not intended to be used in conjunction with an ActionList-driven cutscene state - more one or the other.

    The Engine: Manage systems Action can be used to selectively disable each of AC's systems.  If you disable Interactions and Movement, the player won't be able to interact or move even when in a "Normal" game state.  Such locks can also be implemented through script:

    KickStarter.stateHandler.SetInteractionSystem (false);


    • even if that ActionList is marked as skippable, pressing the skip key (Space in my case) doesn't do anything. This only happens inside a conversation
    What's the GameState set to at the time, according to the debug window?  Is anything else mapped to Space?

    Unless the input is intercepted, the ActionListManager's EndCutscene method should be invoked so long as the GameState is Cutscene - regardless of through script or ActionList.  It may be that the way DS is triggering the ActionList to run in the first place is not causing it to become recorded by the ActionListManager as something to skip.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.