Dye in grey unable button action

Hello,
I’m trying to turn grey actionButton when action point number if under the necessary points.
So I’ve had an image in the prefab button called Unable:

Then I’ve open ActionButtonUI script.
I’ve had a serializedfield GameObject called unableGameObjectImage

[SerializeField] private GameObject unableGameObjectImage;

I’ve saved and add the gameobject containing grey with a little of alpha squared image in the right field:

then in the ActionButtonUi script I’ve created a new method to manage if button is grey or not:

    public void UpdateUnableActionButton()
    {
        unableGameObjectImage.SetActive(true);
    }

I’ve then created a Start method to avoid grey button :slight_smile:

    private void Start()
    {
        unableGameObjectImage.SetActive(false);
    }

And after I’ve tried many option to update setActive false according to the unit’s bool CanSpendActionPointsToTakeAction but withour any success…
If i created an Update method like that:

test if the unit.CanSpendActionPointsToTakeAction is false then display (SetActive(true)) the unableGameObjectImage but it looks that it isn’t the right way to reach the boolean.
It wants dome baseAction between () and when I put on it baseAction, nothing happens…

    private void Update()
    {
        if (unit.CanSpendActionPointsToTakeAction(baseAction))
        {
            unableGameObjectImage.SetActive(true);
        }
    }

I’ven’t error but nothing happens when unit action point fall to zero…
I think I’m not far from the solution but I don’t see what can be wrong…
I precise I’ve created an Unit unit private variable in my Action Button UI script.
Here is the complet one.
Any idea?


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//Pour pouvoir utiliser la fonction Button
using TMPro;

public class ActionButtonUI : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI textMeshPro;
    [SerializeField] private Button button;
    [SerializeField] private GameObject selectedGameObject;
    [SerializeField] private GameObject unableGameObjectImage;

    private BaseAction baseAction;
    private Unit unit;

    private void Start()
    {
        unableGameObjectImage.SetActive(false);
    }

    private void Update()
    {
        if (unit.CanSpendActionPointsToTakeAction(baseAction))
        {
            unableGameObjectImage.SetActive(true);
        }
    }
    public void setBaseAction(BaseAction baseAction)//Methode qui définira les actions possibles par unité, basé sur le script BaseAction qui listera les actions possible en fonction des unités.
    {
        //On déclare que pour l'unité sélectionnée, l'action sélectionnée est celle sélectionnée. 
        this.baseAction = baseAction;
        textMeshPro.text = baseAction.GetActionName().ToUpper();//Le texte affiché dans le bouton sera celui de l'action en question.
        button.image.sprite = baseAction.GetActionIcon();
        UpdateUnableActionButton();
        //Création de la logique lors du clic sur un des boutons
        button.onClick.AddListener(() =>
            {
                //On déclenche l'action en fonction du bouton cliqué.
                UnitActionSystem.Instance.SetSelectedAction(baseAction);
            });
    }

    //Méthode pour mettre à jour le visuel du bouton sélectionné et ceux non sélectionnés
    public void UpdateSelectedVisual()
    {
            //L'action basique sélectionnée est celle sélectionnée par le joueur
            BaseAction selectedBaseAction = UnitActionSystem.Instance.GetSelectedAction();
            selectedGameObject.SetActive(selectedBaseAction == baseAction);
    }

    public void UpdateUnableActionButton()
    {
        unableGameObjectImage.SetActive(true);
    }

}

Thanks.
François

This checks if you can spend the points and activates the unable object if you can. It should probably be

        if (!unit.CanSpendActionPointsToTakeAction(baseAction))
        {
            unableGameObjectImage.SetActive(true);
        }

Hello Bixarrio,
It don’t change anything.
I’ve an error message :slight_smile:
NullReferenceException: Object reference not set to an instance of an object
ActionButtonUI.Update () (at Assets/Scripts/UI/ActionButtonUI.cs:24)

The 24th line is:

    if (!unit.CanSpendActionPointsToTakeAction(baseAction))

That’s because unit doesn’t seem to be set to anything. You need to set unit to something.

The problem is that the buttons are not associated with a unit, which mean you would have to pass the unit to the button. This gets done from the UnitActionSystemUI which gets the selected unit when creating the buttons, so we just need to get that unit to the buttons.

