Follow

©2017 by Dana Steinhoff. Proudly created with Wix.com

Archive

Please reload

Tags

Please reload

Creating a Dynamic System for Linear Dialogue - Design (Part 2)

April 15, 2018

 Spirit Island Development Update: For my third Unity prototype, I created an "interrupt system" for the player to interact with and impact a linear dialogue chain. The goal is for the player to feel like less of an observer and more of an active participant during a dialogue scene.

 

Part 1: Inspiration + Research

Part 2: Design

Part 3: Postmortem

 

The “cop car scene” is where I’ve tested out my own “interruption system.” The Sheriff is taking Emma to her father’s house to allow her to do some sleuthing of her own as to the nature of her father’s disappearance. They have some time to kill, so the Sheriff keeps up a (very long-winded) conversation. In this time, the player can sit and politely listen, or turn their attention to objects in the environment, triggering their own thoughts in the process.

 

My system is different, however, than the systems I mentioned in Part 1 of this post. It “tunes out” rather than pauses the conversation when the protagonist’s attention turns elsewhere. As the player, looking at an artifact in the backseat quiets the Sheriff’s voice and brings the PC’s internal monologue to the forefront. The Sheriff notices the lack of attention and calls the PC out, and the PC always politely apologizes and picks the conversation back up.

 

Why, again, am I doing this?

 

I want to get the player to feel like their actions affect the game world, even during a linear conversation chain. The "interrupt system" also allows for multiple playstyles: one player might politely sit through the entire conversation, while another might quickly grow impatient, turning their attention instead to the objects in the room.

 

There are a few challenges that I foresee with my system:

  1. I have to make sure that the player doesn’t need the information in the dialogue if I allow them to skip it.

  2. Players might be hesitant to skip any of the intentionally long-winded dialogue if they are not properly led away from believing that it is information necessary to the progression of the story.

 

The scene that I created for this prototype is the opening of an early episode. Is it therefore highly expository, and necessarily so, as it's meant to fill the player in on the world and the objective. This means that I must be clever and intentional about how I place the information within the scene to ensure that it gets communicated. 

 

There are two strategies that I’m going to use:

  • Make sure that the information is available in multiple places within the scene: ie., within the dialogue and written into an interactable artifact.

  • Frontload important information, in case the player’s attention teeters off.

 

A bonus? Conversations can be longer. The characters can be more indulgent in their digressions. The player is never held hostage by the conversation, so the dialogue could be seen as optional additional worldbuilding as opposed to only a mercenary info-dump.

Story Context + Design

I made a list of all of the information that must be transmitted to the player in the course of the scene before I wrote out the dialogue. This is what I decided that the player needs to know:

  • Emma has recently arrived to town and is looking for her father Monty.

  • Monty has been missing for six weeks.

  • The driver is the Sheriff.

  • The Sheriff is driving Emma to her father’s house on Spirit Island to do some investigating on her own.

  • Emma is 18 years old and has never met her father.

  • Emma’s objective: Investigate the disappearance of her father.

 

The emboldened, italicized item is the most important piece of information to get across, but, then again, they all feel pretty important. I wrote the dialogue, and - because it is technically optional - allow myself to make it long. In hindsight, I should’ve made it shorter from the get-go, but at this point I was being indulgent.

 

I created three artifacts for the player to interact with in the backseat that would reinforce the narrative:

  1. An aged photograph. The PC remarks: “This is the photo I found in my

     

    mother’s attic that showed me where to look for my dad.”

  2. Printed-out GoogleMap directions: From Chicago to Northern Canada.

  3. A letter, to which the PC comments: “This is what I’m going to say to my dad when I finally meet him. I must’ve written it over a dozen times.”

In the design of the game, the dialogue will wrap up neatly once the player has looked at all of the objects. The player will then be delivered to Spirit Island, prepping them to begin the next chapter, and the Introduction will be finished.

 

Read on the Part 3 to see how it all turned out!

 

Aesthetics

The aesthetic of this prototype is in keeping with the one I chose for my last two prototypes: “Emma’s Big Day Out” and the “Record Puzzle.” The game is made up entirely of 2D images created in a sketchy, black and white style. I created all of the images by hand with ProCreate.

Mechanics + Programming

The basic mechanics remain the same from my previous prototypes and are recognizable for any adventure-game players: double-tap to interact, pinch to zoom out.

 

