Hello,
I would like to be able to fluidly draw on top of any unity scene.
I have tried to do this on the Gui as well as on a texture in a world object.
The code below works, but the mouse drawing is slow and jerky. The problem is that I don’t get real time pos from Input.mousePosition. I tried to use Texture2D.SetPixels and Texture2D.Apply as little as possible.
My questions:
-
How can I draw fluidly on a texture ? GUI or world object. I’m new to Unity so I am not sure the approach I chose is the correct one. Feel free to suggest different methods. I know there are other ways to get mouse input, but Input.mousePosition seemed the most precise.
-
Is there a way to freeze the Unity3D engine and give the GUI priority ? I don’t mind freezing the scene in some cases, while in others I would like the action to continue in the background.
-
I also tried without the GUI, putting a semi transparent world object in front of the camera and drawing on its texture, thinking that function Update() might update faster than function OnGUI() but Input.mousePosition was just as slow.
-
If I reduce the game world window, mouse tracking is more fluid. But I need this to run on a high resolution.
-
I don’t necessarily have to draw 1 pixel dots, I just used that as the first attempt. Eventually I would like to use brushes of various sizes. I saw [here][1] that textures can be linked to brushes in the inspector.
-
Also, eventually I would like to draw not with the mouse but with gestures on an iPad. Will it be easy to replace Input.mousePosition with gesture inputs ? For now I don’t have Unity Pro or the iOS addon, but plan to buy them later on.
-
Is it possible to make a game like crayon physics with Unity ? or is it optimized for 3D rendering ? Just wondering if this is the right tool for what I need to do.
Notes:
I’m not making a game, but just used crayon physics as a reference of something that has fluid drawing capabilities.
I’m new to all this so please bare with me. Also, thought this might be useful for other people, so I will edit to add references to other answers.
System info: win7 64bit, decent graphic card.
Here is my code
#pragma strict
private var canvasBackground: Texture2D;
private var locked: boolean = true;
// initialize the canvas
canvasBackground = new Texture2D(Screen.width, Screen.height);
// get the size of the screen
private var pixels = Screen.width * Screen.height;
// create a color array
private var colors = new Color[pixels];
private var pencolor = Color.black;
// buffer is used to avoid setting pixels on each onGUI call
private var buffer = 0;
// last detected mouse position
private var lastpos:Vector3;
private var reset:boolean = true;
// fill color array with a BG color -- optional -- commented out to leave it transparent
/* for (var i=0;i<pixels;i++)
{
colors *= Color.black;*
} */
function OnGUI() {
-
// mouse 1 shows the ‘canvas’*
-
if (locked && (Input.GetMouseButton(1)) ) {*
-
locked = false;*
-
}*
-
if (locked)*
-
return;*
-
// mouse 2 hides the ‘canvas’*
-
if (!locked && (Input.GetMouseButton(2)) ) {*
-
locked = true;*
-
return;*
-
}*
-
// mouse 0 ‘paints’*
-
if (Input.GetMouseButton(0)){*
-
var currpos:Vector3 = Input.mousePosition;*
-
if (reset){*
-
reset = false;*
-
lastpos = currpos;*
-
}*
-
line(lastpos.x, lastpos.y, currpos.x, currpos.y);*
-
lastpos = currpos;*
-
buffer++;*
-
if (buffer > 9){*
-
buffer = 0;*
-
canvasBackground.SetPixels(colors,0);*
-
canvasBackground.Apply(false);*
-
}*
-
} else {*
-
reset = true;*
-
}*
-
// GUI.Box(Rect(xpos, ypos, 120, 120), “”);*
-
GUI.Box(Rect(0, 0, canvasBackground.width, canvasBackground.height), “”);*
-
// Override the default texture with the custom texture.*
-
GUI.skin.box.normal.background = canvasBackground;*
}
// Bresenham’s line algorithm
function line(x0:int, y0:int, x1:int, y1:int){
var dx = Mathf.Abs(x1-x0);
var dy = Mathf.Abs(y1-y0);
var sx = (x0 < x1) ? 1 : -1;
var sy = (y0 < y1) ? 1 : -1;
var err = dx-dy;
while(true){
// Draw the ‘pixels’ in the color array
_ colors[x0 + Screen.width * y0] = pencolor;_
if ((x0==x1) && (y0==y1)) break;
var e2 = 2*err;
if (e2>-dy){
err -= dy;
x0 += sx;
}
if (e2 < dx){
err += dx;
y0 += sy;
}
}
}
[1]: http://unity3d.com/support/documentation/ScriptReference/GUI.DrawTexture.html