3

I created a diagonal line renderer by attaching the following script to an empty game object. How can I extend the line at both ends for a half its length and how can I also extend the line by say 1 unit along the x-axis? Both over a certain period of time.

public class DiagonalLine : MonoBehaviour {

bool firstLineComplete = false;
LineRenderer diagLine;

public Vector3 startPoint = new Vector3 (0, 0, 0);
public Vector3 endPoint = new Vector3 (1.0f, 1.0f, 0);

public float lineDrawSpeed;
// Use this for initialization
void Start () {

    diagLine = gameObject.AddComponent<LineRenderer>();
    diagLine.material = new Material (Shader.Find ("Sprites/Default"));
    diagLine.startColor = diagLine.endColor = Color.green;
    diagLine.startWidth = diagLine.endWidth = 0.15f;

    diagLine.SetPosition (0, startPoint);
    diagLine.SetPosition (1, endPoint);

    }
}

enter image description here

Programmer
  • 121,791
  • 22
  • 236
  • 328
Hilarious404
  • 434
  • 3
  • 13

2 Answers2

4

This is basic vector math.

You have the line with (from end to start):

 Vector3 v = start - end;

and then you extend on each side by half if it:

 extensionA = start + (v * 0.5f);
 extensionB = end + (v * -0.5f);

If you need to extend by 1 then normalize:

 Vector3 v = (start - end).normalized;
 extensionA = start + v;
 extensionB = end + (v * -1f);
Everts
  • 10,408
  • 2
  • 34
  • 45
  • okay, so how can I extend the line over a period of time, like an animation? – Hilarious404 Nov 06 '17 at 21:18
  • For the animation use a Coroutine and for(float t = 0; t < 1.0f; t += Time.deltaTime/animationDuration) { Vector3 newPos = Vector3.Lerp(fromPos, toPos, t); yield return null; } Vector3 finalPos = toPos; – sight Nov 07 '17 at 08:55
  • I guess your solution combined with Programmer's makes it complete – Hilarious404 Nov 07 '17 at 17:39
3

Break your problem into pieces:

1.Extend line by x units on both sides:

This is done with the Ray class. Create a new Ray instance from the startPoint and endPoint variables then use the Ray.GetPoint function to extend the line. You have to do this on both sides to get the new extended lines.

A simple wrapper for the Ray class to simplify this:

Vector3 extendLine(Vector3 startPoint, Vector3 endPoint, ExtendDirection extendDirection, float extendDistance)
{
    Ray ray = new Ray();

    //Start
    if (extendDirection == ExtendDirection.START_POINT)
    {
        ray.origin = startPoint;
        ray.direction = startPoint - endPoint;
    }

    //End
    else if (extendDirection == ExtendDirection.END_POINT)
    {
        ray.origin = endPoint;
        ray.direction = endPoint - startPoint;
    }

    //Extend
    Vector3 newUnityPoint = ray.GetPoint(extendDistance);
    //Debug.DrawLine(ray.origin, newUnityPoint, Color.blue);
    return newUnityPoint;
}

public enum ExtendDirection
{
    START_POINT, END_POINT
}

Extend to the Left end

Vector3 newStartPos = extendLine(startPoint, endPoint, ExtendDirection.START_POINT, 4);
diagLine.SetPosition(0, newStartPos);

Extend to the Right end

Vector3 newEndPos = extendLine(startPoint, endPoint, ExtendDirection.END_POINT, 4);
diagLine.SetPosition(1, newEndPos);

2.For animating/moving it over time, use coroutine and Time.deltaTime. Increment a variable with Time.deltaTime every frame to then use Vector3.Lerp to lerp the from and to value.

See this function for example.

With both combined, below is a complete function to extend both lines over time:

bool isRunning = false;

IEnumerator extentLineOverTime(LineRenderer targetLineRenderer, float extendDistance, float duration)
{
    //Calculate Left from extension length
    Vector3 fromValLeftPos = targetLineRenderer.GetPosition(0);
    //Calculate Right from extension length
    Vector3 fromValRightPos = targetLineRenderer.GetPosition(1);

    //Calculate Left to extension length
    Vector3 newLeftPos = extendLine(fromValLeftPos, fromValRightPos, ExtendDirection.START_POINT, extendDistance);
    //Calculate Right to extension length
    Vector3 newRightPos = extendLine(fromValLeftPos, fromValRightPos, ExtendDirection.END_POINT, extendDistance);

    //Make sure there is only one instance of this function running
    if (isRunning)
    {
        yield break; ///exit if this is still running
    }
    isRunning = true;

    float counter = 0;


    while (counter < duration)
    {
        counter += Time.deltaTime;

        //Move to left overtime
        Vector3 tempLeftPos = Vector3.Lerp(fromValLeftPos, newLeftPos, counter / duration);
        targetLineRenderer.SetPosition(0, tempLeftPos);

        //Move to Right overtime
        Vector3 tempRightPos = Vector3.Lerp(fromValRightPos, newRightPos, counter / duration);
        targetLineRenderer.SetPosition(1, tempRightPos);

        yield return null;
    }
    isRunning = false;
}

USAGE:

LineRenderer diagLine;

public Vector3 startPoint = new Vector3(0, 0, 0);
public Vector3 endPoint = new Vector3(1.0f, 1.0f, 0);

// Use this for initialization
void Start()
{
    diagLine = gameObject.AddComponent<LineRenderer>();
    diagLine.material = new Material(Shader.Find("Sprites/Default"));
    diagLine.startColor = diagLine.endColor = Color.green;
    diagLine.startWidth = diagLine.endWidth = 0.15f;

    diagLine.SetPosition(0, startPoint);
    diagLine.SetPosition(1, endPoint);

    //Extend Line Over time
    StartCoroutine(extentLineOverTime(diagLine, 4, 3));
}

The StartCoroutine(extentLineOverTime(diagLine, 4, 3)); will extend the line 4 units away from both sides within 3 seconds.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • I just tried your example, and it extended the line at both sides perfectly. Just that when I changed the values to `startPoint = new Vector3 (-1.0f, -1.0f, 0);` and `endPoint = new Vector3 (1.0f, 1.0f, 0);` and `StartCoroutine(extentLineOverTime(diagLine, 2, 3));` the line reduced in length. Also what about if I'm only interested in extending the width of the line regardless of its height as in the lower image in my question. – Hilarious404 Nov 07 '17 at 04:59
  • Okay, I get it. Your solution plus Everts calculation of the line gives me what I need. Thanks. One more thing. How would I grow/extend a box2dcollider to match the line renderer as it increases in length? – Hilarious404 Nov 07 '17 at 17:38
  • 1
    Either you can access the size of the collider or remove the collider (destroy) and then add a new one. It will automatically get the collider to match the new size. – Everts Nov 08 '17 at 06:57
  • @Hilarious404 Sorry for the late reply. I didn't have to to recreate the issue. I did today and found few issues. The answer is now updated to fix them. I suggest you ask new question about BoxCollider. – Programmer Nov 09 '17 at 06:14
  • Sorry for the late reply. I didn't have time to recreate the issue. I did today and found few issues. The answer is now updated with a fix them. Check out the new code. I suggest you create new question about your BoxCollider question. – Programmer Nov 09 '17 at 06:28