How do I allow tracing with the mouse in a 2D environment?

I currently have this script that allows the player to draw freely on a 2D scene:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DrawWithMouse : MonoBehaviour
{
    [SerializeField] private GameObject linePrefab;
    private LineRenderer currentLine;
    private Vector2 previousPosition;
    [SerializeField] float minDistance = 0.1f;
    [SerializeField, Range(0.1f, 2f)] float width;

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            CreateNewLine();
        }

        if (Input.GetMouseButton(0))
        {
            Vector2 currentPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            if (Vector2.Distance(currentPosition, previousPosition) > minDistance)
            {
                currentLine.positionCount++;
                currentLine.SetPosition(currentLine.positionCount - 1, currentPosition);
                previousPosition = currentPosition;
            }
        }
    }

    private void CreateNewLine()
    {
        GameObject lineObject = Instantiate(linePrefab);
        currentLine = lineObject.GetComponent<LineRenderer>();
        currentLine.positionCount = 1;
        previousPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        currentLine.SetPosition(0, previousPosition);
        currentLine.startWidth = currentLine.endWidth = width;
    }
}

I would like to use this script to instruct the player to trace over a dotted pattern similar to the one shown below and determine if the player has properly traced the pattern or not:

Any help would be appreciated. Thank you!

I’m assuming the shape may vary quite a lot and not only a circle, so we’ll avoid circle math and instead go for a quick and dirty solution.

First, we need to create a list of solution points. We’ll generate it from our own mouse’s movement.

  1. create a script to track the mouse’s Vector2s and add it to a List when you move the mouse holding down left click
  2. normalize these positions so it doesn’t matter where the object was displayed or the screen resolution
  3. ta da, you have your “solution” positions of normalized Vector2s in a list
  4. copy this list from the Inspector, exit playmode, and paste it somewhere permanent, eg circleSolutionList field

To validate the user’s result, put all these solution points into a Dictionary<Vector2, int> where the key is one of your solution points and the value is a count.

then
5. let the user trace the shape, collecting the Vector2s and adding to a List
6. normalize by the same procedure
7. do a distance check:

  • increment the count in your dictionary for every point that a point is adjacent to. A user point may be adjacent to multiple solution points. All solution points need to have at least 1 count by the end of the user’s trace or else they did not trace all the points
  • if any user point does not pass the distance check for all solution points, the user did not trace close enough to the solution (cutting corners, drawing too far outside)

Not saying this is an ideal solution but it’s pretty straightforward. Depending on your tracing rules (do they need to trace in a paritcular direction?), it could fail, but it should work for the general shape. You could add a timer so that the # of points does not grow extremely large since this is o(n*n)

I might be wrong but I believe a better way to do this might be using animation curves rather than just adding to a list of Vector2s over a period of time.

Is there a way to get arbitrary shapes with Animation Curves?

Do you really need arbitrary shapes or do you just need to trace coordinates over a given period of time?

Hello! I apologize for the late reply, but yes, I’m trying to implement a way to trace different shapes (circle, square, triangle, etc.) within a time limit.

This sounds basically like gesture recognition.

The basics will involve:

  • reading a stream of input from the mouse
  • visualizing the ongoing line somehow (see below)
  • analyzing the line, which may involve:
    • decomposing it into lines or arcs
    • deciding if those decomposed lines / arcs are “close enough”

This isn’t super-easy stuff. For instance, most shapes can be draw starting from any part of them, doing the parts in any order, etc.

Your “analyze” method will probably need to incorporate some numeric grade representing “how good you did” so you can decide if you “did good enough.”

Here is a nod-yes, shake-no script I made a few years back that has a decent discussion of how it grades the ongoing gesture and ultimately decides if the user has done “yes” or “no”:

You could use AI for pattern recognition, pretty similar example in this showcase for Unity Sentis.