Support Forum

How can I make a visible path from the start point to the end point in real time, before the movement starts?

Hello everyone.
5
I started developing the combat system. The picture shows what I’m looking for. Please tell me what algorithms and functions I need to use for this.

I want to make:

  1. Visible path in real time.
  2. Calculate the distance in nods or units that Unity uses.Limit the path to this distance.
  3. Create a new obstacle where the player characters are and remove the obstacle in the place where they left. The PC must ignore the obstacle in which he is standing.

For drawing the line, set points of the vectorPath on a lineRenderer

1 Like

lineRenderer works very poorly in perspective (isometry). Is there another way? Through a projector or something else?

LineRenderer’s performance could be improved by a good Material, you could check some Laser example which use LineRenderer

I have no performance issues. I had to artificially lower it to 60 fps so that the video card did not overheat. I don’t know how to draw and that’s why I have all the terrain modeled, then maybe at the very end I’ll make a texture instead of a model. The LineRenderer goes through the terrain. I found the points with a script from the documentation. Some more bevels appear. I understand it works fine in 2D only.

I was able to make the path visible. But it works very slowly. Here is a thread on the Unity forum.
https://forum.unity.com/threads/how-can-i-display-points-in-the-scene-or-draw-a-line-between-them.1261976/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.EventSystems;
 
namespace Pathfinding
{
   
    public class AidWar : VersionedMonoBehaviour
    {
        AILerp ai2;
        LineRenderer lin;
 
        GameObject obect;
        public GameObject obecty;
        public Transform pytKon;
        bool warlin = false;
        bool warVkl = false;
 
        GameObject obect2;
        List<Vector3> buffer = new List<Vector3>();
        Vector3 tchk = new Vector3();
        bool mysh = false;
        void OnEnable()
        {
            ai2 = GetComponent<AILerp>();
            ai2.enableRotation = false;
            ai2.canMove = false;
            ai2.canSearch = true;
            lin = GetComponent<LineRenderer>();
            warVkl = true;
            GetComponent<aid>().enabled=false;
        }
 
        void OnDisable()
        {
            warVkl = false;
            buffer.Clear();
            lin.enabled = false;
            Destroy(obect);
            Destroy(obect2);
            ai2.canSearch = false;
            ai2.SetPath(null);
            ai2.canMove = true;
            GetComponent<aid>().enabled = true;
        }
 
 
        void Update()
        {
 
            var dir = ai2.velocity;
            dir.y = 0;
            if (dir != Vector3.zero) ai2.rotation = Quaternion.LookRotation(dir);
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
           
            if (Physics.Raycast(ray, out hit, 1000) && hit.collider.gameObject.tag == "zemlya")
            {
 
                if (warVkl == true)
                {
                    lin.enabled = true;
                    ai2.destination = hit.point;
                    buffer = new List<Vector3>();
                    ai2.GetRemainingPath(buffer, out bool stale);
                    lin.positionCount = buffer.Count;
                    lin.SetPositions(buffer.ToArray());
                    tchk = new Vector3(buffer.Last().x, 10, buffer.Last().z);
                    if (warlin == false)
                    {
                        obect = Instantiate(obecty, tchk, Quaternion.Euler(90, 0, 0));
                        Destroy(obect2);
                        warlin = true;
                    }
                    else
                    {
                        obect2 = Instantiate(obecty, tchk, Quaternion.Euler(90, 0, 0));
                        Destroy(obect);
                        warlin = false;
                    }
 
                }
            }
 
            if (!EventSystem.current.IsPointerOverGameObject() && Input.GetMouseButtonDown(0))
            {
                if (mysh == false)
                {
                    mysh = true;
                    warVkl = false;
                    lin.enabled = false;
                    Destroy(obect);
                    Destroy(obect2);
                    obect2 = Instantiate(pytKon.gameObject, tchk, Quaternion.Euler(90, 0, 0));
                    ai2.canMove = true;
                                     
                }
            }
 
            if (ai2.reachedDestination)
            {
                ai2.SetPath(null);
                ai2.canMove = false;
                Destroy(obect2);
                warVkl = true;
                mysh = false;
            }
        }
 
             
    }
}

