не удалось позвонить в класс - PullRequest
0 голосов
/ 14 марта 2020

Дизайн игры: когда животное попадает в хитбокс, игра заканчивается. Когда игрок нажимает на животное, игрок набирает очки.

У меня есть 3 сценария: GameManager, PlayerDataClass, ScoreManager.

PlayerDataClass не привязан ни к какому объекту. код выглядит следующим образом:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class PlayerDataClass
{
    public string Name
    {
        get
        {
            return Name;
        }
        set
        {
            Name = value;
        }
    }

    public int Score
    {
        get
        {
            return Score;
        }
        set
        {
            Score = value;
        }
    }

    public DateTime DateOfPlaying
    {
        get
        {
            return DateOfPlaying;
        }
        set
        {
            DateOfPlaying = value;
        }
    }

    // constructor
    public PlayerDataClass(string playerName, int playerScore)
    {
        Name = playerName;
        Score = playerScore;
        DateOfPlaying = DateTime.Today; // set the date to be current date
    }
}

Я прикрепил ScoreManager (скрипт) к ScoreManager (GameObject). Цель этого кода - показать счет игрока. Код выглядит так:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class ScoreManager : MonoBehaviour
{
    // create a reference based on PlayerDataClass
    public List<PlayerDataClass> testPlayer;

    void Start()
    {
      //cannot call showscore and setscore or not game will crush
    }

    void Init()
    {
        if (testPlayer != null)
        {
            return;
        }

        // create the list of playerdataclass
        testPlayer = new List<PlayerDataClass>();
        testPlayer.Add(new PlayerDataClass("Harvey", 50)); //testing purpose
    }

    // used to show all the player score in the list
    public void ShowScore()
    {
        Init();

        // only call if the list is not equal to null
        if(testPlayer != null)
        {
            // loop through the list
            for (int i = 0; i <= testPlayer.Count; i++)
            {
                print(testPlayer[i].Name);
                print(testPlayer[i].Score);
                print(testPlayer[i].DateOfPlaying.ToString("dd/MM/yyyy"));
            }
        }
        else
        {
            print("the list is empty");
        }
    }

    // used to new player into the list
    public void SetScore(string playName, int playScore)
    {
        Init();

        // add new player with new score into the list
        testPlayer.Add(new PlayerDataClass(playName, playScore));
    }

    void Update()
    {
        //cannot call showscore and setscore or not game will crush
    }
}

GameManager (Script) присоединен к GameManager (объект). В GameManager (Script) есть boolen gameOver, который будет отображать меню «игра поверх» для пользователя после его окончания. В этом меню я покажу результаты 5 лучших игроков.

В GameManager (Script) нет Update ().

GameManager (Script) выглядит следующим образом.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class GameManager : MonoBehaviour
{
    public static GameManager instance;

    [HideInInspector]
    public List<GameObject> animalList = new List<GameObject>();

    // create player score list array to display
    // public List<PlayerDataClass> playerScoreList = new List<PlayerDataClass>();

    private int playerScore;

    // use to pause the game
    private bool gamePause = false;

    private bool gameOver = false;

    public TextMeshProUGUI scoreText;

    public AnimalSpawnner spawner;

    public GameObject gameOverPanel;

    public Button restartButton;

    // use to show individual score inside the score panel
    public TextMeshProUGUI showScoreText;

    // show score panel for individual
    public GameObject scorePanel;

    // public PlayerDataClass testPlayerPlayerData;

    // public ScoreManager testPlayer;

    // public GameObject scoreManager;

    public int PlayerScore
    {
        get
        {
            return playerScore;
        }

        set
        {
            playerScore = value;
            scoreText.SetText("Score: " + playerScore);
        }
    }

    public bool GameOver
    {
        get
        {
            return gameOver;
        }
        set
        {
            gameOver = value;

            if (gameOver)
            {
                gameOverPanel.SetActive(true);

                spawner.enabled = false;
                // playerScoreList.Add(new PlayerDataClass("James", 123));

                /*
                for(int i = 0; i < playerScoreList.Count; i++)
                {
                    print("my name is " + playerScoreList[i].Name);
                    print("my age is " + playerScoreList[i].Score);
                }
                */

                for (int i = 0; i < animalList.Count; i++)
                {
                    Destroy(animalList[i]);
                }
            }
            else
            {
                gameOverPanel.SetActive(false);
                spawner.enabled = true;
                // Destroy(testPlayer); 
                //destroy score manager
            }
        }
    }

    public bool GamePause
    {
        get
        {
            return gamePause;
        }
        set
        {
            gamePause = value;

            // only pause game when it is not gameOver
            if(gameOver == false)
            {
                if (gamePause)
                {
                    spawner.enabled = false;

                    // if the game is pause, set spawned gameobject to be deactivate
                    for (int i = 0; i < animalList.Count; i++)
                    {
                        animalList[i].SetActive(false);
                    }
                }
                else
                {
                    scorePanel.SetActive(false);

                    for (int i = 0; i < animalList.Count; i++)
                    {
                        animalList[i].SetActive(true);
                    }

                    spawner.enabled = true;
                }
            }
        }
    }

    void Awake()
    {
        if (instance != null)
        {
            return;
        }

        instance = this;
        scoreText.SetText("Score: " + playerScore);
        restartButton.onClick.AddListener(OnClickRestart);
    }

    private void OnClickRestart()
    {
        GameOver = false;
    }
}

