Question about updating Visuals to show Range of Grenade Action

First off, thank you CodeMonkey for the course, it has been a ton of fun learning how to make this game, and I have learned a lot. In fact, I wanted to make the logic for the Grenade action myself as a challenge, and was mostly successful in doing so, got it to damage the correct units, calculate the valid positions, have an explosion range, etc.

One thing that I came up against however was how would I show where the grenade would affect in the world, sort of like what we did with the Shoot action and the 2 grid visuals running to show the range and the valid targets.

I did get it to work, but I am unsure about whether what I did to get it to update correctly is good programming.

In the GridVisualSystem Script I added a GrenadeAction, but then quickly realized that it would not update as the mouse changed its position, and that the default order of showing range then valid positions would need to be reversed for the grenade action to get it to show the area of effect over the valid throwing range.

private void UpdateGridVisual()
    {
        HideAllGridPositions();

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

        switch (selectedAction)
        {
            case null:
                return;
            case MoveAction moveAction:
                gridVisualType = GridVisualType.Blue;

                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPositionList(), gridVisualType);
                break;
            case SpinAction spinAction:
                gridVisualType = GridVisualType.Yellow;

                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPositionList(), gridVisualType);
                break;
            case ShootAction shootAction:
                gridVisualType = GridVisualType.Red;

                //Range First to Show Grid, then valid targets
                ShowGridPositionRange(selectedUnit.GetGridPosition(), shootAction.GetWeaponRange(), GridVisualType.RedSoft);
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPositionList(), gridVisualType);
                break;
            case GrenadeAction grenadeAction:
                gridVisualType = GridVisualType.RedSoft;

                //Valid Targets to show Grid, then explosion Radius from Range
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPositionList(), gridVisualType);
                ShowGridPositionRange(LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition()), grenadeAction.GetExplosionRange(), GridVisualType.Red, false);
                break;
        }
    }

Getting the correct order is not a problem, and I am generally okay with this, its less streamlined, but each call is still only happening once, so there is no extra code invocations here to affect performance. However, to get it to update when the mouse moves, I had to get this function to be called as frequently as the mouse moved. To do this, I made use of the Update function, and the fact that we could determine if the Grenade Action was selected and only update it per frame then.

if (UnitActionSystem.Instance.GetSelectedAction() is GrenadeAction)
        {
            if (UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPositionList().Contains(
                LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition())))
            {
                UpdateGridVisual();
            }
        }

While it does work as I would expect, I cant help but feel that there is a better way to get it t update its visual component as the mouse moves, that is either more standard, or at least more effecient. Do you have any thoughts on how you might make this function as I wanted?

Thanks again for all you have taught me during the course.

1 Like

In order to make it more efficient you can fire some event whenever the mouse position changes.
Make a script to keep track of the mouse GridPosition, just like the Unit logic, and fire some event when it changes. Then on that event run that logic.
That way it will run less often than every single update, only when the mouse changes grid position.

And great job on implementing that feature, I’m glad you’re enjoying the course!

1 Like

Thank you. I added code to the Update function in the MouseWorld to check the grid position of the Mouse, and then if the position changes, I fire that event.

GridPosition newMouseGridPosition = LevelGrid.Instance.GetGridPosition(GetPosition());
        if (mouseGridPosition != newMouseGridPosition)
        {
            mouseGridPosition = newMouseGridPosition;
            OnMouseGridPositionChanged?.Invoke(this, EventArgs.Empty);
        }

And then the GridSystemVisual listens for that event, and checks if we are in the Grenade Action, and updates it then.

private void MouseWorld_OnMouseGridPositionChanged(object sender, EventArgs e)
    {
        if (UnitActionSystem.Instance.GetSelectedAction() is GrenadeAction)
        {
            if (UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPositionList().Contains(
                LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition())))
            {
                UpdateGridVisual();
            }
        }
    }

With this, I can add more action that have similar targeting systems, and they will all work by simply adding checks to whether the action is the one used. I may refactor the Base Action to have an AoE boolean, and then for any Action that has an AoE update like this, so that it can be more genericized, but so far so good.
Thanks again!

1 Like

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

Privacy & Terms