Unity Tower Defence: isPlacable bug

I’m having a bug in which every single waypoint block cannot be clicked except the second to last waypoint block. I’ve tested it by changing the endWaypoint and its always the second to last waypoint that can be clicked on.
image

Thanks in advance.

Hi Umayr,

Select the waypoint which does not work in your Hierarchy and compare it with one that’s working. Maybe a collider is missing.

Hi Nina,
Thank you for replying so quickly.
I’ve tested it with multiple different waypoint combinations i.e.( i changed the end waypoint) and it’s always been the second to last block.
here’s the code:
image

image

image

dont worry about setNotPlacable, I was seeing if maybe I set it previous.isPlacable = false is update it might fix it, but it obviosly didn’t.

Please note, it’s better to copy/paste your code and apply the code fencing characters, rather than using screenshots. Screenshots are ideal for displaying specific details from within a game engine editor or even error messages, but for code, they tend to be less readable, especially on mobile devices which can require extensive zooming and scrolling.

You also prevent those that may offer to help you the ability to copy/paste part of your code back to you with suggestions and/or corrections, meaning that they would need to type a potentially lengthy response. You will often find that people are more likely to respond to your questions if you make it as easy as possible for them to do so.

Did you check the Inspector of the waypoint before the last one?

Hope this helps :slight_smile:


See also;

I have checked the inspector and it says isPlacable is set to true, which is weird because I set previous.isPlacable to false. So something must have gone wrong in previous. For now I could set the second to last block to false manually, but I’m not going to be happy to do it manually like that.

I didn’t mean to make it hard on you in any way, but merrily put the screenshots there because I thought the code would look so ugly and unreadable when I put it in code format(I was wrong as you can see below). So I just snipped it and put it in. I didn’t think about you not being able to copy/paste, but I will definitely keep this in mind.
I put all scripts I thought might be relevent.

Here’s the code from waypoint.cs:

public bool isExplored = false;
    public Waypoint exploredFrom;
    Vector2Int gridPos;
    public bool isPlacable;

    private void Awake()
    {
        isPlacable = true;
    }
    const int gridSize = 10;
    
    public int GetGridSize()
    {
        return gridSize;
    }
    
    public Vector2Int GetGridPos()
    {
        return new Vector2Int(
            Mathf.RoundToInt(transform.position.x / gridSize),
            Mathf.RoundToInt(transform.position.z / gridSize)
        );
    }

    void OnMouseOver()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (isPlacable)
            {
            print("Clicked " + gameObject.name);

            }
            else
            {
                print("Can't Place Here!");
            }
        }
    }

PathFinder.cs

