Recording Route and Scoring Data

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
LongLeggedOne
Posts: 4
Joined: Sun Jul 17, 2016 9:09 am

Recording Route and Scoring Data

Post by LongLeggedOne »

Greetings,

I am designing a prototype for a conversation simulator to be used as a tool for therapists and their patients. Patients will be scored on several criteria based on their chosen responses as they navigate through each conversation. Currently I have these scores as individual fields on each response dialogue node. My goal is to have the simulator update the scores each time responses are chosen, keeping track of the numbers over time and as totals. I also want to keep a record of the route taken through the conversation, probably as a sequence of visited dialogue node ids. This data then needs to be saved externally for later review. My question is, what might be a good way to go about achieving this using the Dialogue System? Is there any built in functionality that might provide a starting point?

Conversations were originally written in ChatMapper but were imported into Unity when I learned about this addon. Thanks to pixelcrushers for making that such a smooth process, by the way! I've done simple scripting in Unity before but am still relatively new to programming, so I apologize if this question is too basic/broad to be appropriate for this forum.
User avatar
Tony Li
Posts: 21050
Joined: Thu Jul 18, 2013 1:27 pm

Re: Recording Route and Scoring Data

Post by Tony Li »

Hi,

Thanks for using the Dialogue System!

The easiest way to handle both of these is with a couple small scripts.

As you know, the Dialogue System is based on Chat Mapper, and Chat Mapper doesn't provide an easy way to access custom fields in dialogue entries. Instead, I suggest writing a small sequencer command script. For example, the script below adds a sequencer command named "UpdateScores()". Just add UpdateScores() to the Sequence field of your response dialogue entry:
  • Sequence: UpdateScores()

Code: Select all

using UnityEngine;

namespace PixelCrushers.DialogueSystem.SequencerCommands
{

    public class SequencerCommandUpdateScores : SequencerCommand
    {

        public void Start()
        {
            // Look up the response dialogue entry:
            var entry = DialogueManager.CurrentConversationState.subtitle.dialogueEntry;
            Debug.Log("Updating scores for dialogue entry " + entry.id + " (" + entry.DialogueText + ").");
            
            // Get the value of the field named "Score X": (replace with your custom field names)
            var scoreX = Field.LookupInt(entry.fields, "Score X");
            
            // Get the value of the "Total X" variable and increment it:
            var totalX = DialogueLua.GetVariable("Total X").AsInt;
            DialogueLua.SetVariable("Total X", totalX + scoreX);
            
            // (Repeat/adjust for all scores)
            
            // Close out the sequencer command:
            Stop();
        }
    }
}
 

To record the route through a conversation, you can use a small script like the one below, which I based off the Scripts/Supplemental/Utility/ConversationLogger.cs script. Add it to the Dialogue Manager.

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;
using System.Collections.Generic;

// This script records conversation routes in a text file named with the conversation's title and the current timestamp.
public class RecordConversationRoutes : MonoBehaviour
{

    private List<string> lines = new List<string>();

    public void OnConversationStart(Transform actor)
    {
        lines.Clear();
        lines.Add("Starting conversation '" + DialogueManager.LastConversationStarted + "'.");
    }

    public void OnConversationLine(Subtitle subtitle)
    {
        if (subtitle == null | subtitle.formattedText == null | string.IsNullOrEmpty(subtitle.formattedText.text)) return;
        string speakerName = (subtitle.speakerInfo != null && subtitle.speakerInfo.transform != null) 
            ? subtitle.speakerInfo.transform.name : "(null speaker)";
        var line = string.Format("{0}: '{1}'", speakerName, subtitle.formattedText.text);
        lines.Add(line);
    }

    public void OnConversationEnd(Transform actor)
    {
        lines.Add("Ending conversation.");
        var title = DialogueLua.StringToTableIndex(DialogueManager.LastConversationStarted); // Replace invalid characters.
        var filename = string.Format("{0}/{1}-{2:yyyy-MM-dd_hh-mm-ss-tt}.txt",
            Application.persistentDataPath, title, System.DateTime.Now);
        System.IO.File.WriteAllLines(filename, lines.ToArray());
        Debug.Log("Recorded conversation to: " + filename);
    }

} 
LongLeggedOne
Posts: 4
Joined: Sun Jul 17, 2016 9:09 am

Re: Recording Route and Scoring Data

Post by LongLeggedOne »

Hello,

Thank you very much for the rapid and detailed response! I'll try implementing these right away.
User avatar
Tony Li
Posts: 21050
Joined: Thu Jul 18, 2013 1:27 pm

