How to Draw Line Graph in unity

Hello Friends
i doing a simulation project, in which i had a task of drawing the graph(Line Graph). i have to get the values from database and display graph for last 24 hours.

so here the problem
i goggled over forums, in there i can find any help for drawing graph, so pl suggest me some tips to draw graph in GUI . i have to show this graph in GUI at left bottom of window

Thanks in advance

Arun

One possibility is to use a line renderer in the scene. If you use an orthographic camera (ie, one without no perspective) you should find it fairly easy to match Unity’s coordinates to the coordinate space of the graph. Another option might be to use Eric5h5’s Vectrosity tool.

1 Like

My best answer for you is to drop into OpenGL for this. I’m not quite sure how to do it just yet, but I believe it can be done.

Alternatively, I noticed Eric5h5 has a line drawing utility you might be able to utilized.

If none of the above work, the last thing you can try it unsing lineRenderer and place it a distance away from the camera using ScreenPointToWorldPoint.

1 Like

hi friend,

Thanks for your help and suggestion and will work out and let you know

Thanks
Arun

Im trying to draw some lines (not planes as “LineRender” does) and I found this:

  1. GL.LINES and all other GL. stuff doesen’t appears on compiled version, only on unity editor.
  2. Use SetPixel() within textures seems to have a very bad performance, as I need to call Texture2D.Apply() every frame, or at least when changes occur (and that is very very often).

am I right ?

1 Like
  1. GL stuff does appear in the compiled version; make sure you’re setting up the material/shader correctly. However Vectrosity is the best and fastest line-drawing solution.
  2. Yes, you need to call Apply() every frame and yes, it’s slow.

–Eric

Here’s some code I use to draw a graph on a texture:

// Attach to simple sprite
// sprite anchor must be set to BOTTOM_LEFT
// sprite texture Wrap Mode must be set to Clamp
// must have rigid body and collider attached for smart cursor

//----------------------------------------------

var blankTexture: Texture2D;  // the blank "paper", assigned in Inspector
var graphTexture: Texture2D;  // the "paper" to draw on, assigned in Inspector
var dotSymbol: Texture2D;  // the symbol to draw, assigned in Inspector
var graphCoordinates: TextMesh;  // where to put the smart cursor info, assigned in Inspector

var pXMin: float; // x axis min value,  // set in Inspector
var pXMax: float; // x axis max value,  // set in Inspector
var pYMin: float; // y axis min value,  // set in Inspector
var pYMax: float; // y axis max value,  // set in Inspector
var pPlotXRange = new Array();  // min/max list
var pPlotYRange = new Array();  // min/max list
var pPlotXScale: float;  // size of the bitmap
var pPlotYScale: float;  // size of the bitmap
var pNewXScale: float;  // adjusted scale
var pNewYScale: float;  // adjusted scale

var axisWidth: float; // length of X axis + offset, set in Inspector
var axisHeight: float; // length of Y axis + offset,  set in Inspector
var xOffset: float;  // x axis origin offset,  // set in Inspector
var yOffset: float;  // y axis origin offset,  // set in Inspector
var symbolSize: int;  // set in Inspector

var symbolHalfWidth: float;  // half size of symbol
var symbolHalfHeight: float;  // half size of symbol

var dRect: Rect;
var dotColors: Color[];
var xx: int;
var yy: int;
var i: int;

var theRay: Ray;
var hit: RaycastHit;

var theCursor: GameObject; // set in Inspector
var spriteWidth: float; // set in Inspector
var spriteHeight: float; // set in Inspector
var cursorCenterOffset: int; // offset from eduge to center of cursor, set in Inspector
private var lastPosition : Vector3;  // Where the mouse position was last

//----------------------------------------------

function Start () {
		
	InitGraph();

	SetXRange(pXMin, pXMax);
	SetYRange(pYMin, pYMax);
  
	pPlotXScale = axisWidth;
	pPlotYScale = axisHeight;
	SetupScale();
		
	theCursor.active = false;
    lastPosition = Input.mousePosition;
	cursorCenterOffset = 5;
}

//----------------------------------------------
// only used for smart cursor

function Update() { 
		
    var mousePos = Input.mousePosition;	
		  	    
   	theRay = mainCamera.ScreenPointToRay(mousePos);
   	
   	// we need to hit a collider
	if (!Physics.Raycast(theRay, hit, 100)){
		if (theCursor.active == true) {
			theCursor.transform.position.x = -999.0;
			Screen.showCursor = true;
			theCursor.active = false;
		return;
		}
	}
		
	// We need to hit a rigidbody 
	if (!hit.rigidbody) {
		if (theCursor.active == true) {
			theCursor.transform.position.x = -999.0;
			Screen.showCursor = true;
			theCursor.active = false;
		return;	
		}
	}

	if (hit.transform == transform) {						
	    // If the mouse has moved since the last update
	    if (mousePos != lastPosition) {
	        lastPosition = mousePos;
	        // Get mouse X and Y position as a percentage of screen width and height
	        Screen.showCursor = false;
			theCursor.active = true;
			
	        MoveMouse(mousePos.x - (Screen.width / 2.0), mousePos.y - (Screen.height / 2.0));
	        UpdateCursorCoordinates(mousePos.x - (Screen.width / 2.0), mousePos.y - (Screen.height / 2.0));
	    }
	}
}
  