[SerializeField] Waypoint StartWaypoint, EndWaypoint;
    int numberOfGetPathsCalled;
    List<Waypoint> path = new List<Waypoint>();
    Waypoint setNotPlacable;

    private void Update()
    {
        setNotPlacable.isPlacable = false;
    }

    public List<Waypoint> GetPath()
    {
        numberOfGetPathsCalled++;
        if (path.Count == 0)
        {
        LoadBlocks();
        BreadthFirstSearch();
        CreatePath();
        }
        return path;
    }
    Dictionary<Vector2Int, Waypoint> grid = new Dictionary<Vector2Int, Waypoint>();
    
    Queue<Waypoint> queue = new Queue<Waypoint>();
    
    bool isRunning = true;
    
    Waypoint searchCenter;
    Waypoint neighbor;
    
    public Waypoint GetNeighbor()
    {
        return neighbor;
    }

    Vector2Int[] directions =
    {
        Vector2Int.up,
        Vector2Int.right,
        Vector2Int.down,
        Vector2Int.left

    };

    private void CreatePath()
    {
        path.Add(EndWaypoint);
        EndWaypoint.isPlacable = false;
        Waypoint previous = EndWaypoint.exploredFrom;
        while(previous != StartWaypoint)
        {
            path.Add(previous);
            previous = previous.exploredFrom;
            previous.isPlacable = false;
            setNotPlacable = previous;
        }
        path.Add(StartWaypoint);
        StartWaypoint.isPlacable = false;
        path.Reverse();
    }

    private void BreadthFirstSearch()
    {
        queue.Enqueue(StartWaypoint);
        while(queue.Count > 0 && isRunning)
        {
            searchCenter = queue.Dequeue();
            searchCenter.isExplored = true;
            // print("Searching from " + searchCenter);
            HaltIfSearchingFromEndPoint();
            ExploreNeighbors();
        } 
    }

    private void HaltIfSearchingFromEndPoint()
    {
        if (searchCenter == EndWaypoint)
        {
            print("Searching from End node... Therefore Stopping");
            isRunning = false;
        }
    }

    private void ExploreNeighbors()
    {
        if (!isRunning) { return; }
        foreach(Vector2Int direction in directions)
        {
            Vector2Int neighborCoordinates = searchCenter.GetGridPos() + direction;
            if (grid.ContainsKey(neighborCoordinates))
            {
                QueueNewNeighbors(neighborCoordinates);
            }
        }
    }

    private void QueueNewNeighbors(Vector2Int neighborCoordinates)
    {
        neighbor = grid[neighborCoordinates];
        if (neighbor.isExplored || queue.Contains(neighbor))
        {
            //Do Nothing
        }
        else {
            queue.Enqueue(neighbor);
            neighbor.exploredFrom = searchCenter;
        }
    }

    private void LoadBlocks()
    {
        var waypoints = FindObjectsOfType<Waypoint>();
        foreach (Waypoint waypoint in waypoints)
        {
            var gridPos = waypoint.GetGridPos();
            bool isOverlapping = grid.ContainsKey(gridPos);

            if (isOverlapping)
            {
                Debug.LogWarning("Skipping block " + waypoint);
            }
            else
            {
                grid.Add(gridPos, waypoint);
            }
        }

    }

EnemyMovement.cs

    void Start()
    {
        PathFinder pathFinder = FindObjectOfType<PathFinder>();
        var path = pathFinder.GetPath();
        StartCoroutine(FollowPath(path));
    }
    IEnumerator FollowPath(List<Waypoint> path)
    {
        print("Starting patrol");
        foreach (Waypoint waypoint in path)
        {
            transform.position = waypoint.transform.position;
            yield return new WaitForSeconds(1f);
        }
        print("Ending patrol");
    }

EditorCube.cs

Waypoint waypoint;
    
    TextMesh textMesh;
    string blockLabel; 
    private void Awake()
    {
        waypoint = GetComponent<Waypoint>();
    }
    void Update()
    {
        int gridSize = waypoint.GetGridSize();
        SnapToGrid(gridSize);
        WriteToTextMesh(gridSize);
    }

    private void SnapToGrid(int gridSize)
    {
        transform.position = new Vector3(waypoint.GetGridPos().x * gridSize, 0f, waypoint.GetGridPos().y * gridSize);
        gameObject.name = blockLabel;
    }

    private void WriteToTextMesh(int gridSize)
    {
        textMesh = GetComponentInChildren<TextMesh>();
        blockLabel = waypoint.GetGridPos().x + "," + waypoint.GetGridPos().y;
        textMesh.text = blockLabel;
    }

Something I just realized is that in the inspector 6,3 is explored from 7,3 when I run the game
image
and previous is:

Waypoint previous = EndWaypoint.exploredFrom;

which doesn’t make sense at ALL!

I fixed this by adding previous.isPlacable = false; outside the while loop. I still think this bug doesn’t make any sense, but maybe someone could explain it(That is if it’s explainable).

    private void CreatePath()
    {
        path.Add(EndWaypoint);
        EndWaypoint.isPlacable = false;

        Waypoint previous = EndWaypoint.exploredFrom;
        previous.isPlacable = false;// where I put it
        while(previous != StartWaypoint)
        {
            path.Add(previous);
            previous = previous.exploredFrom;
            previous.isPlacable = false;
        }
        path.Add(StartWaypoint);
        StartWaypoint.isPlacable = false;
        path.Reverse();
    }

Thank you Nina, for helping me with this crazy bug.

Also I realized that ben is going to fix this in a few lectures.

I’m glad you found a solution in the course. :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms