Unity 中的 TurnManager 逻辑同时执行 if 和 else 条件

问题描述 投票:0回答:1

在我的统一项目中,当玩家做出正确的“猜测”时,turnManager 会执行错误的循环。我很难找出问题所在,如果有任何回报,我将不胜感激。 据我所知,这似乎是一个游戏逻辑问题。

从游戏逻辑角度来看,回合管理器旨在检查条件(如果给定玩家拥有给定卡牌)。事实上,在执行循环的 if 部分(正确/真条件)后,它也会自动执行 else 部分(条件为假)。这结束了玩家的回合...而不是为当前玩家(回合的玩家)提供另一次尝试“猜一张牌”。

我怀疑这是turnmanger代码的问题,而不是Unity的设置等问题。我的假设是基于我可以反驳其他问题,即以下问题:

  1. 多次点击 - 那是因为当“猜测”错误时,触发猜测/条件验证的点击按预期工作,当“猜测”错误时按预期执行。

  2. 其他脚本对错误方法的其他调用:由错误/错误的“猜测”验证调用的方法仅由 Turnmanager 调用或出现在 Turnmanager 上。没有其他类或脚本调用这些方法(DrawCardFromDeck 和 EndTurn)。

  3. 错误的方法调用:换句话说,如果调用猜测验证的方法是( OnEventGuessClick ),基于触发事件 m 或直接依赖项调用,问题是相同的。

  4. 在 debug.logs 之后,似乎 Else 片段在 PlayerController 更新后执行,它应该是这样,即代表当前玩家的手牌、四重奏和要猜测的牌。 UI 更新中的某些元素可能会触发另一个 OnEventGuessClick。然而,这只是一个猜测,因为我无法证实它。

我认为主要问题是代码似乎是正确的,但事实并非如此。 IE。我找不到我应该解决哪个问题。

任何帮助将不胜感激。

以下是脚本。我只排除了我绝对可以排除的部分,这使得它有点长。下面附上脚本的一些注释:

a.除了上述问题之外,该项目在播放模式下按预期运行。

b. TurnManager 是通过 GameFlowManager.StartTurnManager 调用的,而不是在游戏开始时调用。

