For a simple implementation of the drawing logic for a real-time graph viewer in Unity using UI Toolkit and C#, we’ll create a basic setup that simulates incoming data and draws a continuously updating graph. This example will focus on the graph drawing part, assuming you already have a UI Document setup with UI Toolkit.
The implementation will include:
- A
GraphViewer class to handle incoming data and draw the graph.
- Simulated real-time data generation for demonstration purposes.
- Drawing the graph using the immediate mode GUI (IMGUI) within the UI Toolkit’s
IMGUIContainer.
This example simplifies certain aspects for clarity and focuses on the core concepts. You may need to adjust and expand upon this for a fully functional oscilloscope-like viewer.
- Make sure your Unity project is set up with the UI Toolkit package and you have a UI Document (
UIDocument) attached to a GameObject in your scene.
- Create a Visual Element in your UXML called
GraphContainer where the graph will be drawn.
Create a new C# script GraphViewer.cs and open it in your code editor. Replace its contents with the following:
using UnityEngine.UIElements;
public class GraphViewer : MonoBehaviour
public UIDocument uiDocument; // Assign in the Inspector
private IMGUIContainer graphContainer;
private float[] dataPoints;
private int dataCapacity = 100; // Number of data points to display at once
private float updateInterval = 0.05f; // Update interval in seconds
private float nextUpdateTime = 0;
// Initialize data points
dataPoints = new float[dataCapacity];
// Find the GraphContainer and set up the IMGUIContainer
var rootVisualElement = uiDocument.rootVisualElement;
graphContainer = new IMGUIContainer(DrawGraph);
rootVisualElement.Q("GraphContainer").Add(graphContainer);
// Simulate real-time data update
if (Time.time >= nextUpdateTime)
UpdateData(Random.value * 100); // Simulate a new data point
nextUpdateTime = Time.time + updateInterval;
graphContainer.MarkDirtyRepaint(); // Mark the IMGUIContainer for repaint
private void UpdateData(float newData)
// Shift data points to the left
for (int i = 1; i < dataPoints.Length; i++)
dataPoints[i - 1] = dataPoints[i];
dataPoints[dataPoints.Length - 1] = newData;
Rect graphRect = new Rect(0, 0, graphContainer.contentRect.width, graphContainer.contentRect.height);
GUI.Box(graphRect, GUIContent.none);
for (int i = 1; i < dataPoints.Length; i++)
float prevX = (i - 1) * (graphRect.width / dataCapacity);
float prevY = graphRect.height - (dataPoints[i - 1] / 100) * graphRect.height; // Assuming data range 0-100
float currX = i * (graphRect.width / dataCapacity);
float currY = graphRect.height - (dataPoints[i] / 100) * graphRect.height; // Adjust as needed
GUI.DrawLine(new Vector2(prevX, prevY), new Vector2(currX, currY), Color.green);
- Graph Viewer: This script manages the data and the drawing of the graph within a specified
IMGUIContainer.
- Data Simulation: The
Update method simulates incoming data at specified intervals and stores this data in a circular buffer fashion by shifting old data points.
- Drawing: The
DrawGraph method is called to redraw the graph each time MarkDirtyRepaint is called on the graphContainer. It uses the GUI class to draw lines between data points, creating a simple graph visualization.
- Attach the
GraphViewer script to a GameObject in your scene.
- Assign the
UIDocument (which contains your UI Document with the GraphContainer) to the uiDocument field in the Inspector.
This example provides a basic starting point. You may extend it by incorporating more complex data handling, interactive features (like zooming and panning), and optimizing performance for your specific needs.