Here is the code for the “interruption system” which I loaded up with comments:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IntroVOScript : MonoBehaviour {

    //When dragging the audio files into the array spots in the inspector, must make sure that they are in order that they will appear.
    public AudioClip [] sheriffClips;
    public AudioClip [] emmaClips;
    public AudioClip [] interruptClips;
    public AudioClip wereHereClip;
    public Queue<AudioClip> dialogueQueue;
    public Queue<AudioClip> interruptQueue;

    //Set what the volume of the dimmed VO should be
    float dimmedVolume = 0.4f;
    float normalVolume;
    bool pauseQueue = false;

    AudioSource audioComp;

    public enum State {
        SheriffTalking,
        EmmaTalking,
        Interrupted
        };

    public State currentState = State.SheriffTalking;

    void Start () {
        audioComp = GetComponent<AudioSource>();
        normalVolume = audioComp.volume;

        CreateVOQueue();
        PlayVOAudio();
    }

    }

    void CreateVOQueue(){
        dialogueQueue = new Queue<AudioClip>();

        int numberOfSheriffClips = sheriffClips.Length;
        //This "loads up" the queue, alternating between the Sheriff and Emma's lines.
        for ( int i = 0; i < numberOfSheriffClips; i++)
        {
            if(sheriffClips[i] != null)    dialogueQueue.Enqueue(sheriffClips[i]);
            if(emmaClips[i] != null)    dialogueQueue.Enqueue(emmaClips[i]);

        }

        //This "loads up" the queue of interrupt audio clips
        interruptQueue = new Queue<AudioClip>();
        for (int i = 0; i < 3; i++)
        {
            interruptQueue.Enqueue(interruptClips[i]);
        }
    }

    void PlayVOAudio(){

        //Do this first to avoid error messages
        if(dialogueQueue.Count > 0)
        {
            //If interrupt dialogue is still running, do not activate the next audio clip in the queue.
            if(currentState == State.Interrupted && pauseQueue) return;

            if(currentState == State.Interrupted && !pauseQueue)
            {
                //take out the next Interrupt bit of dialogue, then place it at the back of the line
                //(In case we cycle through and need to use it again)
                AudioClip thisClip = interruptQueue.Dequeue();
                interruptQueue.Enqueue(thisClip);

                //Play the interrupt audio clip
                audioComp.clip = thisClip;
                float clipLength = thisClip.length;
                StartCoroutine(PlayClip(clipLength));
            }

            else {
                //take the next item in the queue and set it as the active clip
                AudioClip thisClip = dialogueQueue.Dequeue();
                audioComp.clip = thisClip;
                //Find the length of the clip and pass it into the coroutine
                float clipLength = thisClip.length;
                StartCoroutine(PlayClip(clipLength));
            }
        }
    }

    IEnumerator PlayClip(float clipLength)
    {
        //Play the clip
        audioComp.Play();

        //Wait until the clip is over, plus a buffer in between lines.
        yield return new WaitForSecondsRealtime(clipLength + .3f);

        //At the end of the clip, switch who's talking.
        if(currentState == State.SheriffTalking) currentState = State.EmmaTalking;
        if(currentState == State.EmmaTalking) currentState = State.SheriffTalking;

        //Then automatically play the next clip
        PlayVOAudio();
    }

    public void Interrupt (float clipLength){
        StartCoroutine(InterruptCo(clipLength));
    }

    //Scripts attached to other objects will trigger this when tapped
    IEnumerator InterruptCo(float artifactVOClipLength){

        //if sheriff is talking, dim the sheriff's talking until the artifact VO is over.
        if(currentState == State.SheriffTalking)
        {
            //This makes sure that PlayVOAudio() won't keep the regular conversation rolling
            pauseQueue = true;
            currentState = State.Interrupted;
            //dim this audioSource for the length of time of the artifact VO
            //(Artifact VO is handled by a different audioSource connected to the artifact itself)
            audioComp.volume = dimmedVolume;
            //Wait until the artifact VO is over
            yield return new WaitForSecondsRealtime(artifactVOClipLength);
            //Return dialogue VO to normal volume and play the next clip in the queue
            pauseQueue = false;
            audioComp.volume = normalVolume;

            //If the queue has already stopped, start playing it again.
            //Otherwise it will reactivate itself in the PlayAudioVO()
            if(!audioComp.isPlaying) PlayVOAudio();
        }
    }

}

 

 

 

 

 

 

 

 

 

 

Please reload

Recent Posts

Please reload