GridVisualSingles not showing up

I have followed the course until this lecture, which has not touched pathfinding yet.
Currently i am able to interact and grenade correctly, melee and shoot shows the adjacent hex tiles but cannot execute the move and move action shows nothing

The move won’t work until the Pathfinding is adjusted for multi-floor…

But in this lecture, gridVisual for move option was showing up before pathfinding was adjusted. I guess i will try to carry on first. Thanks

Nobody’s actually mixed the two systems to my knowledge yet, so that’s sort of the assumption that I’m working on…

Let’s take a look at your MoveAction.cs script (Understand, without any scripts at all, I have no idea why it might not be working).

From the adjustments made to facilitate floors i can see that the current fix only looks for valid gps on floor 0, but from the lecture it seems that he is able to get validgrids even though he is on floor 1

public override List<GridPosition> GetValidActionGridPositionList()
    {
        List<GridPosition> gridPositions = new List<GridPosition>();
        GridPosition unitGridPosition = unit.GetGridPosition();

        for (int x = -maxMovementDistance; x <= maxMovementDistance; x++)
        {
            for(int z = -maxMovementDistance; z <= maxMovementDistance; z++)
            {
                GridPosition offsetGP = new GridPosition(x, z, 0);
                GridPosition testGP = unitGridPosition + offsetGP;

                if (!LevelGrid.Instance.isValidGridPosition(testGP))
                {
                    //TestGP is outofbounds
                    continue;
                }

                if (testGP == unitGridPosition)
                {
                    //TestGP is same as starting GP
                    continue;
                }

                if(LevelGrid.Instance.hasAnyUnitOnGrid(testGP))
                {
                    //TestGP already has a unit on it
                    continue;
                }

                if(!Pathfinding.Instance.IsWalkable(testGP))
                {
                    //TestGP is not Walkable
                    continue;
                }

                if(!Pathfinding.Instance.IsReachable(unit.GetGridPosition(), testGP))
                {
                    //TestGP is not reachable from current position
                    continue;
                }

                int pathfindingDistanceMultiplier = 10;
                if(Pathfinding.Instance.GetPathLength(unit.GetGridPosition(), testGP) > maxMovementDistance * pathfindingDistanceMultiplier)
                {
                    //TestGP is too far with current move distance
                    continue;
                }

                gridPositions.Add(testGP);
                //Debug.Log(testGP);              
            }
        }
        //foreach (var gp in gridPositions)
        //    Debug.Log("Position: " + gp.ToString());
        return gridPositions;
    }

Rewatching the video to see what might be going on

For more context, i was able to recreate the results of the end of the previous lecture (i.e able to put units on the next level and return their GridPositions correctly)

Ok, so I was focused on the Mover, but in this lecture all of the changes are in the GridSystemVisual class.