У животного есть функция OnTriggerEnter2D, которая запускает логическую игру, когда животное попадает в хитбокс. В этой части я попытался вызвать функцию ShowScore () из ScoreManager, игра была разбита.

Я не смог показать счет игрока, когда выскочило меню. Я хотел бы спросить, как я должен реализовать свою функцию ScoreManager, чтобы я мог показать счет игрока, когда всплывет меню? Спасибо.

1 Ответ

0 голосов
/ 17 марта 2020

Проблема заключается в вашей недвижимости в PlayerDataClass !!

. Внимательно посмотрите, что здесь происходит:

public string Name
{
    get
    {
        return Name;
    }
    set
    {
        Name = value;
    }
}

public int Score
{
    get
    {
        return Score;
    }
    set
    {
        Score = value;
    }
}

public DateTime DateOfPlaying
{
    get
    {
        return DateOfPlaying;
    }
    set
    {
        DateOfPlaying = value;
    }
}

Каждый раз, когда вы читаете свойства значение его геттера называется; каждый раз, когда вы присваиваете ему значение, вызывается его установщик. Даже в этом случае, если это чтение или присвоение происходит внутри этих методов получения или установки.

Допустим, например, что вы хотите, например, присвоить значение Name.

Итак, что происходит, это

set
{
    Name = value;
}

, где вы снова присваиваете значение свойству Name, чтобы оно вызывало установщик этого свойства снова и снова в рекурсивном бесконечном l oop! По сути, то, что вы здесь сделали, равно вызову метода, подобному

public void SetName(string value)
{
    SetName(value);
}

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

get
{
    return Name;
}

равно методу, подобному

public string GetName()
{
    return GetName();
}

Приложение рушится, потому что вы делаете это уже в конструкторе PlayerDataClass, поэтому не имеет значения, в каком методе ... как только вы вызываете new PlayerDataClass(x, y), конструктор вызывает бесконечное l oop!


В вашем случае вам фактически не нужны никакие свойства, вы можете просто сделать это простыми полями:

public class PlayerDataClass
{
    public string Name;
    public int Score;
    public DateTime DateOfPlaying;

    // constructor
    public PlayerDataClass(string playerName, int playerScore)
    {
        Name = playerName;
        Score = playerScore;
        DateOfPlaying = DateTime.Today; // set the date to be current date
    }
}

Использование свойств на самом деле имеет смысл, только если вы a) хотите реализовать некоторые особые действия, такие как проверка значения в получателе и / или установщике, или б) хотят ограничить доступ, например, разрешить только чтение publi c Propert ie, но присвоить значение только private. Во всех остальных случаях вы должны просто использовать поля.


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

public class PlayerDataClass
{
    // this one can be assigned from any class also afterwards
    public string Name {get; set; }  

    // This one can be assigned afterwards but only from this class
    // e.g. via a method, it is read-only for any other class
    public int Score {get; private set; }

    // This one can only be assigned in the constructor of this class
    // and not be changed by anyone afterwards
    // it is read-only for any other class and this one except for the constructor
    public DateTime DateOfPlaying {get; }

    // constructor
    public PlayerDataClass(string playerName, int playerScore)
    {
        Name = playerName;
        Score = playerScore;
        DateOfPlaying = DateTime.Today; // set the date to be current date
    }
}

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

public class PlayerDataClass
{
    private string name;     
    private int score;
    private DateTime dateOfPlaying;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int Score
    {
        get { return score; }
        private set { score = value; }
    }

    public DateTime DateOfPlaying
    {
        get { return dateOfPlaying; }
    }

    // constructor
    public PlayerDataClass(string playerName, int playerScore)
    {
        name = playerName;
        score = playerScore;
        dateOfPlaying = DateTime.Today; // set the date to be current date
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...