Home > Net >  Trying to change BattleState globally
Trying to change BattleState globally

Time:09-28

Hi I'm a completely new to coding and am trying to create a card game. I've watched some tutorials and tried to take things into my own hands but cant seem to figure out something. I currently have a BattleState set up;

public enum BattleState { START, PLAYERMAINPHASE, PLAYERBATTLEPHASE, PLAYERENCORESTEP, ENEMYTURN, WON, LOST }

and would like it so when i change the BattleState with a script, it changes it for every other script that references this BattleState. Sorry for the bad wording. Coding is rough :/

CodePudding user response:

You can use interfaces, create an interface such as IBattleStateChanger and have a method on it

interface ISampleInterface{
    void ChangeBattleState(YourClass.BattleState state);
}

Then on every script you want the value to change implement this interface as

ClassExample : IBattleStateChanger

This will then force you to create a method in the script to change the state

After that, whenever you want to change the value globally on the scripts where you implemented this interface, you can do a foreach loop finding each type of this interface such as

BattleState newState = BattleState.START;
foreach (var interface in FindObjectsOfType<IBattleStateChanger>){
      interface.SetBattleState(newState);
}

CodePudding user response:

I believe you are confused about the scope of your variable. Each script you place an instance of the enum Battlestate, is a local version of that enum. If you want the reference to be global, you will need to have a central point where all scripts can grab this reference.

public class BattleManager : MonoBehaviour
{
     private BattleState battleState;

     // setter / getters
     public BattleState GetBattleState(){return battleState; }
     public void SetBattleState(BattleState state){ battleState = state; } 
}

You are going to want to make a single script that holds the only reference to your enum Battlestate, then have your other scripts reference the variable.

public class OtherScript : MonoBehaviour
{
     // assign this reference in the inspector
     [SerializeField] private BattleManager bm = null;

     private void YourFunction()
     {
          if(bm.GetBattleState() == BattleState.randomStateHere)
          { 
                // run logic here
          }
     }
}

There are a number of ways to go about doing this, but the easiest would most likely be by declaring the variable static.

public class BattleManager : MonoBehaviour
{
     private static BattleState battleState;

     // setter / getters
     public static BattleState GetBattleState(){return battleState; }
     public static void SetBattleState(BattleState state){ battleState = state; } 
}
public class OtherScript : MonoBehaviour
{
     private void YourFunction()
     {
          if(BattleManager.GetBattleState() == BattleState.randomStateHere)
          { 
                // run logic here
          }
     }
}

I do not know how many scripts you need to access this variable, but if it is only a handful, I would instead assign references to the script that holds the enum to each of the scripts that need it. I would avoid simply using static as it is the easy approach but creates what is called a code smell. The reason for this is OOP (object-oriented programming) by design should generally not have mutable global variables.

If you have a single instance of an object that manages all of your battle activity and a lot of scripts need to access it, you can look into the Singleton pattern. As you are new to programming, I would not implement this pattern until you understand the time and place to properly use it. You can also completely avoid using it by properly assigning the references you need in the inspector or by using a Object.FindObjectOfType in either Start or Awake.

CodePudding user response:

public class BattleStateMgr
{
    public enum BattleState
    {
        START, PLAYERMAINPHASE, PLAYERBATTLEPHASE, PLAYERENCORESTEP, ENEMYTURN, WON, LOST
    }

    public static BattleState State;
    public static event System.Action OnStateChange;
    public static ChangeState(BattleState s)
    {
        State = s;
        if(OnStateChange != null) OnStateChange();
    }
}

public class OtherScript : MonoBehaviour
{
    private void Awake()
    {
        BattleStateMgr.OnStateChagne  = OnBattleStateChange;
    }

    private void OnDestroy()
    {
        BattleStateMgr.OnStateChagne -= OnBattleStateChange;
    }

    private void OnBattleStateChange()
    {
        //Here Get State Change.
        Debug.LogFormat("Battle State {0}", BattleStateMgr.State);
    }
}

Using Event To Listen State Change

CodePudding user response:

I think you can learn about the design pattern after you solve this problem which can help you solve many prolems like this.

  • Related