Home > other >  How to set linerender to be drawn only in 3 directions in Unity
How to set linerender to be drawn only in 3 directions in Unity

Time:02-23

I really don't know how the title of this question should look like, bcs the question is more complex.Here i uploaded 2 images.

Here i created board using positions from 0 to row lenght,and then i added linerenderer to draw a line from first touch position to last touach position and everything works fine

So my question is how to draw a line from starting point to last point,but if the line from starting point is not in the angle of 45,set it to be angle 45,between x and y and from starting point. F.e if i have a situation like on the picture above,i want to transform it like in the picture below.

It should look like this,and line only should be able to go horizontal,vertical and diagonal(180,90 and 45 degrees)

So if the line is not drawn on any of this directions,move it to closest one.

CodePudding user response:

Without knowing more about your project you can map your input onto the available directions using something like e.g.

private readonly Vector2[] _availableDirections =
{
    Vector2.up,
    Vector2.right,
    Vector2.down,
    Vector2.left,

    new Vector2.one,
    -new Vector2.one,
    new Vector2(1, -1),
    new Vector2(-1, 1)
};

private Vector2 MapToClosestDirection(Vector2 startPoint, Vector2 endPoint)
{
    // get the current input direction
    var currentDirection = (endPoint - startPoint);

    // Find the available direction for which the angle is the smallest
    var smallestAngle = float.MaxValue;
    var direction = currentDirection;
    foreach (var availableDirection in _availableDirections)
    {
        var currentAngle = Vector2.Angle(currentDirection, availableDirection);
        if (currentAngle < smallestAngle)
        {
            direction = availableDirection;
            smallestAngle = currentAngle;
        }
    }

    // then project your input onto this direction
    var mappedDirection = (Vector2)Vector3.Project(currentDirection, direction);

    return startPoint   mappedDirection;
}

This could look like e.g.

[SerializeField]
private LineRenderer _line;

[SerializeField]
private Camera _camera;

private readonly Vector2[] _availableDirections =
{
    Vector2.up,
    Vector2.right,
    Vector2.down,
    Vector2.left,

    new Vector2.one,
    -new Vector2.one,
    new Vector2(1, -1),
    new Vector2(-1, 1)
};

private Vector2 _startPoint;

private void Awake()
{
    if (!_camera) _camera = Camera.main;

    _line.positionCount = 2;
}

private void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        _line.gameObject.SetActive(true);
        _startPoint = _camera.ScreenToWorldPoint(Input.mousePosition);
        _line.SetPosition(0, _startPoint);
    }

    if (Input.GetMouseButton(0))
    {
        _line.SetPosition(1, MapToClosestDirection(_startPoint, _camera.ScreenToWorldPoint(Input.mousePosition)));
    }

    if (Input.GetMouseButtonUp(0))
    {
        _line.gameObject.SetActive(false);
    }
}

private Vector2 MapToClosestDirection(Vector2 startPoint, Vector2 endPoint)
{
    var currentDirection = (endPoint - startPoint);

    var smallestAngle = float.MaxValue;
    var direction = currentDirection;
    foreach (var availableDirection in _availableDirections)
    {
        var currentAngle = Vector2.Angle(currentDirection, availableDirection);
        if (currentAngle < smallestAngle)
        {
            direction = availableDirection;
            smallestAngle = currentAngle;
        }
    }

    var mappedDirection = (Vector2)Vector3.Project(currentDirection, direction);
    return startPoint   mappedDirection;
}

enter image description here

  • Related