Skip to content

Test tool for Unity that allows observation of varying values, as a two-dimensional plot

Notifications You must be signed in to change notification settings

hww/varp_oscilloscope

Repository files navigation

VARP Oscilloscope

Documentation for Unity asset

Getting Started

VARP Oscilloscope is a small, easy to use Unity asset that you can use to record and analyze values used and updated by scripts, physics or animation, in real time. The oscilloscope has 4 channels but can be extended to 8 without additional programming. In addition to the list of general features, this section covers the following topics:

  • How to add the VARP/OSC asset to your project.
  • How to add initialize the oscilloscope from your code.
  • How to push or pull values to the oscilloscope probes.
  • How to adjust probe magnitude attenuation factor.
  • How to adjust trigger settings and horizontal scale value.

Features

  • Single time base digital real-time oscilloscope.
  • Every frame or every fixed update sample rate1 and 10242 point record length for each channel.
  • Screen 550x550 pixels and 11x11 divisions grid4.
  • Four3 independent recording channels.
  • Any channel can be used as trigger source.
  • Each channel has a buffer array of Vector3 values.
  • Each channel has its own color tag.
  • Four automated measurements (min, max, peak, average).
  • Custom labels OSD.
  • Alternative 'Logic' rendering for integer values as a logic analyzer.
  • Autoset for quick setup5.
  • Cursors with readout5.

1 The sampling rate is fully configurable and can be replaced to other time steps.

2 Can be modified to another size.

3 Can be modified to another channels quantity.

4 Can be modified to another dimensions.

5 Not yet implemented.

Additional Features

  • Does not require custom Unity GUI tools. Easy to learn.
  • Fully configurable with script for different measurements.
  • Human friendly attenuation gain and time per division values.

Screenshot

The asset is in development so the final screenshot appearance may have slight differences.

Screenshot

Adding VARP/OSC to your project

Copy VARP folder inside Assets/Plugins folder. After that you can instantiate the Oscilloscope prefab in your project’s scenes. Finally, write a script to control the oscilloscope with your game events or data, based on the provided documentation and examples.