// ------------------------------------------

function InitGraph () {

	dotColors = blankTexture.GetPixels(0);
	graphTexture.SetPixels(dotColors, 0);
	graphTexture.Apply();
	renderer.material.mainTexture = graphTexture;
}

//----------------------------------------------

function DrawGraph (theData: Array) {
  
	dotColors = blankTexture.GetPixels(0);
	graphTexture.SetPixels(dotColors, 0);
	
	SetupScale();
	for (i = 0; i < theData.length; i++) {
		PlotPoint(theData[i].x, theData[i].y, false);
	}
	graphTexture.Apply();	
	renderer.material.mainTexture = graphTexture;
}

//----------------------------------------------

function PlotPoint (xx, yy: float, redraw: boolean) {
	  
	yy = Mathf.Round((yy * pNewYScale) - (pPlotYRange[0] * pNewYScale)) + yOffset;
 
	xx = Mathf.Round((xx * pNewXScale) - (pPlotXRange[0] * pNewXScale)) + xOffset;
   
	symbolHalfWidth = Mathf.Round(symbolSize / 2.0);
	symbolHalfHeight = Mathf.Round(symbolSize / 2.0);
	
	if (xx > spriteWidth - symbolHalfWidth)
		return;
	if (yy > spriteHeight - symbolHalfHeight)
		return;	
	if (xx < xOffset)
		return;
	if (yy < yOffset)
		return;
	
	//Circle(graphTexture, xx, yy, symbolHalfWidth, Color.black);  // draw circle
	
	dRect = Rect(xx - symbolHalfWidth, yy - symbolHalfHeight, dotSymbol.width, dotSymbol.height);  // draw symbol
	
	dotColors = dotSymbol.GetPixels(0);
	graphTexture.SetPixels(xx - symbolHalfWidth, yy - symbolHalfHeight, dotSymbol.width, dotSymbol.height, dotColors, 0); 

	if (redraw)
		graphTexture.Apply();
}

//----------------------------------------------

function SetXRange (tMin, tMax: float) {
	
	pXMin = tMin;
	pXMax = tMax;  
	pPlotXRange = [tMin, tMax];  
}

//----------------------------------------------

function SetYRange (tMin, tMax: float) {  
	
	pYMin = tMin;
	pYMax = tMax;
	pPlotYRange = [tMin, tMax];  
}

//----------------------------------------------
// must call before plotting first point if anything has changed since InitGraph

function SetupScale () {
	pNewXScale = pPlotXScale/(pPlotXRange[1] - pPlotXRange[0]);
	pNewYScale = pPlotYScale/(pPlotYRange[1] - pPlotYRange[0]);
}

//----------------------------------------------
// "texture" is the texture you want to draw the circle in
// "x" and "y" are the x and y coordinates of the midpoint of the circle
// "radius" is the radius of the circle in pixels
// "color" is the color of the circle

function Circle (tex : Texture2D, cx : int, cy : int, r : int, col : Color) {
	
    var y = r;
    var d = 1/4 - r;
    var end = Mathf.Ceil(r/Mathf.Sqrt(2));
    
    for (x = 0; x <= end; x++) {
        tex.SetPixel(cx+x, cy+y, col);
        tex.SetPixel(cx+x, cy-y, col);
        tex.SetPixel(cx-x, cy+y, col);
        tex.SetPixel(cx-x, cy-y, col);
        tex.SetPixel(cx+y, cy+x, col);
        tex.SetPixel(cx-y, cy+x, col);
        tex.SetPixel(cx+y, cy-x, col);
        tex.SetPixel(cx-y, cy-x, col);
        
        d += 2*x+1;
        if (d > 0) {
            d += 2 - 2*y--;
        }
    }
}

//----------------------------------------------

function MoveMouse(mousePosX : float, mousePosY : float) {
    theCursor.transform.position.x = mousePosX - cursorCenterOffset;
    theCursor.transform.position.y = mousePosY + cursorCenterOffset;
}

//----------------------------------------------

function UpdateCursorCoordinates (mousePosX : float, mousePosY : float) {
	
	var tLoc: Vector2;
	var tempNewXScale: float;
	var tempNewYScale: float;
	
	tLoc.x = mousePosX - transform.position.x;
	tLoc.y = mousePosY - transform.position.y;

	tempNewYScale = pNewYScale;
	tLoc.y = (tLoc.y + (pPlotYRange[0] * tempNewYScale) - yOffset) / tempNewYScale;
	
	tempNewXScale = pNewXScale;
	tLoc.x = (tLoc.x + (pPlotXRange[0] * tempNewXScale) - xOffset) / tempNewXScale;
	
	if (tLoc.x < pXMin)
		tLoc.x = pXMin;		
	if (tLoc.y < pYMin)
		tLoc.y = pYMin;

	graphCoordinates.text = "t = " + tLoc.x.ToString("F2") + " sec, y = " + tLoc.y.ToString("F3") + " m";
  
}

It uses EZ GUI, hence the sprite reference, but should work with any 2D texture. It also includes a “smart cursor” that you can move over the graph and display the coordinates. It currently draws either predefined symbols or circles. It could easily be modified to draw a line between two points. Check out the Unify wiki for line-drawing code.

3 Likes