Search Unity

Recording a player's movement during a game in xyz coordinates, then outputting to a file.

Discussion in 'Editor & General Support' started by ijohnston, Jul 16, 2014.

  1. ijohnston

    ijohnston

    Joined:
    Jul 16, 2014
    Posts:
    5
    Dear all,

    I'm a Professor at a University working on a research project looking at human learning, and I want to understand how people learn to navigate through environments. Unity seems to be an ideal platform to design these types of studies in a virtual environment.

    The basic design will be that a participant is inserted into the environment and are asked to find a hidden goal. They explore the environment from a first person perspective until they do. This is repeated across several trials and we see how their behaviour changes with experience with the environment, and try to understand how people use aspects of their environment to orientate themselves.

    The long-term aim is to do this while people are having their brains scanned.

    However, I'm having problems seeing how I can get data back from this.

    What I need are ways to measure the following:

    1. The total time it takes for them to find the goal from the time of insertion.
    2. The path distance they travel to find the goal from insertion
    3. A description of their path in x,y,z coordinates at regular time intervals so I can determine dwell/search times in certain parts of the environment.
    4. A description of the direction of the camera at regular time intervals so I can try to determine what aspects of the environment they are using to navigate (i.e., which landmarks they are looking at).
    I suppose that #3 can be used to determine #1 and #2, so this is the most important one. #4 is a bit of a wish-list time.

    Could anyone point in the direction of how to go about solving #3?

    I'll be using a PC environment and the player/participant will be in front of the computer.

    Thanks in advance, Ian
     
  2. Josh-Naylor

    Josh-Naylor

    Administrator

    Joined:
    Jul 1, 2014
    Posts:
    216
    Hi Ian.

    This is totally do-able in Unity and I've created a very brief example just from the standard asset packages and one small script alone.

    It's fairly straight forward taking the players current position and forward facing position to output to a text file at regular intervals as demonstrated below.

    Code (CSharp):
    1. using System.IO;
    2.  
    3. public class savePosition : MonoBehaviour {
    4.  
    5.     string FILE_NAME = "positionFile.txt";
    6.     int time = 0;
    7.     int interval = 150;
    8.     // Use this for initialization
    9.     void Start () {
    10.    
    11.     }
    12.    
    13.     // Update is called once per frame
    14.     void Update () {
    15.    
    16.         if (time > interval)
    17.         {
    18.             float x = transform.position.x;
    19.             float z = transform.position.z;
    20.             float fx = transform.forward.x;
    21.             float fz = transform.forward.z;
    22.             StreamWriter sw = File.AppendText(FILE_NAME);
    23.             sw.WriteLine ("my x position is " + x + " my z position is " + z);
    24.             sw.WriteLine ("I'm facing " + transform.forward);
    25.             sw.Close ();
    26.             Debug.Log ("write to file");
    27.             time = 0;
    28.         }
    29.         else
    30.             time ++;
    31.     }
    32. }
    I hope this was the kind of thing you where looking for.

    Below is a link to the project also for you to try if you wish

    HERE

    - Josh
     
    mohamadizaz98 and crag like this.
  3. crag

    crag

    Joined:
    Dec 13, 2013
    Posts:
    145
  4. Lo0NuhtiK

    Lo0NuhtiK

    Joined:
    Jan 29, 2012
    Posts:
    9
    I thought this was an interesting idea when you asked about it in the Answers forum yesterday, and my first thought was the same @crag had about using xml for saving this info in case you wanted to use something other than unity to view the data (I've only used PlayerPrefs for saving before now because I was just saving small things and didn't know much of anything about xml or how to use it)... but last night I decided to figure out something about xml, turns out it's pretty easy to use with Unity, and I put something together for you to help get you going on this using the FPS controller that comes with Unity.

    In the script I noted this, but just to make sure you see it I'll type it here : In your scene(s) with the character controller, your "goal" object needs to be a Collider object that has isTrigger set to true (checkmarked in the inspector) so that when the controller runs through it it knows it's finished and will save an xml file for that run.

    [deleted what would now be irrelevant content for this post since stuff changed]
    Edit : Initially I had uploaded a unityPackage with a few scripts in it that I had made and a few that come with Unity which I had modified. Had other things in mind when I first started on it, and now made it a bit better than it was before anyway, so now it's just this one script. Take the default unity first person controller prefab and slap this script onto it. Read through the script and the comments for more info about what it does.

    Any more questions about it, feel free to ask.
    If it's buggy, feel free to report here lol I'll see about fixing it for you.

    Edit : forgot to mention... if you're having this thing do the check for all objects in sight, then you need to disable the renderer on the "Graphics" or Graphix, however they spelled it, child on the first person controller otherwise it might see that sometimes also.
     

    Attached Files:

    Last edited: Jul 19, 2014
    ijohnston and crag like this.
  5. crag

    crag

    Joined:
    Dec 13, 2013
    Posts:
    145
    Holy sh!t that's tasty @Lo0NuhtiK. Serve that up with a side of Vectrosity, load multiple xml sessions, do color variant line segments on 2D/3D lines with beziers and get yourself a real delicious visual via Unity. Outside of Unity, graphs galore. D4mn I'm hungry now.
     
  6. Lo0NuhtiK

    Lo0NuhtiK

    Joined:
    Jan 29, 2012
    Posts:
    9
    @crag : Yeah, I was thinking some of the same things about him using unity to draw out the movements with markers/lines/floating gui with the data displaying, etc lol

    Found a bug or two in it a minute ago and fixed it, added another small thing to it as well. Messing around with it some more, will upload the updated script later when I'm done playing with it xD
     
  7. ijohnston

    ijohnston

    Joined:
    Jul 16, 2014
    Posts:
    5

    This is absolutely wonderful! Let me try it out and I'll get back to you ASAP!

    Thanks everyone, what a fantastic community!
    Ian
     
  8. ijohnston

    ijohnston

    Joined:
    Jul 16, 2014
    Posts:
    5
  9. Lo0NuhtiK

    Lo0NuhtiK

    Joined:
    Jan 29, 2012
    Posts:
    9
    Updated the FPSInputTracker this evening, and added a small example GUI script to go along with it to show how you might go about using Unity to read the saved data; and if not for reading it with the GUI it still shows an example of how to load the saved data from the files into an array to use in other ways (like the 3D displaying @crag mentioned).

    Seems to all be working properly, and it'd be easy enough to add/remove things to/from the classes for saving if you wanted.

    Hopefully you find it useful, but if you don't then someone somewhere might at some point lol

    Good luck with your experiments, maybe I'll get to read about them some day xD

    [uploaded the updated script and the example gui script into my first comment above here]
     
  10. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,657
    FWIW this can be done even more easily using InvokeRepeating(); that way you eliminate the dependency on framerate, too:

    Code (csharp):
    1.  
    2. public class betterSavePosition : MonoBehaviour
    3. {
    4.    public float samplingRate = 1f; // sample rate in Hz
    5.    public string outputFilePath;
    6.  
    7.    private StreamWriter _sw;
    8.  
    9.    public void OnEnable() {
    10.       _sw = System.IO.File.AppendText(outputFilePath);
    11.       InvokeRepeating("SampleNow", 0, 1/samplingRate);
    12.    }
    13.  
    14.    public void OnDisable() {
    15.       _sw.Close();
    16.       CancelInvoke();
    17.    }
    18.  
    19.    public void SampleNow()
    20.    {
    21.       _sw.WriteLine("t {0} x {1} z {2} fx {3} fz {4}",
    22.          Time.time, transform.position.x, transform.position.z, transform.forward.x, transform.forward.z);
    23.    }
    24. }
    25.  
     
    edvin1989 likes this.
  11. crag

    crag

    Joined:
    Dec 13, 2013
    Posts:
    145
  12. ijohnston

    ijohnston

    Joined:
    Jul 16, 2014
    Posts:
    5
    I've just been play testing this with some students, and it's working perfectly. Thanks everyone!
     
    superpig likes this.
  13. ijohnston

    ijohnston

    Joined:
    Jul 16, 2014
    Posts:
    5
    I've been going through the tutorials and projects learning more about Unity and how it's set up, and I've been able to get a few projects up that are getting closer to the architecture I want, and came back to this script you prepared. This is really very good. I'll have a closer look at it over the next few days.

    Again, a great community here and I'm amazed at the help.
     
    crag likes this.
  14. edvin1989

    edvin1989

    Joined:
    Nov 28, 2019
    Posts:
    6
    Thank you so much.