1

Currently I am working on a project using Unity and the Virtual Reality Toolkit (VRTK). I want to log the times of the grabbed objects (How long the user grabs an object).

So far I got this:

using System;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;

public class System_2_Script_Slider_X : MonoBehaviour
{
    float Timer;

    void Start()

    {
        Timer = 0;

        if (GetComponent<VRTK_InteractableObject>() == null)
        {
            Debug.LogError("Team3_Interactable_Object_Extension is required to be attached to an Object that has the VRTK_InteractableObject script attached to it");

            return;
        }

        GetComponent<VRTK_InteractableObject>().InteractableObjectGrabbed += new InteractableObjectEventHandler(ObjectGrabbed);

        GetComponent<VRTK_InteractableObject>().InteractableObjectUngrabbed += new InteractableObjectEventHandler(ObjectUngrabbed);
    }

    private void ObjectGrabbed(object sender, InteractableObjectEventArgs e)

    {
        //Some Code

        Timer += Time.deltaTime;
    }

    private void ObjectUngrabbed(object sender, InteractableObjectEventArgs e)

    {
        //Some Code

        File.AppendAllText("PATH/Timer.txt", Timer.ToString());

        Timer = 0;
    }
}

Unfortunately this doesn't work as I get times of around 2 milliseconds even though I grabbed the object way longer. So it seems the ObjectGrabbed() function starts the timer but stops it immediately.

How can I fix this?

Joh
  • 327
  • 4
  • 13

2 Answers2

3

The object grabbed function is likely only called once (when you grab). It doesn't start a timer, it just add the time since last frame to your variable. If it is only called once, it will only add the time of one frame to the Time variable.

What you should do instead is register when the object was grabbed so you can compute the total length when it is released:

using System;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;

public class System_2_Script_Slider_X : MonoBehaviour
{
    private float _timeWhenGrabbed;

    void Start()
    {
        if (GetComponent<VRTK_InteractableObject>() == null)
        {
            Debug.LogError("Team3_Interactable_Object_Extension is required to be attached to an Object that has the VRTK_InteractableObject script attached to it");

            return;
        }

        GetComponent<VRTK_InteractableObject>().InteractableObjectGrabbed += new InteractableObjectEventHandler(ObjectGrabbed);

        GetComponent<VRTK_InteractableObject>().InteractableObjectUngrabbed += new InteractableObjectEventHandler(ObjectUngrabbed);
    }

    private void ObjectGrabbed(object sender, InteractableObjectEventArgs e)

    {
        //Some Code

        _timeWhenGrabbed = Time.time;
    }

    private void ObjectUngrabbed(object sender, InteractableObjectEventArgs e)

    {
        //Some Code
        var grabDuration = Time.time - _timeWhenGrabbed;
        File.AppendAllText("PATH/Timer.txt", grabDuration.ToString());
    }
}
Basile Perrenoud
  • 4,039
  • 3
  • 29
  • 52
2

Probably the ObjectGrabbed method gets fired only when the Grab action occurs, and not every frame the object is grabbed. So you should probably setup your code by using some Timer or StopWatch (The stopwatch has more precision). By starting the timer into the ObjectGrabbed method and stopping the timer into the ObjectUngrabbed method.
Something like this:

using System.Diagnostic.Stopwatch;
...
private StopWatch Watcher = new StopWatch();
...
private void ObjectGrabbed(object sender, InteractableObjectEventArgs e)
{
    Watcher.Start();
}

private void ObjectUngrabbed(object sender, InteractableObjectEventArgs e)
{
    Watcher.Stop();
    long millis = Watcher.ElapsedMilliseconds;
    Watcher.Reset();
    File.AppendAllText("PATH/Timer.txt", millis.ToString());
}
ZzAtomiic
  • 326
  • 2
  • 9