The simplest would be this:

    // Update the SetBaseAction in ActionButtonUI
    public void setBaseAction(BaseAction baseAction, Unit unit)//Methode qui définira les actions possibles par unité, basé sur le script BaseAction qui listera les actions possible en fonction des unités.
    {
        //On déclare que pour l'unité sélectionnée, l'action sélectionnée est celle sélectionnée. 
        this.baseAction = baseAction;
        textMeshPro.text = baseAction.GetActionName().ToUpper();//Le texte affiché dans le bouton sera celui de l'action en question.
        button.image.sprite = baseAction.GetActionIcon();
        UpdateUnableActionButton();
        //Création de la logique lors du clic sur un des boutons
        button.onClick.AddListener(() =>
            {
                //On déclenche l'action en fonction du bouton cliqué.
                UnitActionSystem.Instance.SetSelectedAction(baseAction);
            });
        this.unit = unit; // set the unit
    }

Now, we need to send the unit here when we create the button, so in UnitActionSystemUI

    private void CreateUnitActionButtons()
    {
        foreach (Transform buttonTransform in actionButtonContainerTransform)
        {
            Destroy(buttonTransform.gameObject);
        }

        actionButtonUIList.Clear();

        Unit selectedUnit = UnitActionSystem.Instance.GetSelectedUnit();

        foreach (BaseAction baseAction in selectedUnit.GetBaseActionArray())
        {
            Transform actionButtonTransform = Instantiate(actionButtonPrefab, actionButtonContainerTransform);
            ActionButtonUI actionButtonUI = actionButtonTransform.GetComponent<ActionButtonUI>();
            actionButtonUI.SetBaseAction(baseAction, selectedUnit); // Pass selectedUnit here

            actionButtonUIList.Add(actionButtonUI);
        }
    }

That should work

Re Bixarrio.
Maybe I’m noot enought advance in the course because when I add this.unit = unit in the set base action, it says me that assignation (unit) is already assigned to the same variable.

And if I add selectedUnit in the UnitActionSystemUI 's CreateUnitActionButtons, it says me that no overload (selectedUnit) is allowed in arguments 2 …
Do you want my actual project at this time?

You have to add unit to the method signature, too. I think you may have missed it

    // Update the SetBaseAction in ActionButtonUI
    public void setBaseAction(BaseAction baseAction, Unit unit) // <--- HERE
    {
        this.baseAction = baseAction;
        textMeshPro.text = baseAction.GetActionName().ToUpper();
        button.image.sprite = baseAction.GetActionIcon();
        UpdateUnableActionButton();
        button.onClick.AddListener(() => UnitActionSystem.Instance.SetSelectedAction(baseAction));
        this.unit = unit; // set the unit
    }

whhaaaouuu… :slight_smile:
It works perfectly as i wanted :heartpulse:

I’ve made one move action, so it let me only 1 action point and the spin action turn grey :slight_smile:

And if I select the second unit and directly made a spin action costing 2 points, all the button turn grey :slight_smile:

So happy :slight_smile:
Thanks a lot Bixarrio !
I’ve know learnt that if I want to reach unit method I must add it in the other method…
It what I has forgotten :slight_smile:

Thanks again.

François

Edit:
I’ve implemented a little bit the code.
When the action is unable and grey, the green square desappear and re appear at the next player turn :wink:
So in the UpdateSelectedVisual i’ve had condition:

    public void UpdateSelectedVisual()
    {
        //L'action basique sélectionnée est celle sélectionnée par le joueur
        if (unit.CanSpendActionPointsToTakeAction(baseAction))
        {
            BaseAction selectedBaseAction = UnitActionSystem.Instance.GetSelectedAction();
            selectedGameObject.SetActive(selectedBaseAction == baseAction);
        }
        else
        {
            BaseAction selectedBaseAction = UnitActionSystem.Instance.GetSelectedAction();
            selectedGameObject.SetActive(!selectedBaseAction == baseAction);
        }
    }

and update also the … update method :wink:

    private void Update()
    {
        if (!unit.CanSpendActionPointsToTakeAction(baseAction))
        {
            unableGameObjectImage.SetActive(true);
            UpdateSelectedVisual();
        }
        else
        {
            unableGameObjectImage.SetActive(false);
            UpdateSelectedVisual();
        }
    }

Now the green square desappear when the player can’t do the action, and reappear the next turn :slight_smile:

At the end of the turn 1 after the spin, no more action point, and no more green square:

and after the enemy turn (2), at the begining of the turn 3, Green square re appear and highlighted available actions appear too :slight_smile:

Thank you so much Bixarrio :slight_smile:

3 Likes

Well done, all around! This looks great!

Privacy & Terms