04 May How to Record What Your Playtesters are Doing in Your Unity or Twine Games
This post is more technical than most of our blog posts. If you’re not making computer games then this probably won’t be of terrible interest to you.
This happens all the time at Tiltfactor: we’re developing a single player Unity game or Twine story prototype, and we’ve watched team members, friends, and family play the game and it’s working well. Now it’s time to see how acquaintances and strangers play the game. We always need feedback on our game prototypes, but perhaps even more important than feedback is observing players play. Since it’s often hard to recruit strangers to come to Tiltfactor and play a prototype, we would like to be able to share a link, but then how will we get observation notes, or what players’ final scores are, or places where they’re getting stuck? It’s a lot of work to build a database to save player actions and hook that into your game so you can see what every player is doing with your prototype. Instead, we have come up with a down and dirty solution that we’ve been using in a bunch of our prototypes—this post leads you through how to quickly and easily record what players are doing in a game prototype that you send out over the internet!
Try it out: https://tiltfactor.org/StupidStory.html — you’ll see that the choices you make are recorded in the survey after the game.
What You’ll Need
- A Unity or Twine game prototype that you want to record player actions from. Other types of games would probably work too. I’ll be using Twine as an example.
- A Qualtrics account (or similar survey service that can record Query strings—it seems to me that Google Forms cannot, but most other services can). I’ll be using Qualtrics as an example.
If you know what a query string is, you can skip this section. Otherwise: a query string is information that you can put in a URL (webpage link) that the page can read. It’s really easy and you can try it now—just go into the address bar for this blog post and add
?cake=good and then press enter to reload the page.
Now try making cake bad (
?cake=bad). You can send data to the webpage! Yeah! This page uses that data for nothing except the little widget above that changes based on the first query string, but other websites can do all sorts of things. For example, Amazon uses query strings to track how to get to product pages so they can see which of their ads are working. We’re going to use query strings to send what the player does in our game to a survey website (Qualtrics in my case), and then Qualtrics is going to save that data for us.
The thing of the left side of the equals sign (
cake in our case) is called the parameter name. The thing on the right side of the equals sign (
good) is called the value. You can have tons of query strings in the same URL. The first one must have a ‘?’ in front of the parameter namet to tell the browser that this is a query string and not part of the URL itself. All of the ones after that should have a ‘&’ before the parameter name.
Saving Player Actions
The first step is to actually have the game save what players are doing! This is probably a thing you should be doing anyway, but shouldn’t be too hard regardless. Exactly what player actions you want to save will change with the type of game, but I’ve got a nonlinear text-based story in Twine, so I’m just going to record the passage name of each part of the story the player gets to. No matter what you’re saving, you’re going to want to save it in one big long string variable that looks kinda like this:
In Twine I’m creating 2 variables. The first variable, called
$actions is the string that will store the player actions in the format above. The second variable, called
$actionCount is simply the number of actions the player has taken. Now I’m going to insert the following code into the ‘Footer’ passage of my story:
(set: $actions to it + “&action” + $actionCount + “=” + (passage:)’s name)
(set: $actionCount to it +1)
Because the Footer passage in Twine automatically happens at the end of each story passage, whenever the player visits a story passage (i.e. makes a choice), the
$actions variable will get a new parameter called ‘action9’ (where 9 is the number of the action taken), and the value of that parameter is the name of the passage. This will very simply show me which choices a player makes.
In the example story at the top of the post (pictured above), the player starts at Passage1 and then can either go to Passage2A or Passage2B, and then can go to Passage3A, 3B, or 3C, and finally can restart or go to End. After playing, the
$actions variable will be
&action1=Passage1&action2=Passage2B&action3=Passage3A&action4=End if the player chooses to go to Passage2B and passage 3A, and then end.
The process is similar if you are using Unity, except you’ll need to decide which player actions you want to record—since Unity can be used to make all sorts of games, this isn’t super easy to explain in a general way. You’ll also have to likely make a Game Object to store your actions variable. If you are making a realtime game, instead of using ‘action1’ you might want to do ‘action3786’ where 3786 is the timestamp of the action so you can tell how long players are taking to do things.
Sending Player Actions to the Survey
This part is surprisingly easy. At the end of your game you simply give the player a link to a survey you’ve created, and you tack on the $actions string.
(set: $surveyLink to ‘https://dartmouth.co1.qualtrics.com/jfe/form/SV_3pAd56Iuy4G9tA1’)
(link: "Survey")[Survey(goto-url: $surveyLink + "?gamename=Stupid Story" + $actions)]
In the Twine code above, a few things to note:
(link: "Survey")[Survey(goto-url: $surveyLink + "?gamename=Stupid Story" + $actions)]portion will just open an external link to your survey. This is how Twine does this, but Unity can also open links in webpages.
- You’ll note that I’ve added
?gamename=Stupid Story. We don’t really need to save the game name, but as I mentioned in the Query Strings section, the first query string we provide always needs to be preceded by a ‘?’
?gamename=Stupid Storycould just as well be
?test=testfor our purposes; we just need a parameter with a question mark before it.
- Some surveys services have a built in set of query strings (some even determine which survey to go to using query strings!). If your survey link looks like this: ‘https://dartmouth.co1.qualtrics.com/jfe/form/?sid=3pAd56Iuy4G9tA1’ then you’ll want to omit the
?gamename=Stupid Storyparameter because your browser won’t be happy to have TWO parameters starting with a ‘?’
When the player clicks on your link they’ll be sent to the survey with all of the query strings going with them. Okay, now we just need to tell our survey service to actually SAVE the query strings.
Saving Player Actions in the Survey
This portion will depend on your survey service. Here’s how to do it in Qualtrics:
- Create a survey. Chances are you may have already done this, since you’ll need the link to the survey to put in your game as shown in the previous section. It doesn’t matter if there are any questions in the survey, but you might want to put a small “Rate the game on a scale of 1 to 5” so people don’t get freaked out about you saving their game actions.
- Get the link for your survey and put it in your game. In Qualtrics, the link can be found by clicking on the “Distributions” tab and then click “Anonymous Link” in the sidebar.
- Save the query strings. In Qualtrics, click the “Survey Flow” button at the top. In the Survey Flow, click “Add a New Element Here” → “Embedded Data.” In the Embedded Data section you just added, write the names for each of the query strings you want to save. Leave the values blank and click “Save Flow.” Now Qualtrics will fill them in from the query strings automatically!
That’s it! Now you can test it. Play your game, click the survey link, and then log into your Qualtrics account, click on the survey and click on the “Data and Analysis” tab. There will be a list of the people who have played the game and clicked on the survey, and within each person’s response will be embedded data for the actions they took!
Thanks for reading, and if you have any questions, feel free to post them in the comments!