Search code examples
c#unity-game-enginecenterdirectionindicator

Unity lineRenderer takes the 0,0 point as center


In my 2D unity mobile game, when I touch and pull the ball it shows up a lineRenderer from the ball through the way I pull there is no problem with that but if I touch to screen while the ball is dynamic (before it stopped) the new lineRenderer take (0,0) point as the center instead of the location of the ball.

This is how it works properly when I touch the screen while the ball is not moving

This is the problematic version line renderer starts from the point (0,0) instead of the ball

void Update()
    {
        

        if (Input.touchCount > 0 && !hasMoved)
        {
            touch = Input.GetTouch(0);

            if (touch.phase == TouchPhase.Began)
            {
                dragStart();
            }
            if (touch.phase == TouchPhase.Moved)
            {
                Dragging();
            }
            if (touch.phase == TouchPhase.Ended)
            {
                DragRelease();


            }
        }
}

 void dragStart()
    {
        dragStartposition = transform.position;

        dragStartposition.z = 0;

        gostergeLine.positionCount = 1;

        gostergeLine.SetPosition(0,transform.position);
    }

    void Dragging()
    {
        Vector3 draggingPos = Camera.main.ScreenToWorldPoint(touch.position);
        draggingPos.z = 0;
        gostergeLine.positionCount = 2;
        gostergeLine.SetPosition(1, draggingPos);

    }

    void DragRelease()
    {
        gostergeLine.positionCount = 0;

        Vector3 dragReleasePos = Camera.main.ScreenToWorldPoint(touch.position);

        dragReleasePos.z = 0;

        Vector3 forceVec = dragStartposition - dragReleasePos;

        forcePower = forceVec.magnitude;

        if(forcePower > 45)
        {
            topRb.velocity = forceVec * 45;
        }
        else
        {
            topRb.velocity = forceVec * forcePower;
        }
        

    }

Even though it does not read my touch while the ball is moving (!hasmoved); if I touch the screen before it stopped, the new linerenderer shows up in wrong direction.


Solution

  • Update is called every frame.

    The TouchPhase.Began is only true in the very first frame of a touch -> your ball was moving then so you ignored it

    Now you continue touching so eventually TouchPhase.Moved is true at some point

    => Since the ball stopped in the meantime you now call Dragging without having called dragStart before.


    You could make sure that the other cases are only called at all if dragStart was actually called first.

    You could e.g. use a nullable

    private Vector2? dragStartposition;
    

    and then check for it in

    void Dragging()
    {
        if(dragStartposition == null) return;
    
        ...
    }
    

    and also reset it in

    void DragRelease()
    {
        if(dragStartposition == null) return;
    
        ...
    
        Vector3 forceVec = dragStartposition.Value - dragReleasePos;
    
        ...
    
        dragStartposition = null;
    }   
    

    This way if a touch started to early it doesn't trigger the other methods, only if one started after the ball has stopped.

    There is still a pitfall though with multiple touches

    => I would also use exactly one touch only

    if(Input.touchCount == 1 && !hasMoved)