I made a tutorial for you that should get you up and running. I don't know your background so I made it as comprehensive as possible just in case. That being said, here you go:
First, you can simplify the fingerdetect assignment. No need to do if statement checks against the input, those inputs already return bools. Try this:
fingerdetect = (Input.GetKeyDown(KeyCode.Space));
Another thing though, due to the way unity's inputs work, this won't act the way you expect. It will only add a new dot when you press space and hadn't had it pressed the previous frame. Let's touch it up:
fingerdetect = (Input.GetKey(KeyCode.Space));
Now that we've got that out of the way, Are you sure this is what you want?
if (Input.GetKeyDown(KeyCode.Space))
{
fingerdetect = true;
lineRenderer.SetVertexCount(0);
linePoints.RemoveRange(0, linePoints.Count);
lineRenderer.SetColors(Color.green , Color.green);
}
This code clears the line renderer when you're holding the button down. Further down though, we use the same condition to add to the line. This means your total line length will never exceed a single point. By definition, you can't have a line like this. Lets' do some touch ups, and the code should look like this for your Update() function:
void Update()
{
Frame frame = controller.Frame();
Finger finger = frame.Hands[0].Fingers
[(int)Finger.FingerType.TYPE_INDEX];
Vector3 fingerTipPos = finger.TipPosition.ToUnityScaled();
fingerdetect = (Input.GetKey(KeyCode.Space));
if (fingerdetect)
{
fingerTipPos = Camera.main.ScreenToViewportPoint(fingerTipPos);
fingerTipPos.z = 0;
if (!linePoints.Contains(fingerTipPos))
{
linePoints.Add(fingerTipPos);
lineRenderer.SetVertexCount(linePoints.Count);
lineRenderer.SetPosition(linePoints.Count - 1, (Vector3)linePoints[linePoints.Count - 1]);
Debug.Log(string.Format("Added point at: {0}!", fingerTipPos));
}
}
}
Now we've got something looking a little more like this:
Whoa! That's alot of points for what is just a tiny ball! What we have here is a conceptual problem. We're sampling data tons of times a second, while most of that data isn't going to be very different. Your initial approach acknowledges this, but unfortunately it's a little too naive. Due to the way hands and fingers work IRL, they don't ever sit in exactly the same spot, even when the human attached to them thinks they're 'still'. It also means that if the person is moving their finger slowly, we get more resolution than if they moved their hand quickly. What we need to do is filter the data somehow. Instead of checking for two identical points, why not use a delta (change) value? Let's make a new variable for this:
private float newPointDelta = 0.02f;
In Unity, the scale is in meters, so this new delta value is 2cm. I got this by pulling out a ruler and seeing what distance 'felt' good for a small movement. Let's implement the actual check in the code. Replace:
if (!linePoints.Contains(fingerTipPos))
{
linePoints.Add(fingerTipPos);
lineRenderer.SetVertexCount(linePoints.Count);
lineRenderer.SetPosition(linePoints.Count - 1, (Vector3)linePoints[linePoints.Count - 1]);
Debug.Log(string.Format("Added point at: {0}!", fingerTipPos));
}
With:
// Using named temp variables like this helps me think more clearly about the code
Vector3 previousPoint = (linePoints.Count > 0) ? linePoints[linePoints.Count - 1] : new Vector3(-1000, -1000, -1000); // If you've never seen this before, it's called a ternary expression.
// It's just an if/else collapsed into a single line of code.
// Also, the crazy out of bounds initial value here ensures the starting point will always draw.
if (Vector3.Distance(fingerTipPos, previousPoint) > newPointDelta)
{
linePoints.Add(fingerTipPos);
lineRenderer.SetVertexCount(linePoints.Count);
lineRenderer.SetPosition(linePoints.Count - 1, (Vector3)linePoints[linePoints.Count - 1]);
Debug.Log(string.Format("Added point at: {0}!", fingerTipPos));
}
When I tried running this, I ran into an issue: no lines were spawning at all. I imagine it's due to the fact that something isn't scaling right. I'm not used to retrieving the Leap Controller the way you are, by instantiating one with the new constructor in the Awake method. It might be a valid way to do things, but I'll have to use the method I know to get things working correctly. So, in a new scene, let's drag the prefab "Assets/LeapMotion/Prefabs/HandControllerSandBox" into the scene. It should look like this:
And after that, we'll make another new object and call it 'Painter'. Add the fingertip script to the new painter object. Now we'll need to place it above the HandController object in the scene, so a location of 0,0,-3 should be about right. Make sure the camera is at the position: 0, 3, 0
We'll need to jump back into our script to change the way our hand data is acquired. Let's go back into our FingerTip script and look at the beginning of the file. Replace:
Leap.Controller controller = new Controller();
With:
public HandController LeapHandController;
In Awake() we'll need to delete the line that instantiated the old controller:
controller = new Controller();
And in Update, we'll change how we get the fingertip position by doing the following:
void Update()
{
HandModel[] allGraphicHands = LeapHandController.GetAllGraphicsHands();
if (allGraphicHands.Length <= 0) return;
HandModel handModel = allGraphicHands[0];
finger = handModel.fingers[(int)Finger.FingerType.TYPE_INDEX];
fingerTipPos = finger.GetTipPosition();
The scripts should all compile, and if they do you can now run back to the editor. We'll need to assign the HandController in the scene to the variable our script expects. Like so:
Alright. The screen-space scaling might have been messing us up before too. Let's go back and turn that into real-world coordinates. In the finger detection script, delete the following two lines:
fingerTipPos = Camera.main.ScreenToViewportPoint(fingerTipPos);
fingerTipPos.z = 0;
Once that's all done, go back to your scene, put one hand over the Leap Motion Controller. Once the hand registers, you'll see a black poly model in the world. Hold the spacebar down and a line will draw every time the finger moves 2cm in the real world!
There's way more we can do past this point, like flatten the drawing to 2d space, use a custon hand model that shows a glowing marker of where you'll draw, save to a file, etc. But this should be enough to get you up and running.
The completed project is available here: https://github.com/jcorvinus/FingerPainting