c.为了分离游戏逻辑和 UI 逻辑,player.cs 是唯一将数据传递到 PlayerController 的项目。

    using System.Collections.Generic;
    using UnityEngine;
    using System.Linq;
     
    public class Player : MonoBehaviour
    {
        // Existing attributes
        public int ID;
        public string playerName; // Renamed 'name' to 'playerName' to avoid conflict
        public int score;
        public int result = 0;
        public bool isWinner;
        private bool _hasTurn;
     
        public bool hasTurn
        {
            get { return _hasTurn; }
            set
            {
                _hasTurn = value; // Simply set the value
                Debug.Log($"{playerName}: from player script hasTurn is set to {hasTurn}");
                // Notify listeners about attribute changes
                OnPlayerAttributesChanged?.Invoke(this);
            }
        }
     
        // Properties for the player's cards, hand, quartets, and score text
        public List<Card> HandCards { get; set; }
        public List<Card> CardsPlayerCanAsk { get; private set; }
        public Transform PlayerHand { get; set; }
        public Transform PlayerQuartets { get; set; }
        public TMPro.TextMeshProUGUI ScoreText { get; set; }
        public TMPro.TextMeshProUGUI ResultText { get; set; }
        // Property to display other players' names excluding the current player
        public List<Player> PlayerToAsk { get; private set; } = new List<Player>();
        private List<Card> _previousCards; // Store the previous state of Cards
     
        private CardManager cardManager;
        // Event to notify listeners when player attributes change
        public event System.Action<Player> OnPlayerAttributesChanged;
     
        private void Awake()
        {
            GameObject managersGameObject = GameObject.Find("Managers");
     
            if (managersGameObject != null)
            {
                // Get the CardManager component from the Managers GameObject
                cardManager = managersGameObject.GetComponent<CardManager>();
     
                if (cardManager == null)
                {
                    Debug.LogError("CardManager component not found on the Managers GameObject.");
                }
            }
            else
            {
                Debug.LogError("Managers GameObject not found in the scene.");
            }
     
                HandCards = new List<Card>();
                CardsPlayerCanAsk = new List<Card>();
        }
     
        // Constructor to initialize the player with the initial turn status
        public Player(bool initialTurn)
        {
            _hasTurn = initialTurn;
            OnPlayerAttributesChanged?.Invoke(this);
        }
     
        public void SetPlayerToAsk(List<Player> playersToAsk)
        {
            PlayerToAsk = playersToAsk;
        }
     
        // Player.cs
        public void AddCardToHand(Card card)
        {
            HandCards.Add(card);
     
            // Set the card's parent to the player's hand
            card.gameObject.transform.SetParent(PlayerHand);
     
            Debug.Log($"Card added to Hand. Total cards in HandCards: {HandCards.Count}");
            CheckForQuartets();
            UpdateCardsPlayerCanAsk();
            // Notify listeners about attribute changes
            OnPlayerAttributesChanged?.Invoke(this);
        }
     
        public void RemoveCardFromHand(Card card)
        {
            HandCards.Remove(card);
            Debug.Log($"Card added to Hand. Total cards in HandCards: {HandCards.Count}");
            CheckForQuartets();
            UpdateCardsPlayerCanAsk();
            // Notify listeners about attribute changes
            OnPlayerAttributesChanged?.Invoke(this);
        }
     
        public void UpdateCardsPlayerCanAsk()
        {
            CardsPlayerCanAsk.Clear();
            foreach (Card card in cardManager.AllCards)
            {
                if (HandCards.Any(playerCard => playerCard.rank == card.rank) && !HandCards.Contains(card))
                {
                    CardsPlayerCanAsk.Add(card);
                }
            }
     
            OnPlayerAttributesChanged?.Invoke(this);
        }
     
        public void CheckForQuartets()
        {
            var groupedCards = HandCards.GroupBy(card => card.rank);
     
            foreach (var group in groupedCards)
            {
                if (group.Count() >= 4)
                {
                    MoveCardsToQuartetsArea(group.ToList());
                }
            }
        }
     
        public void MoveCardsToQuartetsArea(List<Card> quartetCards)
        {
            //...
        }
     
        // Check if the player's hand is empty
        public bool IsHandEmpty()
        {
            return HandCards.Count == 0;
        }
    }
     
     
    using UnityEngine;
    using TMPro;
    using UnityEngine.UI;
    using System.Linq;
    using System.Collections.Generic;
     
    public class PlayerController : MonoBehaviour
    {
        public TMP_Text playerNameText;
        public TMP_Text playerScoreText;
        public TMP_Text playerTurnText;
        public Transform PlayerHand;
        public Transform PlayerQuartetsArea;
     
        public TMP_Dropdown cardsDropdown; // Dropdown for cards player can ask
        public TMP_Dropdown playersDropdown; // Dropdown for active players
        public Button guessButton; // Button for guess request
     
        public delegate void GuessButtonClickHandler(Card selectedCard, Player selectedPlayer);
        public static event GuessButtonClickHandler OnGuessButtonClick;
     
        private List<Card> CardsPlayerCanAsk;
        private List<Player> PlayerToAsk;
        private List<Card> InitialCards; // Placeholder for cards dropdow
     
        private List<int> playerIDs = new List<int>();
        private List<int> cardIDs = new List<int>();
     
        private CardManager cardManager;
     
        public Player AssociatedPlayer { get; set; } // Add this field
       
     
        public void SetPlayerData(Player player)
        {
            AssociatedPlayer = player;
     
            player.OnPlayerAttributesChanged += OnPlayerAttributesChanged;
     
            CardsPlayerCanAsk = player.CardsPlayerCanAsk;
            PlayerToAsk = player.PlayerToAsk;
     
            playerNameText.text = player.playerName; // Use playerName instead of name
            playerScoreText.text = "Score: " + player.score;
     
            playerTurnText.text = player.hasTurn ? "Turn: Yes" : "Turn: No";
     
            // Populate the playersDropdown with active players (excluding the current player)
            UpdatePlayersDropdown(AssociatedPlayer.PlayerToAsk); // Pass the list of player names
     
            // Update the cardsDropdown with cards that the player can ask
            UpdateCardsDropdown(AssociatedPlayer.CardsPlayerCanAsk);
     
            // Deactivate the turn UI objects for players without turn
            if (!player.hasTurn)
            {
                cardsDropdown.gameObject.SetActive(false);
                playersDropdown.gameObject.SetActive(false);
                guessButton.gameObject.SetActive(false);
            }
            else
            {
                cardsDropdown.gameObject.SetActive(true);
                playersDropdown.gameObject.SetActive(true);
                guessButton.gameObject.SetActive(true);
            }
        }
     
        private void OnPlayerAttributesChanged(Player player)
        {
            // Update the score text when the attributes change
            playerNameText.text = player.playerName;
            playerScoreText.text = "Score: " + player.score;
     
            playerTurnText.text = player.hasTurn ? "Turn: Yes" : "Turn: No";
            Debug.Log("OnPlayerAttributesChanged is called");
     
            foreach (Card card in player.HandCards)
            {
                card.gameObject.transform.SetParent(PlayerHand);
            }
     
            UpdatePlayersDropdown(player.PlayerToAsk);
            UpdateCardsDropdown(player.CardsPlayerCanAsk);
     
            // Update the UI activation
            ActivatePlayerTurnUI(player.hasTurn);
            if (player.hasTurn)
            {
                // Activate the turn UI objects for the player with the current turn
                cardsDropdown.gameObject.SetActive(true);
                playersDropdown.gameObject.SetActive(true);
                guessButton.gameObject.SetActive(true);
            }
            else
            {
                // Deactivate the turn UI objects for the player whose turn has ended
                cardsDropdown.gameObject.SetActive(false);
                playersDropdown.gameObject.SetActive(false);
                guessButton.gameObject.SetActive(false);
            }
     
        }
     
        public void UpdatePlayersDropdown(List<Player> updatedPlayersToAsk)
        {
            Debug.Log("UpdatePlayersDropdown is called");
            if (updatedPlayersToAsk != null && updatedPlayersToAsk.Count > 0)
            {
                // Clear the current dropdown options and lists
                playersDropdown.ClearOptions();
                playerIDs.Clear();
     
                // Add the player names to the dropdown and store their IDs
                List<string> playerNames = updatedPlayersToAsk.Select(player =>
                {
                    playerIDs.Add(player.ID);
                    return player.playerName;
                }).ToList();
     
                playersDropdown.AddOptions(playerNames);
            }
            else
            {
                Debug.LogWarning("Updated players list is null or empty.");
            }
        }
     
        public void UpdateCardsDropdown(List<Card> cards)
        {
            if (cardsDropdown != null)
            {
                cardsDropdown.ClearOptions();
                cardIDs.Clear();
     
                if (cards != null)
                {
                    List<string> cardNames = new List<string>();
     
                    foreach (Card card in cards)
                    {
                        cardIDs.Add(card.ID);
                        cardNames.Add(formattedCardEntry);    
                    }
     
                    cardsDropdown.AddOptions(cardNames);
                }
                else
                {
                    Debug.LogWarning("UpdateCardsDropdown - cards is null");
                }
            }
        }
     
     
        public void HandleGuessButtonClick()
        {
            // Disable the button to prevent multiple clicks
            guessButton.interactable = false;
     
            Debug.Log("HandleGuessButtonClick called");
     
            // Get the selected index from the dropdowns
            int selectedPlayerIndex = playersDropdown.value;
            int selectedCardIndex = cardsDropdown.value;
     
            // Use the selected index to access the corresponding IDs
            int selectedPlayerID = playerIDs[selectedPlayerIndex];
            int selectedCardID = cardIDs[selectedCardIndex];
     
            // Find the corresponding Card and Player objects based on IDs
            Card selectedCard = CardsPlayerCanAsk.Find(card => card.ID == selectedCardID);
            Player selectedPlayer = PlayerToAsk.Find(player => player.ID == selectedPlayerID);
     
            Debug.Log($"Selected Card ID: {selectedCardID}, Selected Player ID: {selectedPlayerID}");
            Debug.Log($"Selected Card: {selectedCard.cardName}");
            Debug.Log($"Selected Player: {selectedPlayer.playerName}");
     
            // Directly call the HandlePlayerTurn method in TurnManager
            TurnManager turnManager = GameObject.Find("Managers").GetComponent<TurnManager>();
            if (turnManager != null)
            {
                turnManager.OnGuessButtonClick(selectedCard, selectedPlayer);
            }
            else
            {
                Debug.LogError("TurnManager not found.");
            }
     
            // Re-enable the button after the method is called
            guessButton.interactable = true;
     
            Debug.Log("HandleGuessButtonClick finished");
        }
     
        public void ActivatePlayerTurnUI(bool isActive)
        {
            cardsDropdown.gameObject.SetActive(isActive);
            playersDropdown.gameObject.SetActive(isActive);
            guessButton.gameObject.SetActive(isActive);
        }
     
    }
     
     
    using System.Collections.Generic;
    using UnityEngine;
     
    public class TurnManager : MonoBehaviour
    {
        public PlayerManager playerManager;
        public CardManager cardManager;
        private List<Card> deckCards;
        private bool isInitialized = false;
        private Card selectedCard;
        private Player selectedPlayer;
        private Player currentPlayer;
        private bool isPlayerUIEnabled = true;
        private bool isDrawingCard = false;
     
        private bool hasHandledCurrentPlayer = false;
     
        private void Awake()
        {
            PlayerController.OnGuessButtonClick += OnGuessButtonClick;
        }
     
        private void OnDestroy()
        {
            PlayerController.OnGuessButtonClick -= OnGuessButtonClick;
        }
     
        private void Start()
        {
            StartTurnManager();
        }
     
        public void StartTurnManager()
        {
            if (!isInitialized)
            {
                if (cardManager != null)
                {
                    deckCards = cardManager.GetDeckCards();
                    Debug.Log($"Total number of cards in turn manager deckCards are: {deckCards.Count}");
                    isInitialized = true;
                }
                else
                {
                    Debug.LogError($"{Time.time}: CardManager reference is not assigned.");
                }
     
                currentPlayer = playerManager.Players.Find(player => player.hasTurn);
     
                if (currentPlayer != null)
                {
                    StartCoroutine(TurnLoop());
                }
                else
                {
                    Debug.LogError("No initial player with hasTurn == true found.");
                }
            }
        }
     
        public void OnGuessButtonClick(Card selectedCard, Player selectedPlayer)
        {
            Debug.Log($"OnGuessButtonClick - Selected Card: {selectedCard}, Selected Player: {selectedPlayer}");
            this.selectedCard = selectedCard;
            this.selectedPlayer = selectedPlayer;
     
            if (currentPlayer != null && !isDrawingCard)
            {
                HandlePlayerTurn(currentPlayer); // Moved to HandlePlayerTurn
            }
            else
            {
                Debug.LogWarning($"{Time.time}: Invalid player turn.");
            }
        }
     
        private System.Collections.IEnumerator TurnLoop()
        {
            while (true)
            {
                if (currentPlayer.hasTurn)
                {
                    if (!hasHandledCurrentPlayer)
                    {
                        HandlePlayerTurn(currentPlayer);
                        hasHandledCurrentPlayer = true;
                    }
                }
     
                if (!currentPlayer.hasTurn)
                {
                    hasHandledCurrentPlayer = false;
                    NextCurrentPlayer();
                }
     
                yield return null;
            }
        }
     
        private void HandlePlayerTurn(Player currentPlayer)
        {
            if (selectedCard == null && selectedPlayer == null)
            {
                MakeGuess();
            }
            else
            {
                AskForCard(selectedCard, selectedPlayer);
            }
        }
     
        private void MakeGuess()
        {
            //this method will Enable, disable the turn UI, currently not developed.
            Debug.Log("MakeGuess method is called");
        }
     
        private void AskForCard(Card selectedCard, Player selectedPlayer)
        {
            if (selectedPlayer != null && selectedCard != null)
            {
                if (selectedPlayer.HandCards.Contains(selectedCard))
                {
                    Debug.Log("AskForCar guess is correct");
                    TransferCard(selectedCard, currentPlayer);
                    CheckForQuartets();
     
                    // If the guess is correct and the player's hand isn't empty, allow another guess.
                    if (!IsPlayerHandEmpty(currentPlayer))
                    {
                        // Allow the player to make another guess without drawing a card or ending the turn.
                        HandlePlayerTurn(currentPlayer);
                    }
                    else if (deckCards.Count > 0)
                    {
                        // If the player's hand is empty but the deck isn't, draw a card from the deck.
                        DrawCardFromDeck();
                        // After drawing a card, re-evaluate the hand.
                        if (!IsPlayerHandEmpty(currentPlayer))
                        {
                            // Allow the player to make another guess.
                            // Remove the EndTurn() call from here.
                            HandlePlayerTurn(currentPlayer);
                        }
                    }
                    // No need to check for the deck being empty here, as we've already handled that case.
                }
                else
                {
                    // If the guess is wrong, draw a card from the deck and end the turn.
                    DisplayMessage($"{selectedPlayer.playerName} does not have {selectedCard.cardName}.");
                    DrawCardFromDeck();
                    EndTurn(); // This is the correct place to call EndTurn for an incorrect guess.
                }
            }
        }
     
     
        private void TransferCard(Card selectedCard, Player curPlayer)
        {
            selectedPlayer.RemoveCardFromHand(selectedCard);
            currentPlayer.AddCardToHand(selectedCard);
        }
     
        private bool IsPlayerHandEmpty(Player currentPlayer)
        {
            return currentPlayer.IsHandEmpty();
        }
     
        private void EndTurn()
        {
            NextCurrentPlayer();
        }
     
        private void NextCurrentPlayer()
        {
            int currentIndex = playerManager.Players.IndexOf(currentPlayer);
            int nextIndex = (currentIndex + 1) % playerManager.Players.Count;
            currentPlayer.hasTurn = false;
            Player nextPlayer = playerManager.Players[nextIndex];
            nextPlayer.hasTurn = true;
            currentPlayer = nextPlayer;
        }
     
        private void CheckForQuartets()
        {
            currentPlayer.CheckForQuartets(); // Implement your quartet-checking logic here
        }
     
        private void DisplayMessage(string message)
        {
     
            Debug.Log("Display Message: " + message);
        }
     
        public void DrawCardFromDeck()
        {
            if (cardManager != null && currentPlayer != null)
            {
                cardManager.DrawCardFromDeck(currentPlayer);
            }
            else
            {
                Debug.LogError($"{Time.time}: CardManager reference or current player or selected card is not assigned.");
            }
        }
     
        private void CheckGameEnd()
        {
            //...
        }
     
        private void GameEnd()
        {
            Debug.Log($"{Time.time}: Game Ended");
        }
    }

c# unity-game-engine if-statement multiplayer
1个回答
0
投票

您可以尝试重命名 UI 中按钮 onclick 上映射的函数,以便明确地破坏调用该方法的任何按钮或 UI。之后,通过添加按钮字段并将按钮拖入其中,直接添加您自己的 OnClick 处理程序:

[SerializeField] Button buttonToBeClicked;

void Awake(){ 
buttonToBeClicked.onClick.AddListener( () => { OnEventGuessClickRenamed(); });
}

重命名该函数将确保没有其他人意外调用它并排除 UI 问题。通过代码在唤醒状态下添加 OnClick 处理程序,然后确保它是您添加它的唯一位置。 如果仍然出现问题,请在调试器中单步执行并添加更多日志输出。

© www.soinside.com 2019 - 2024. All rights reserved.