So we need to compare the GridSystemVisual.cs to what we have in the course repo… For reference, here’s the GridSystemVisual from the course repo:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridSystemVisual : MonoBehaviour
{

    public static GridSystemVisual Instance { get; private set; }


    [Serializable]
    public struct GridVisualTypeMaterial
    {
        public GridVisualType gridVisualType;
        public Material material;
    }

    public enum GridVisualType
    {
        White,
        Blue,
        Red,
        RedSoft,
        Yellow,
    }

    [SerializeField] private Transform gridSystemVisualSinglePrefab;
    [SerializeField] private List<GridVisualTypeMaterial> gridVisualTypeMaterialList;


    private GridSystemVisualSingle[,,] gridSystemVisualSingleArray;


    private void Awake()
    {
        if (Instance != null)
        {
            Debug.LogError("There's more than one GridSystemVisual! " + transform + " - " + Instance);
            Destroy(gameObject);
            return;
        }
        Instance = this;
    }

    private void Start()
    {
        gridSystemVisualSingleArray = new GridSystemVisualSingle[
            LevelGrid.Instance.GetWidth(),
            LevelGrid.Instance.GetHeight(),
            LevelGrid.Instance.GetFloorAmount()
        ];

        for (int x = 0; x < LevelGrid.Instance.GetWidth(); x++)
        {
            for (int z = 0; z < LevelGrid.Instance.GetHeight(); z++)
            {
                for (int floor = 0; floor < LevelGrid.Instance.GetFloorAmount(); floor++)
                {
                    GridPosition gridPosition = new GridPosition(x, z, floor);

                    Transform gridSystemVisualSingleTransform =
                        Instantiate(gridSystemVisualSinglePrefab, LevelGrid.Instance.GetWorldPosition(gridPosition), Quaternion.identity);

                    gridSystemVisualSingleArray[x, z, floor] = gridSystemVisualSingleTransform.GetComponent<GridSystemVisualSingle>();
                }
            }
        }

        UnitActionSystem.Instance.OnSelectedActionChanged += UnitActionSystem_OnSelectedActionChanged;
        LevelGrid.Instance.OnAnyUnitMovedGridPosition += LevelGrid_OnAnyUnitMovedGridPosition;

        UpdateGridVisual();
    }

    public void HideAllGridPosition()
    {
        for (int x = 0; x < LevelGrid.Instance.GetWidth(); x++)
        {
            for (int z = 0; z < LevelGrid.Instance.GetHeight(); z++)
            {
                for (int floor = 0; floor < LevelGrid.Instance.GetFloorAmount(); floor++)
                {
                    gridSystemVisualSingleArray[x, z, floor].Hide();
                }
            }
        }
    }

    private void ShowGridPositionRange(GridPosition gridPosition, int range, GridVisualType gridVisualType)
    {
        List<GridPosition> gridPositionList = new List<GridPosition>();

        for (int x = -range; x <= range; x++)
        {
            for (int z = -range; z <= range; z++)
            {
                GridPosition testGridPosition = gridPosition + new GridPosition(x, z, 0);

                if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition))
                {
                    continue;
                }

                int testDistance = Mathf.Abs(x) + Mathf.Abs(z);
                if (testDistance > range)
                {
                    continue;
                }

                gridPositionList.Add(testGridPosition);
            }
        }

        ShowGridPositionList(gridPositionList, gridVisualType);
    }

    private void ShowGridPositionRangeSquare(GridPosition gridPosition, int range, GridVisualType gridVisualType)
    {
        List<GridPosition> gridPositionList = new List<GridPosition>();

        for (int x = -range; x <= range; x++)
        {
            for (int z = -range; z <= range; z++)
            {
                GridPosition testGridPosition = gridPosition + new GridPosition(x, z, 0);

                if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition))
                {
                    continue;
                }

                gridPositionList.Add(testGridPosition);
            }
        }

        ShowGridPositionList(gridPositionList, gridVisualType);
    }

    public void ShowGridPositionList(List<GridPosition> gridPositionList, GridVisualType gridVisualType)
    {
        foreach (GridPosition gridPosition in gridPositionList)
        {
            gridSystemVisualSingleArray[gridPosition.x, gridPosition.z, gridPosition.floor].
                Show(GetGridVisualTypeMaterial(gridVisualType));
        }
    }

    private void UpdateGridVisual()
    {
        HideAllGridPosition();

        Unit selectedUnit = UnitActionSystem.Instance.GetSelectedUnit();
        BaseAction selectedAction = UnitActionSystem.Instance.GetSelectedAction();

        GridVisualType gridVisualType;

        switch (selectedAction)
        {
            default:
            case MoveAction moveAction:
                gridVisualType = GridVisualType.White;
                break;
            case SpinAction spinAction:
                gridVisualType = GridVisualType.Blue;
                break;
            case ShootAction shootAction:
                gridVisualType = GridVisualType.Red;

                ShowGridPositionRange(selectedUnit.GetGridPosition(), shootAction.GetMaxShootDistance(), GridVisualType.RedSoft);
                break;
            case GrenadeAction grenadeAction:
                gridVisualType = GridVisualType.Yellow;
                break;
            case SwordAction swordAction:
                gridVisualType = GridVisualType.Red;

                ShowGridPositionRangeSquare(selectedUnit.GetGridPosition(), swordAction.GetMaxSwordDistance(), GridVisualType.RedSoft);
                break;
            case InteractAction interactAction:
                gridVisualType = GridVisualType.Blue;
                break;
        }

        ShowGridPositionList(
            selectedAction.GetValidActionGridPositionList(), gridVisualType);
    }

    private void UnitActionSystem_OnSelectedActionChanged(object sender, EventArgs e)
    {
        UpdateGridVisual();
    }

    private void LevelGrid_OnAnyUnitMovedGridPosition(object sender, EventArgs e)
    {
        UpdateGridVisual();
    }

    private Material GetGridVisualTypeMaterial(GridVisualType gridVisualType)
    {
        foreach (GridVisualTypeMaterial gridVisualTypeMaterial in gridVisualTypeMaterialList)
        {
            if (gridVisualTypeMaterial.gridVisualType == gridVisualType)
            {
                return gridVisualTypeMaterial.material;
            }
        }

        Debug.LogError("Could not find GridVisualTypeMaterial for GridVisualType " + gridVisualType);
        return null;
    }

}

