Как мы можем обрабатывать данные только в базовом классе, не клонируя их в производные классы? - PullRequest
0 голосов
/ 09 июля 2020

Моя игра имеет несколько игровых режимов. Каждый тип игры имеет свой лог c. Но некоторые части общие. Я хочу хранить общие части (общий лог c, игровые данные и c.) В базовом классе для чистого кода и переопределения частей, связанных с игровым режимом, в производном классе. Мои цели и примеры кодов ниже.

  • GameManager - это базовый класс игровых режимов (нормальный, против, обучающий и т.д. c.)
  • Только этот класс имеет игровые данные, и производные классы должны их использовать. (данные игрока, свойства и т.д. c.)
  • Этот класс имеет методы кнопок, общие методы. Эти общие методы должны быть переопределены производными классами.

GameManager.cs

public class GameManager : MonoBehaviour
{
    //Example game data (this data only should store in base class)
    [SerializeField] protected List<Player> players = new List<Player>();
    protected bool someOneWon = false;
    protected int winnerIndex = -1;
    protected int botCount = 4;

    public virtual void StartGame()
    {
        MenuManager.Instance.GamePanelActivateUI();
        InitBots();
    }

    private void InitBots()
    {
        for (int i = 0; i < botCount; i++)
        {
             Player bot = Instantiate(UIManager.Instance.PlayerPrefab).GetComponent<Player>();
             bot.InitPlayer(PlayerType.Bot); //Player data initialize here
             players.Add(bot);
        }
    }

    public void SomeButton()
    {
        //This method attached button

        //Throws null error because its null on GameManager
        Debug.Log("Player.coin" + players[1].coin) 
    }
}
  • Производные классы могут иметь собственные свойства и методы.
  • Они может получить доступ к свойствам и методам родительского класса и переопределить их для собственного игрового журнала c.
  • Производный класс не должен дублировать игровые данные базового класса (данные игрока и т.д. c.). Они должны достичь базового класса.

NormalGame.cs

public class NormalGame: GameManager
{
      //Related Normal Game Properties

      public override void StartGame()
      {
           base.StartGame();
           StartCoroutine(NormalGameCycle());
      }

      IEnumerator NormalGameCycle()
      {
           //normal game logic
      }
}

VersusGame.cs

public class VersusGame: GameManager
{
      //Related Versus Properties & Methods
}

TutorialGame.cs

public class TutorialGame: GameManager
{
      //Related Tutorial Properties & Methods
}

Когда я пытаюсь, как будто данные базового класса архитектуры дублируют весь производный класс, это вызывает ошибки нулевой ссылки при нажатии кнопки или запуске некоторого кода на базовой стороне. Когда я вызываю из производного класса, такого как base.StartGame (), данные будут инициализированы в производном классе, а не в базовом классе. Я хочу, чтобы обработанные данные включались только в базовый класс. Жду ваших предложений, спасибо за внимание.

GameManager properties are null after initializing

На нем инициализируются свойства NormalGame.

Ответы [ 2 ]

0 голосов
/ 09 июля 2020

Ответ скрывается у всех на виду в вашем вопросе: «данные, свойства»!

Подобные вещи решаются с помощью композиции, а не наследования .

Что вам нужно, так это что-то вроде Unity Scriptable Object , который определяется как:

A data контейнер, который вы можете использовать для сохранения больших объемов данные, не зависящие от экземпляров класса .

Это позволит вам настроить различные свойства, которые вы, возможно, захотите изменить между различными режимами игры, сохраняя их в поле.

public class GameManager : MonoBehaviour
{
    public GameOptions gameOptions;
}

[CreateAssetMenu(menuName = "Data/Game Options")]
public class GameOptions : ScriptableObject
{
    public List<string> options;
}
0 голосов
/ 09 июля 2020

Мне было трудно разобраться с вашей проблемой, но я подозреваю, что вы ожидаете, что ваши объекты класса будут вести себя так, как если бы они были c классами, когда вы фактически имеете дело с отдельными экземплярами объектов ваших двух классы.

К сожалению, простое изменение классов на stati c не решит проблему, поскольку классы stati c запечатаны в C# и не могут быть унаследованы, поэтому вам может потребоваться пересмотреть свой подход к этой проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...