That’s what I did.

Can anything be done to make it work better?

You can try calling ai2.SearchPath(), it will search for the path immediately which should make it much more responsive.

1 Like

Yes, I did. The path also learned to count. But in the paid version of the library there are functions with which it would be better. Now I’m working on the step strip. Here is the script I am working on.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Pathfinding
{
    
    public class AidWar : VersionedMonoBehaviour
    {
        AILerp ai2;
        Seeker Seeek;
        LineRenderer lin;

        GameObject obect;
        public GameObject obecty;
        public Transform pytKon;
        bool warlin = false;
        bool warVkl = false;

        GameObject obect2;
        List<Vector3> buffer = new List<Vector3>();
        Vector3 tchk = new Vector3();
        bool mysh = false;
        bool mysh2 = false;
        Vector3 hithit = new Vector3();
        Path pp;
        GridGraph grid;
        GridGraph segment;
        List<GraphNode> spgrid = new List<GraphNode>();
        GraphNode posPer;

        public Image poloskaVerh2;
        public Image poloskaVerh1;
        Transform prom;
        float dist;
        float distNach;
        float poloska;
        float poloska2;
        float polS;
        float koef;
        void OnEnable()
        {
            Seeek = GetComponent<Seeker>();
            ai2 = GetComponent<AILerp>();
            ai2.enableRotation = false;
            ai2.canMove = false;
            ai2.canSearch = true;
            lin = GetComponent<LineRenderer>();
            warVkl = true;
            GetComponent<aid>().enabled=false;
            int tt = GetComponent<Outfit>().Personag.speed;
            if (tt==30)
            {
                dist = 11;
                distNach = 11;
                koef = 21.4f;
            } 
            else if (tt==40)
            {
                dist = 14;
                distNach = 14;
                koef = 16f;
            }
            print(dist);
             poloska = 214;
             poloska2 = 214;
            poloskaVerh2.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,
                             214);
            poloskaVerh2.rectTransform.ForceUpdateRectTransforms();

            //grid = AstarPath.active.data.gridGraph;
            //spgrid = PathUtilities.BFS(posPer, 10);
            //List<Vector3> v3position = new List<Vector3>(spgrid.Count);
            //for (int i=0; i< spgrid.Count; i++)
            //{
            //    v3position.Add ((Vector3)spgrid[i].position);
            //    Instantiate(pytKon, new Vector3(v3position[i].x,10,v3position[i].z), Quaternion.Euler(90, 0, 0));
            //}


        }

        void OnDisable()
        {
            warVkl = false;
            buffer.Clear();
            lin.enabled = false;
            Destroy(obect);
            Destroy(obect2);
            ai2.canSearch = false;
            ai2.SetPath(null);
            ai2.canMove = true;
            GetComponent<aid>().enabled = true;
        }
               
        void Update()
        {
            
            var dir = ai2.velocity;
            dir.y = 0;
            if (dir != Vector3.zero) ai2.rotation = Quaternion.LookRotation(dir);

                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;

           
            if (prom != null)
            {
                GameObject promOb = prom.GetChild(1).gameObject;
                promOb.SetActive(false);
                prom = null;
            }

            if (!EventSystem.current.IsPointerOverGameObject() && Physics.Raycast(ray, out hit, 1000))
            {
                var gytok = hit.transform;
                if (gytok.CompareTag("Unit"))
                {
                    GameObject promOb = gytok.GetChild(1).gameObject;
                    if (promOb != null)
                    {
                        promOb.SetActive(true);
                    }
                    prom = gytok;
                }
            }

            if (Physics.Raycast(ray, out hit, 1000) && hit.collider.gameObject.tag == "zemlya")
            {
                if (warVkl == true)
                {
                    hithit = hit.point;
                    
                    GraphNode nodeS2 = AstarPath.active.GetNearest(hit.point).node;

                    if (nodeS2.Walkable == true)
                    {
                        ai2.destination = hithit;
                        ai2.SearchPath();


                    }

                    buffer = new List<Vector3>();
                    if (ai2.remainingDistance>=1 && ai2.remainingDistance < dist )
                    {
                       // print(ai2.remainingDistance);
                        lin.enabled = true;
                        if (ai2.remainingDistance <= dist - 1)
                        {
                            poloskaVerh2.GetComponent<Image>().color = new Color(0.5333334f, 0.8862745f, 0.1882353f,1);
                            polS = poloska - (ai2.remainingDistance - 0.5f) * koef;
                            poloskaVerh2.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,
                             polS);
                            poloskaVerh2.rectTransform.ForceUpdateRectTransforms();
                        }
                        else if (ai2.remainingDistance < dist) 
                        {
                            polS = poloska - (ai2.remainingDistance - 0.5f) * koef;
                            poloskaVerh2.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,
                             polS);
                            poloskaVerh2.rectTransform.ForceUpdateRectTransforms();
                            poloskaVerh2.GetComponent<Image>().color =
                            Color.Lerp(Color.green, Color.white, Mathf.PingPong(Time.unscaledTime*5, 1));

                        }
                        ai2.GetRemainingPath(buffer, out bool stale);
                        lin.positionCount = buffer.Count;
                        lin.SetPositions(buffer.ToArray());
                        tchk = new Vector3(buffer.Last().x, 10, buffer.Last().z);
                        if (warlin == false)
                        {
                            obect = Instantiate(obecty, tchk, Quaternion.Euler(90, 0, 0));
                            Destroy(obect2);
                            warlin = true;
                        }
                        else
                        {
                            obect2 = Instantiate(obecty, tchk, Quaternion.Euler(90, 0, 0));
                            Destroy(obect);
                            warlin = false;
                        }
                        mysh2 = false;
                    }
                     else
                    {
                        buffer.Clear();
                        lin.enabled = false;
                        Destroy(obect);
                        Destroy(obect2);
                        mysh2 = true;
                    }
                }
            }
            else if (hit.collider.gameObject == ai2.gameObject && mysh == false)
            {
                lin.enabled = false;
                ai2.SetPath(null);
                Destroy(obect);
                Destroy(obect2);
                poloskaVerh2.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,
                       poloska);
                poloskaVerh2.rectTransform.ForceUpdateRectTransforms();

            }
            if (!EventSystem.current.IsPointerOverGameObject() && Input.GetMouseButtonDown(0))
                {
                    if (mysh == false &&mysh2==false)
                    {
                    WarRegim.hd_nt = true;
                    mysh = true;
                    
                 //  poloskaVerh1.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,
                 //poloska - (ai2.remainingDistance+1) * 21.4f);
                 //  poloskaVerh1.rectTransform.ForceUpdateRectTransforms();
                 dist =dist-ai2.remainingDistance; //(ai2.remainingDistance-0.5f) * 21.4f                   
                    if (dist >= 1) poloska = polS;
                    else  poloska=0;
                    poloskaVerh2.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,
                             poloska);
                    poloskaVerh2.rectTransform.ForceUpdateRectTransforms();
                    print(dist);
                    float vremya = dist/ai2.speed ;
                    warVkl = false;
                    lin.enabled = false;
                    Destroy(obect);
                    Destroy(obect2);
                    obect2 = Instantiate(pytKon.gameObject, tchk, Quaternion.Euler(90, 0, 0));                  
                    ai2.canMove = true;
                   // print(vremya);                        

                    }
                }
            if (ai2.reachedDestination)
                {
                    ai2.SetPath(null);
                    ai2.canMove = false;
                    Destroy(obect2);
                    warVkl = true;
                    mysh = false;
                WarRegim.hd_nt = false;
                }
         }

    }
}

Here’s what came out.

By blinking, I masked what I did not succeed.
Now I’m trying to make the second green bar decrease as the character travels the path.
It probably must be done through the coroutine? I would be grateful if I could tell the formulas and functions through which this can be done. The length of the green strip, the length of the path and the speed of the character are known.