I have compared mine against the repo’s version and only have naming convention diferences

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class GridSystemVisual : MonoBehaviour
{
    public static GridSystemVisual Instance { get; private set; }


    [Serializable]
    public struct GridVisualTypeMaterial
    {
        public GridVisualType gridVisualType;
        public Material material;
    }

    public enum GridVisualType
    {
        White,
        Blue,
        Red,
        RedSoft,
        Yellow
    }

    [SerializeField]
    private Transform gridSystemVisualSinglePrefab;

    [SerializeField]
    private List<GridVisualTypeMaterial> gridVisualTypeMaterials;

    private GridSystemVisualSingle[,,] gridSystemVisualArray;

    private void Awake()
    {
        if (Instance != null)
        {
            Debug.LogError("More than 1 instance of GridSystemVisual! " + transform + " - " + Instance);
            Destroy(gameObject);
            return;
        }
        Instance = this;
    }

    private void Start()
    {
        gridSystemVisualArray = new GridSystemVisualSingle[
            LevelGrid.Instance.GetWidth(),
            LevelGrid.Instance.GetHeight(),
            LevelGrid.Instance.GetFloorAmount()];

        for (int x = 0; x < LevelGrid.Instance.GetWidth(); ++x)
        {
            for (int z = 0; z < LevelGrid.Instance.GetHeight(); ++z)
            {
                for (int floor = 0; floor < LevelGrid.Instance.GetFloorAmount(); ++floor)
                {
                    GridPosition gridPosition = new GridPosition(x, z, floor);
                    Transform gridSystemVisualSingleTransform =
                        Instantiate(gridSystemVisualSinglePrefab, LevelGrid.Instance.GetWorldPosition(gridPosition), Quaternion.identity);

                    gridSystemVisualArray[x, z, floor] = gridSystemVisualSingleTransform.GetComponent<GridSystemVisualSingle>();
                }

            }
        }

        UnitActionSystem.Instance.OnSelectedActionChanged += UnitActionSystem_OnSelectedActionChanged;
        LevelGrid.Instance.OnAnyUnitMovedGridPosition += LevelGrid_OnAnyUnitMovedGridPosition;

        UpdateGridVisual();
    }

    public void HideAllGridPositions()
    {
        for (int x = 0; x < LevelGrid.Instance.GetWidth(); ++x)
        {
            for (int z = 0; z < LevelGrid.Instance.GetHeight(); ++z)
            {
                for (int floor = 0; floor < LevelGrid.Instance.GetFloorAmount(); ++floor)
                {
                    gridSystemVisualArray[x, z, floor].Hide();
                }

            }
        }
    }

    private void ShowGridPositionRange(GridPosition gridPosition, int range, GridVisualType gridVisualType)
    {
        List<GridPosition> gridPositions = new List<GridPosition>();
        for (int x = -range; x <= range; ++x)
        {
            for (int z = -range; z <= range; ++z)
            {
                GridPosition testGridPosition = gridPosition + new GridPosition(x, z, 0);

                if (!LevelGrid.Instance.isValidGridPosition(testGridPosition))
                {
                    //TestGP is outofbounds
                    continue;
                }

                int testDistance = Mathf.Abs(x) + Mathf.Abs(z);
                if (testDistance > range)
                {
                    continue;
                }

                gridPositions.Add(testGridPosition);
            }
        }
        ShowGridPositionList(gridPositions, gridVisualType);
    }

    private void ShowGridPositionRangeSquare(GridPosition gridPosition, int range, GridVisualType gridVisualType)
    {
        List<GridPosition> gridPositions = new List<GridPosition>();
        for (int x = -range; x <= range; ++x)
        {
            for (int z = -range; z <= range; ++z)
            {
                GridPosition testGridPosition = gridPosition + new GridPosition(x, z, 0);

                if (!LevelGrid.Instance.isValidGridPosition(testGridPosition))
                {
                    //TestGP is outofbounds
                    continue;
                }

                gridPositions.Add(testGridPosition);
            }
        }
        ShowGridPositionList(gridPositions, gridVisualType);
    }

    public void ShowGridPositionList(List<GridPosition> gridPositions, GridVisualType gridVisualType)
    {
        Debug.Log("gridPositions: " + gridPositions.Count);
        foreach (var gp in gridPositions)
        {
            gridSystemVisualArray[gp.x, gp.z, gp.floor].
                Show(GetGridVisuaTypelMaterial(gridVisualType));
        }
    }

    private void UpdateGridVisual()
    {
        HideAllGridPositions();

        Unit selectedUnit = UnitActionSystem.Instance.GetSelectedUnit();
        BaseAction selectedAction = UnitActionSystem.Instance.GetSelectedAction();

        GridVisualType gridVisualType;
        switch (selectedAction)
        {
            default:
            case MoveAction moveAction:
                gridVisualType = GridVisualType.White;
                break;

            case SpinAction spinAction:
                gridVisualType = GridVisualType.Blue;
                break;

            case ShootAction shootAction:
                gridVisualType = GridVisualType.Red;

                ShowGridPositionRange(selectedUnit.GetGridPosition(), shootAction.GetShootingRange(), GridVisualType.RedSoft);
                break;

            case GrenadeAction grenadeAction:
                gridVisualType = GridVisualType.Yellow;
                break;

            case MeleeAction meleeAction:
                gridVisualType = GridVisualType.Red;

                ShowGridPositionRangeSquare(selectedUnit.GetGridPosition(), meleeAction.GetMeleeRange(), GridVisualType.RedSoft);
                break;

            case InteractAction interactAction:
                gridVisualType = GridVisualType.Blue;
                break;
        }
        ShowGridPositionList(
            selectedAction.GetValidActionGridPositionList(), gridVisualType);
    }

    private void LevelGrid_OnAnyUnitMovedGridPosition(object sender, EventArgs e)
    {
        UpdateGridVisual();
    }

    private void UnitActionSystem_OnSelectedActionChanged(object sender, EventArgs e)
    {
        UpdateGridVisual();
    }

    public Material GetGridVisuaTypelMaterial(GridVisualType gridVisualType)
    {
        foreach (var material in gridVisualTypeMaterials)
        {
            if (material.gridVisualType == gridVisualType)
            {
                return material.material;
            }
        }
        Debug.LogError("GridVisualTypeMaterial could not be found for gridVisualType " + gridVisualType);
        return null;
    }
}