To activate/deactivate the oscilloscope, use ` key or property IsVisible.

oscilloscope.gui.IsVisible = true;  // Make visible
oscilloscope.gui.IsVisible = false; // Make invisible

To activate/deactivate input shortcuts, use property IsInFocus. The enabled/disabled keyboard state is indicated by an icon on the screen.

oscilloscope.gui.IsInFocus = true;  // Enable keyboard shortcuts
oscilloscope.gui.IsInFocus = false; // Disable keyboard

Basic Concepts

To use your oscilloscope effectively, you must understand the following basic concepts:

  • Triggering.
  • Acquiring data.
  • Scaling and positioning waveforms.
  • Measuring waveforms.
  • Setting up the oscilloscope.

The figure below shows a block diagram of the various functions of an oscilloscope and their relationship to each other.

Basic Concept Diagram

GameValue Any variable or class member can be captured by pushing it to the probe every frame or only when it was changed. As alternative the probe can pull values by calling a lambda function assigned to the probe. Before recording the value should be converted to floating point, Vector2 or Vector3 types.

OscProbe Container of configuration settings for the channel or trigger. Every time when the probe is connected to the channel, the values will be copied to the channel and optionally to trigger (if this channel connected to trigger).

OscChannel This class contains data for data recording and rendering it on the screen.

OscGrid Rendering the grid on the screen.

OscRenderer Renderer waveforms or texts on screen.

OscTrigger Class which monitors one of the channels and can be used to the start/stop acquiring data. Every time when trigger is connected to a channel, the trigger reads the configuration values from it.

Oscilloscope Main oscilloscope's code.

Understanding Grid

The grid has divisions, subdivisions and rulers. Center of the screen has coordinate 0,0. Horizontal axis X, and vertical axis Y have the ruler bar in the center of screen.

Grid

Channel Names

Access to each channel by script require to provide as argument channel's name C1, C2, ..., C8. The enum value OscChannel.Name has the list of default names.

Value Value Name Comment
0 C1 Channel 1
1 C2 Channel 2
2 C3 Channel 2
3 C4 Channel 4
4 C5 Channel 51
5 C6 Channel 61
6 C7 Channel 71
7 C8 Channel 81

1 Reserved for extension

Additionally the name of channel will be displayed on screen as the label. The label has a horizontal arrow to mark channel's origin (0 value).

Channel Labels

When the origin is outside of screen the label will rendered at the screen edge.

Class OscSettings

This class is based on ScriptableObject and can be used to create an asset with the oscilloscope's configuration settings.

Type Field Info
int pixelsPerDivision How many pixels in single division (recommend 10,20,30,...)
int divisionsX Horizontal divisions number (recommend odd value)
int divisionsY Vertical divisions number (recommend odd value)
int subdivisions Subdivisions in the division (recommend 5 or 10)
bool drawGrid Draw grid lines
bool drawRullerX Draw horizontal ruler in center
bool drawRullerY Draw vertical ruler in center

Class OsdGrid

This class allows changing the grid view by script.

oscilloscope.grid.DrawGrid = true;    // Draw grid cells
oscilloscope.grid.DrawRullerX = true; // Draw horizontal ruler
oscilloscope.grid.DrawRullerY = true; // Draw vertical ruler

Class OsdProbe

Probe Names

The name of probe in just a string value will be displayed on screen to inform user about which probe is connected to this or that channel.

Probe Instantiating

Let’s create a simple probe and connect it to oscilloscope channel A.

// Create probe
var probe= new OscProbe("CharacterVelocity");
// Plug to the channel
oscilloscope.GetChannel(OscChannel.Name.C1).Plug(probe);
// Remove probe from channel (disable channel)
oscilloscope.GetChannel(OscChannel.Name.C1).Unplug();

Probe Parameters

probe.Gain = 2f;                              // To set gain value V/
probe.position = -5;                          // To adjust vertical position (zero level of oscillogram)
probe.autoGain = true;                        // To enable auto gain feature
probe.autoGainDivisions = 2;                  // Request 2 divisions for peak to peak oscillogram
probe.style = OscProbe.Style.Logic;           // To change rendering style (Default, Logic)
// To set trigger's values (will be applied after tigger will be connected to channel)
probe.triggerMode = OscTrigger.Mode.Normal;   // Trigger's normal mode
probe.triggerMode = OscTrigger.Mode.Auto;     // Trigger's auto mode
probe.triggerMode = OscTrigger.Mode.Single;   // Trigger's single mode
probe.triggerEdge = OscTrigger.Edge.Rising;   // Trigger's rising edge detection
probe.triggerEdge = OscTrigger.Edge.Falling;  // Trigger's failing edge detection
probe.triggerLevel = 0.5f;                    // Trigger's edge detection threshold

Push Value to Probe

After the probe is created we can push values to it by various methods (listed below) or you can directly change the probe’s sample field.

// Direct access to sample
probe.sample.x = Time.time;
probe.sample = transform.position;
// Write floating point value to probe
probe.Log(rigidbody.velocity.magnitude);
// Write integer value to probe
probe.Log((int)Time.time);
// Write bool value to probe
probe.Log(Time.time > 10f);
// Write Vector2 to probe
probe.Log(transform.achoredPosition);
probe.Log(x,y);
// Write Vector3 value to probe
probe.Log(rigidbody.velocity);
probe.Log(x,y,z);
// Write color value to probe
probe.Log(text.color);

Pull Value by Probe

Another way to send values to a probe is to assign a lambda method to the probe’s readSample delegate. The delegate will be called before channel will acquire sample.

characterVelocityProbe.readSample = (OscProbe probe) =>
{
   probe.sample = rigidbody.velocity;
}; 

Render Probe Markers

Each probe can display horizontal markers with short text.

oscLastDifficultyForce.postRender = (OscRenderer renderer, OscChannel channel) =>
{
    channel.DrawLabel(renderer, "-2", -2f);
    channel.DrawLabel(renderer, "-1", -1f);
    channel.DrawLabel(renderer, " 0", 0f);
    channel.DrawLabel(renderer, "+1", 1f);
    channel.DrawLabel(renderer, "+2", 2f);
};

Custom Probe Markers

Default Probes

Three predefined probe types available.

  • OscProbe.Null Default probe usually used for disabling a channel.
  • OscSineProbe.Default Default probe with 10Hz 1V sine wave form.
  • OscSquareProbe.Default Default probe with 10Hz 1V square form.

Class OscChannel

When probe is connected to channel, all values from this probe will be copied to the channel. Now we can manipulate by channel's values directly.

var channel = oscilloscope.GetChannel(OscChannel.Name.C1);
channel.Gain = 2f;                            // To set gain (Volts per Div) 
channel.GainPlus();                           // Increase gain
channel.GainMinus();                          // Decrease gain
channel.Position = 1f;                        // Vertical position of channel (Divisions)
channel.AutoGain = true;                      // Enable auto gain
channel.autoDivisions = 2f;                   // Auto gain division number
channel.Decoupling = true;                    // AC mode
channel.Decoupling = false;                   // DC mode
channel.Style = Style.Default;                // Render standart diagramm
channel.Style = Style.Logic;                  // Render logic analyzer diagram

Class OscTrigger

The trigger determines when the oscilloscope starts to acquire data and display a waveform. When a trigger is set up properly, it can convert unstable displays or blank screens into meaningful waveforms.

Trigger Source

You can derive your trigger source from any channel. To select a trigger source, use the SetChannel method.

var trigger = oscilloscope.trigger;
trigger.SetChannel(OscChannel.Name.C1);

By calling SetChannel, the settings from the channel will be applied as the trigger source. After that, the settings can be adjusted by next methods.

oscilloscope.trigger.SecondsDivision = 1f;   // set 1 second per division
oscilloscope.trigger.SecondsDivisionPlus();  // increase second per division value
oscilloscope.trigger.SecondsDivisionMinus(); // decrease second per division value
oscilloscope.trigger.Position = 1f;          // chanel horizontal position 1 division after trigger
oscilloscope.trigger.Level = 1f;             // set threshold value for trigger

When the assigned channel records Vector3 or Vector2 data, the trigger uses only the X component of the vector. To alternate this behavior the readTriggerSample delegate can be used.

probe.readTriggerSample = (OscCnannel ch) => ch.sample.magnitude; // use vector's magnitude as the trigger's source

Modes

There are three trigger modes available: Auto, Normal and Single. To set the trigger mode use the SetMode method.

oscilloscope.trigger.SetMode(Mode.Auto); // start capturing
  • Auto. This trigger mode allows the oscilloscope to acquire a waveform even when it does not detect a trigger condition. If no trigger condition occurs while the oscilloscope waits for a specific period (as determined by the time-base setting), it will force itself to trigger.

  • Normal. The Normal mode allows the oscilloscope to acquire a waveform only when it is triggered. If no trigger occurs, the oscilloscope will not acquire a new waveform, and the previous waveform, if any, will remain on the display.

  • Single The Single mode allows the oscilloscope to acquire one waveform each time you call ForceTrigger method, and the trigger condition is detected.

Edge Detection

The trigger compares the channel value with trigger's level value and produces starting data acquiring depend on Edge detection mode. The picture below explain difference of Edge modes.

Edge Detection

The AutoSetLevel method will set the trigger's level to the vertical midpoint between the peaks of signal at the trigger's source.

oscilloscope.trigger.AutoSetLevel();  

Stopping waveform data acquisition

While acquisition is running, the waveform display is live. Stopping the acquisition freezes the display. In either mode, the waveform display can be scaled or positioned with the vertical and horizontal controls.

oscilloscope.trigger.Pause = true;   // stop acquiring
oscilloscope.trigger.Pause = false;  // resume acquiring

Single Mode

Starts an acquisition regardless of an adequate trigger signal. This button has no effect if the acquisition is already stopped.

oscilloscope.trigger.ForceTrigger(); // start capturing

Time Labels

Time labels will be rendered below the screen. Each label has unique id and calling the AddTimeLabel method with the same index will overwrite a previous label definition.

oscilloscope.trigger.AddTimeLabel(0, "T1", Color.red); // add time label at the current time

Time Markers

Taking Measurements

TODO

Appendix

Keyboard Shortcuts

Keys Functions
` Enable, Disable oscilloscope GUI. Also used to activate input focus
1 to 8 Select current channel
0 Select trigger
SHIFT+1 to SHIFT+8 Activate channel for trigger's source
Pause Pause/Unpause the data acquiring
S Force start acquiring
G Modify grid style
Selected Channel
+, - Adjust gain value
Up, Down Adjust vertical position
C Adjust coupling settigs
A Enable/Disable auto gain mode
V Alternate view style
Selected Trigger
E Alternate edge detection mode
M Alternate trigger mode
+, - Adjust time scale value
Left, Right Adjust horizontal position

Icons legends

Icons

About

Test tool for Unity that allows observation of varying values, as a two-dimensional plot

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages