Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Draw on an object with a static brush (2D Raycasting)

Discussion in 'Scripting' started by quinnsea, Feb 19, 2023.

  1. quinnsea

    quinnsea

    Joined:
    Aug 29, 2018
    Posts:
    2
    Hi! I'm making a game where you move a piece of paper underneath a static marker in order to draw. (Like fabric going under a sewing machine.)

    I figured out how to get things to draw onto the paper using a mouse, but I don't know how to change the marker to something static. I know it'd probably be easier to just... use the mouse, but I really need it to be set up like this. From my understanding, raycasting is the way to go but I have no idea what I'm doing. I can't figure out for the life of me how to draw continuously on the paper. (The red lines are the line texture + me trying and failing to draw)



    Here's my code for telling the needle to draw the line. I'm getting the line onto the paper and to stick to it, but no new lines are being made as I move it.

    Code (CSharp):
    1.     public GameObject linePrefab;
    2.     public Transform needleTip;
    3.  
    4.     private bool isColliding = false;
    5.  
    6.     //what is being drawn on
    7.     private SpriteMask pattern;
    8.  
    9.     //where on the seam/pattern is this being sewn
    10.     private Vector2 stitchPos;
    11.  
    12.     //in what direction is the needle pointing
    13.     private Vector2 direction;
    14.  
    15.     private RaycastHit2D raycastHit;
    16.  
    17.     DrawMesh activeLine;
    18.  
    19.     private void Start()
    20.     {
    21.         direction = Vector2.zero;
    22.     }
    23.  
    24.     void Update()
    25.     {
    26.         // figure out what's being hit by the raycast
    27.         raycastHit = Physics2D.Raycast(needleTip.position, direction);
    28.  
    29.         // confirmed that the raycast is working kind of properly, it's hitting objects and recognizing
    30.         // that it's hitting objects
    31.         // it just doesn't know *where* on the objects
    32.  
    33.         // if player presses the space bar while the needle is colliding with a pattern...
    34.         if (Input.GetKeyDown(KeyCode.Space) && isColliding == true)
    35.         {
    36.             // make a line where the needle currently is and attach it to the pattern as a child
    37.             GameObject newLine = Instantiate(linePrefab, needleTip.position, needleTip.rotation);
    38.             newLine.transform.SetParent(pattern.transform);
    39.             //activeLine = newLine.GetComponent<DrawMesh>();
    40.         }
    41.    
    42.         // if the player stops pressing the space bar, they're no longer sewing
    43.         if (Input.GetKeyUp(KeyCode.Space))
    44.         {
    45.             activeLine = null;
    46.         }
    47.  
    48.         // this is where we get the position and tell the line to start drawing
    49.         if (activeLine != null && isColliding == true)
    50.         {
    51.             //this DID work but the line is being drawn where the mouse is
    52.             //Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    53.             //activeLine.UpdateLine(mousePos);
    54.  
    55.             //this currently isn't doing anything
    56.             Vector2 needlePos = raycastHit.point;
    57.             activeLine.UpdateLine(needlePos);
    58.         }
    59.     }
    60.  
    61.     private void OnTriggerEnter2D(Collider2D collision)
    62.     {
    63.         // checks if what's colliding with the needle is a pattern or a seam
    64.         // will sew no matter what
    65.         if (collision.gameObject.tag == "Pattern" || collision.gameObject.tag == "Seam")
    66.         {
    67.             isColliding = true;
    68.             pattern = collision.GetComponent<SpriteMask>();
    69.         }
    70.     }
    71.  
    72.     private void OnTriggerStay2D(Collider2D collision)
    73.     {
    74.         if (collision.gameObject.tag == "Pattern" || collision.gameObject.tag == "Seam")
    75.         {
    76.             isColliding = true;
    77.         }
    78.     }
    79.  
    80.     private void OnTriggerExit2D(Collider2D collision)
    81.     {
    82.         if (collision.gameObject.tag == "Pattern" || collision.gameObject.tag == "Seam")
    83.         {
    84.             isColliding = false;
    85.         }
    86.     }
    And here's the code for the line being created: (My "DrawMesh" component)
    Code (CSharp):
    1.     public LineRenderer lineRenderer;
    2.  
    3.     List<Vector2> points;
    4.  
    5.     public void UpdateLine(Vector2 position)
    6.     {
    7.         if (points == null)
    8.         {
    9.             points = new List<Vector2>();
    10.             SetPoint(position);
    11.             return;
    12.         }
    13.  
    14.         if (Vector2.Distance(points.Last(), position) > .1f)
    15.         {
    16.             SetPoint(position);
    17.         }
    18.     }
    19.  
    20.     void SetPoint(Vector2 point)
    21.     {
    22.         points.Add(point);
    23.  
    24.         lineRenderer.positionCount = points.Count;
    25.         lineRenderer.SetPosition(points.Count - 1, point);
    26.     }
    The only other script I'm using right now is a pretty basic click and drag script to move the paper around. What *is* being generated is moving with the paper just fine.
     
    Last edited: Feb 19, 2023
  2. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    Add the raycast script to an empty GO where you need it to be to perform your operation. It doesn't need to be coming from the mouse.
     
  3. quinnsea

    quinnsea

    Joined:
    Aug 29, 2018
    Posts:
    2
    Makes sense! I fixed that, and it's drawing now, but it's going in a weird direction instead of constantly coming out of the GO. (It's at the tip of the arrow, to be clear.)



    Code (CSharp):
    1.     void Update()
    2.     {
    3.         // if player presses the space bar while the needle is colliding with a pattern...
    4.         if (Input.GetKeyDown(KeyCode.Space) && isColliding == true)
    5.         {
    6.             raycastHit = Physics2D.Raycast(pattern.transform.localPosition, direction);
    7.             // make a line where the needle currently is and attach it to the pattern as a child
    8.             GameObject newLine = Instantiate(linePrefab);
    9.             Vector3 distance = raycastHit.point;
    10.             newLine.transform.position = (needleTip.transform.position - distance);
    11.             newLine.transform.SetParent(pattern.transform);
    12.             activeLine = newLine.GetComponent<DrawMesh>();
    13.         }
    14.        
    15.         // if the player stops pressing the space bar, they're no longer sewing
    16.         if (Input.GetKeyUp(KeyCode.Space))
    17.         {
    18.             activeLine = null;
    19.         }
    20.  
    21.         // this is where we get the position/where the line should be drawn
    22.         if (activeLine != null && isColliding == true)
    23.         {
    24.             raycastHit = Physics2D.Raycast(pattern.transform.position, direction);
    25.  
    26.             Vector2 needlePos = raycastHit.point;
    27.             activeLine.UpdateLine(needlePos);
    28.         }
    29.     }
     
  4. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    Yeah, you'll need to play with it to get it exactly how you want it.