As a double check, are the visuals not showing at all, or are they showing on the 0th floor instead of on the 1st floor? (like at the beginning of the video)

they do not show up on the lower floor, but if the unit originated from floor 0, all functionality and visuals are working

Ok, that makes me wonder if the LevelGrid’s GridSystem didn’t get the memo…

The next thing to look at is the LevelGrid.cs.

Ok let me re-check against repo’s LevelGrid

Do not see any difference aside from formatting issues

Zip up your project and upload it to https://gdev.tv/projectupload and I’ll see if I can figure out what’s going on. Be sure to remove the Library folder to conserve space.

Hi Brian, i have uploaded the file already. I tried to do this on the conventional square grid project and it works. Perhaps it is the underlying pathfinding that is wonky. (I checked the stack trace and no grid was deemed available when on the second floor)

It looks like the Pathfinding is not set up for multi-floors… While the changes have been made to accomodate the GridSystem and the extra parameter in GridPosition, only the 0th floor is actually tested or walklability, and GetNode() only returns XY positions on the 0th floor.

There is a small error to point out in GridSystemHex.GetGridPosition;. Your test positions are all the current GridPosition + the surrounding positions + floor (new GridPosition(-1,-1, floor) instead of new GridPosition(-1,-1,0); When adding one Gridposition to another gridposition, and wanting to stay on the same floor, the floor in the added gp should be 0.

One I fixed this, and temporarily commented out the pathfinding checks in MoveAction’s GetValidGridPositionList, the positions appeared on the 1st floor.


I think once you implement the multi-floor pathfinding that you should be good to go.

Privacy & Terms