Choppy lines when using GUI.Label

EDIT: New Screenshots attached.

This is the current result. alt text

This is the app that I mentioned. alt text

EDIT: Here is my codes, after doing some addons to it with Herman's suggestion.

Here is my new script. Now I can't figure out how to call the OnGui function to draw the other points. Currently when I press a finger on the screen and drag, it does not create a trail along. Instead, the texture is just moving with my finger.

var drawArray : ArrayList = new ArrayList( );
var pos : Vector2;
var newPos : Vector2;
var lastPos : Vector2;

var distanceBetweenLastANdNew : Vector2;

var brush : Texture;

var minimumDistanceBetweenNodes : float = 0.1;

function Update () 
{

    for (var i = 0; i < iPhoneInput.touchCount; ++i) 
    {
        var hit : RaycastHit;
        var ray = Camera.main.ScreenPointToRay (iPhoneInput.GetTouch(i).position);

        if(iPhoneInput.GetTouch(i).phase == iPhoneTouchPhase.Began)
        {   
            pos = new Vector2(iPhoneInput.GetTouch(i).position.x,iPhoneInput.GetTouch(i).position.y);

        }

        if(iPhoneInput.GetTouch(i).phase == iPhoneTouchPhase.Moved)
        {
            pos = new Vector2(iPhoneInput.GetTouch(i).position.x, iPhoneInput.GetTouch(i).position.y);
            drawArray.Add(pos);
            AddPoint(pos);

        }
        if(iPhoneInput.GetTouch(i).phase == iPhoneTouchPhase.Ended)
        {
            drawArray.Clear();
        }

    }

}

function AddPoint(newPos : Vector2)
{
    lastPos = drawArray[drawArray.Count - 1];
    distanceBetweenLastAndNew = (lastPos - newPos).magnitude;

    if(distanceBetweenLastAndNew > minimumDistanceBetweenNodes)
    {  
        direction = (newPos - lastPos);
        for(var k : int = 0; k < distanceBetweenLastAndNew / minimumDistanceBetweenNodes; k++)
        {
         // Add the interpolated point
         drawArray.Add(lastPos +  k * direction);
         }

   }
}

function OnGUI () 
{
    if (drawArray.Count>0)
    {
        for (var lastPos : Vector2 in drawArray)
        {           
            GUI.Label(Rect (pos.x, Screen.height - pos.y, brush.width, brush.height),brush);
        }   
    }
}

I am not sure whether using GUI Labels is a good way to draw the lines. (Using a LineRenderer in 3D is perhaps better, although it might be tricky to get it to draw over everything else.)

However, you can make it work by interpolating between array points that are far apart. The easiest would be to add extra points as the array is being filled. Here is how it looks (based on your code sample).

var drawArray : ArrayList = new ArrayList( );
var lastPos : Vector2;    

var brush : Texture;
var minimumDistanceBetweenNodes : float = 0.1;
var distanceBetweenLastAndNew : Vector2;

function Update () 
{
    for (var i = 0; i < iPhoneInput.touchCount; ++i) 
    {
        var hit : RaycastHit;
        var ray = Camera.main.ScreenPointToRay (iPhoneInput.GetTouch(i).position);

        if(iPhoneInput.GetTouch(i).phase == iPhoneTouchPhase.Began)
        {   //Add the first point
            AddPoint(iPhoneInput.GetTouch(i)); //WARNING: you should maintain separate arrays for each touch!
        }

        if(iPhoneInput.GetTouch(i).phase == iPhoneTouchPhase.Moved)
        {                
            AddPoint(iPhoneInput.GetTouch(i)); //WARNING: you should maintain separate arrays for each touch!  
        }
        if(iPhoneInput.GetTouch(i).phase == iPhoneTouchPhase.Ended)
        {
            drawArray.Clear();
        }    
    }    
}    

function AddPoint(newPos : Vector2)
{
    //what to do if the array is empty
    if(drawArray.Count == 0)
    {
       drawArra.Add(newPos);
       return;
    }

    lastPos = drawArray[drawArray.Count - 1];
    distanceBetweenLastAndNew = (lastPos - newPos).magnitude;    

    if(distanceBetweenLastAndNew > minimumDistanceBetweenNodes)
    {  
        direction = (newPos - lastPos).normalized;
        for(var k : int = 0; k < distanceBetweenLastAndNew / minimumDistanceBetweenNodes; k++)
        {
         // Add the interpolated point
         drawArray.Add(lastPos +  minimumDistanceBetweenNodes * k * direction);
         }   
   }

   //Only add the new pint after adding all the interpolated points.
   drawArray.Add(newPos );
}

function OnGUI () 
{
    if (drawArray.Count>0)
    {
        for (var lastPos : Vector2 in drawArray)
        {           
            GUI.Label(Rect (pos.x, Screen.height - pos.y, brush.width, brush.height),brush);
        }   
    }
}

(But if I were you, I would really check out a method using LineRenderer).

As others have said, GUI.Label is probably not the way to go. GUI.* doesn't perform well enough on iOS to use for gameplay, unless not much else is being drawn at the same time. And the worse it performs, the bigger your gaps.

Having said that, you may have gaps regardless of how you draw the texture. So there are two parts to my answer: alternatives to GUI.Label, and a way to fill the gaps.

1) Alternatives to GUI.Label.

You might want to look at Texture2D.SetPixel or Texture2D.SetPixels. Your framerate will be better because you'll be accumulating colors into a single texture instead of drawing a large number of GUI.Label objects.

Or, you could simply create a sprite- a triangle or plane (not the built-in Unity plane object- that has way more vertices than you need) with your brush texture on it. You would create one at every touch point, instead of a GUI.Label. This will have a lot less overhead, and the mesh combiner will draw them all with one draw call.

2) Here's a simple algorithm to fill in the gaps [EDIT: which I now see Herman has already coded in a previous answer. Still, here is the description.]

If your frame rate is sufficiently high and your brush (the texture you draw at each position) is big you might not need this. The idea is simply to add new points along the line between the start and end point.

  • Take the starting position (previous touch position) and the new position.
  • Subtract start from end- this gives you the vector that goes from start to end.
  • If the vector length is less then some threshold (let's say 5) then there's no gap; add the new position to your list and you are done.
  • If the vector is too long then there is a gap. But all you have to do is add a whole bunch of points along that line, instead of just the endpoint.
  • So shrink the vector until it is only 5 pixels long, or whatever the threshold is. (This is easy- just call Vector2.Normalize to make it length 1, then multiple by 5.)
  • Now add this vector repeatedly to the start point. Each time, add the result to your list of points to draw.
  • You are done when you've gotten to (or past) the end point.