Re: Recording Route and Scoring Data

Post by Tony Li »

Happy to help! If you run into any issues or questions, just let me know.
LongLeggedOne
Posts: 4
Joined: Sun Jul 17, 2016 9:09 am

Re: Recording Route and Scoring Data

Post by LongLeggedOne »

So I have modified versions of these scripts working in my project and everything is doing what it needs to. Thank you for the excellent support. Incidentally I spent some time researching exactly what the scripts were doing and that led to me learning a whole bunch of things about C# and programming in general. So also thanks for the inspiration, intended or not!

As I've spent more time working with the dialogue system, I now have a few suggestions for additional features/improvements. Should I post those here, or would you prefer I start a new thread? Or perhaps you have some other place meant for suggestions that I haven't noticed?
User avatar
Tony Li
Posts: 21050
Joined: Thu Jul 18, 2013 1:27 pm

Re: Recording Route and Scoring Data

Post by Tony Li »

Hi,

A new thread would be great. Thanks in advance for the suggestions!
Roncin
Posts: 11
Joined: Sun Aug 17, 2014 10:17 pm

Re: Recording Route and Scoring Data

Post by Roncin »

I am currently working on the same problem.

What I did was modify the conversation logger script to echo the debug log to a file which I could then parse.
In the debug information, I record the conversation id and node ID of each item selected in a log file. Now I am working on taking these ID numbers and displaying them in a heat map.

An idea I think will work going forward is to use Unity Heat maps with the conversation ID (X direction) and node ID (Y direction). However, if you are doing psychological testing, your institution may have concerns about data privacy.

Good luck.
User avatar
Tony Li
Posts: 21050
Joined: Thu Jul 18, 2013 1:27 pm

Re: Recording Route and Scoring Data

Post by Tony Li »

That's a neat idea. Players might enjoy this even for games. I often run across forum threads where players speculate on the popularity of in-game choices -- did most people choose the good or evil option, how many people sacrificed Kaidan or Ashley, etc.
Roncin
Posts: 11
Joined: Sun Aug 17, 2014 10:17 pm

Re: Recording Route and Scoring Data

Post by Roncin »

@"LongLeggedOne"
I am working on solving that problem right now with 50 some log files.

Attached is the code I used to record the conversation data. It is customized for my project but might give you a few ideas. If I was doing it again, I would use something like a % symbol as a delimiter in my log file. That would make parsing out the nodes and edges easier.

<Logger.zip>

An alternative solution that might help you is SRDebugger. It provides debugging tools captures your debug.log statements from your executable on the target device/machine. Mostly set up for android testing. Looks promising but I have only begun to explore this.

For graphing my conversations, I ended up using Cytoscape. It's an academic program designed for cell research. However it can map my 1000 node conversation easily. You can adjust node properties on the fly and zoom in to dialog text as well. Unfortunately it was output only and tended to crash often.
http://cytoscape.org/
<image.png>
-------------------------------
Recently I started working on a parser for my log files. The code here is a work in progress. What it does is take a log file and parse it into three windows, the original log file, the nodes, and the edges. The code references _uiFB which is the "In Game File Browser" asset https://www.assetstore.unity3d.com/en/#!/content/33638.
This portion is not complete yet but the goal is to select log files without getting access violations.
<parser.zip>

Challenges:
Unity has a 65k maximum verts in the UI. Depending on which forum you read, EACH character takes 4 (text mesh pro) to 20 verts. Some of my log files are 17k in size and blew this limit out of the water. I had to incorporate checks to make sure I was only displaying a portion of the text. Apparently TextMeshPro recently addressed this but I haven't played with it yet.

Microsoft requires you to get special permissions to access folders. So I was frequently getting "access violations" depending on the location of my files. In Game File Browser got around that.

One challenge I am encountering when trying to generate a heat map is that the nodes are not sequential. So I need to map the conversation node to an XY position.
This code for a bi-directional dictionary by Jon Skeet on Stackexchange should help.
http://stackoverflow.com/questions/2553 ... ary#255630

Goals:
I want to interface my node data with "Cytoscape" I already have vba scripts to parse the Dialogue System csv file into nodes and edges.

What I would like to do with this information is generate a heat map or animated heat map. If I can interface with Unity's Heat Map analytics, that would be awesome.

Best of luck.
Roncin
Attachments
Parser.zip
(5.18 KiB) Downloaded 129 times
image.png
image.png (198.79 KiB) Viewed 2049 times
Logger.zip
(3.15 KiB) Downloaded 146 times
Post Reply