我尝试了所有推荐的步骤和论坛上建议的潜在解决方案。但是,这个问题仍然存在。已经5天了,我仍然试图找到为什么它只发生在构建导出而不是在Unity编辑器中。
问题详细信息:
“IntroductionHUD”(画布)是此场景的画布。“TestText”(TextMeshPro)用于测试“IntroModalScreenPanel”(图像)是否处于活动状态。“IntroModalScreenManager”(空对象)具有处理IntroModalScreenPanel(图像)及其子级的激活和停用的脚本。
“IntroModalScreenManager”脚本中有一个唤醒方法,该方法将“IntroModalScreenPanel”及其子项设置为非活动状态。
脚本中还有其他方法可以激活和停用“IntroModalScreenPanel”及其相应的子对象。这些对象是通过脚本中的SetActive(bool)激活和停用的。这些对象是通过检查器分配的。
出于某种原因,我不知道,'IntroModalScreenPanel'在唤醒方法中停用后没有被激活。另外,这个奇怪的问题只在我进行构建导出时存在。然而,它在Unity编辑器中工作得很好,正如预期的那样。
"TestText“用于测试”IntroModalScreenPanel“是否处于活动状态,以及每次它在构建导出中变为非活动状态时。
另一个奇怪的部分是(如果你看到层次结构快照)'Background'和'TestText'作为'IntroModalScreenManager'的同一画布对象(IntroductionHUD)的子对象工作得很好。据我所知,问题只出在'IntroModalScreenPanel'及其子对象上。
如果有人能在这方面提出建议,我将非常感激。任何建议都可以。
脚本:
using System;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class IntroModalScreenManager : MonoBehaviour
{
public bool IsIntroModalScreenActive() { return _isIntroModalScreenActive; }
//Bool variables...
[SerializeField] private bool _isIntroModalScreenActive;
//INTRO MODAL SCREEN MANAGER
[Header("INTRO MODAL SCREEN MANAGER")]
[SerializeField] private GameObject _introModalScreenPanel;
[SerializeField] private GameObject _introModalScreenHeader;
[SerializeField] private GameObject _introModalScreenBody;
[SerializeField] private GameObject _introModalScreenFooter;
//INTRO MODAL SCREEN PANEL
[Header("INTRO MODAL SCREEN PANEL")]
[SerializeField] private Image _introModalScreenPanelImage;
//HEADER
[Header("HEADER")]
[SerializeField] private Image _introModalScreenPanelImageHeaderImage;
[SerializeField] private TextMeshProUGUI _introModalScreenPanelImageHeaderImageHeaderText;
//BODY
[Header("BODY")]
[SerializeField] private Image _introModalScreenPanelImageBodyImage;
[SerializeField] private Image _introModalScreenPanelImageBodyImageBodyImage;
[SerializeField] private TextMeshProUGUI _introModalScreenPanelImageBodyImageBodyText;
//FOOTER
[Header("FOOTER")]
[SerializeField] private Image _introModalScreenPanelImageFooterImage;
[SerializeField] private Button _introModalScreenPanelImageFooterImageFooterNegativeButton;
[SerializeField] private TextMeshProUGUI _introModalScreenPanelImageFooterImageFooterNegativeButtonText;
[SerializeField] private Button _introModalScreenPanelImageFooterImageFooterAlternateButton;
[SerializeField] private TextMeshProUGUI _introModalScreenPanelImageFooterImageFooterAlternateButtonText;
[SerializeField] private Button _introModalScreenPanelImageFooterImageFooterPositiveButton;
[SerializeField] private TextMeshProUGUI _introModalScreenPanelImageFooterImageFooterPositiveButtonText;
public static IntroModalScreenManager Instance { get; private set; }
private void Awake()
{
if(Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
}
DeactivateModalScreenDisplay();
//DontDestroyOnLoad(this.gameObject);
}
//Called by Awake() in the begining and by other script to deactivate modal screen when needed
public void DeactivateModalScreenDisplay()
{
DeactivateAndClearAll();
_introModalScreenPanel.SetActive(false);
_isIntroModalScreenActive = false;
}
void DeactivateAndClearAll()
{
DeactivateHeader();
DeactivateBody();
DeactivateFooter();
}
//Called by another script to activate modal screen when needed
public void ActivateModalScreenDisplay(bool isBook, bool isBookWithAlternateOption,
bool isSinglePage, bool isSinglePageWithNegativeOption, bool isSinglePageWithNegativeAndAlternateOption,
bool needBodyImage,
string headerText = "",
Sprite bodyImageSprite = null, string bodyText = "",
string footerNegativeButtonText = "", string footerAlternateButtonText = "", string footerPositiveButtonText = "",
Action negativeActionOption = null, Action alternateActionOption = null, Action positiveActionOption = null)
{
_introModalScreenPanel.SetActive(true);
//Book - has front and back navigation options
if (isBook)
{
ActivateHeader(headerText);
ActivateBody(needBodyImage, true, bodyImageSprite, bodyText);
ActivateFooter(true, false, true, footerNegativeButtonText, footerAlternateButtonText, footerPositiveButtonText,
negativeActionOption, alternateActionOption, positiveActionOption);
}
//BookWithAlternateOption - Book with an addition of alternate option. (Eg: Skip button)
else if (isBookWithAlternateOption)
{
ActivateHeader(headerText);
ActivateBody(needBodyImage, true, bodyImageSprite, bodyText);
ActivateFooter(true, true, true, footerNegativeButtonText, footerAlternateButtonText, footerPositiveButtonText,
negativeActionOption, alternateActionOption, positiveActionOption);
}
//SinglePage - has one button (positive option - Eg: Continue, start, etc. buttons)
else if (isSinglePage)
{
ActivateHeader(headerText);
ActivateBody(needBodyImage, true, bodyImageSprite, bodyText);
ActivateFooter(false, false, true, footerNegativeButtonText, footerAlternateButtonText, footerPositiveButtonText,
negativeActionOption, alternateActionOption, positiveActionOption);
}
//SinglePageWithNegativeOption - Single page with an addition of negative option (Eg: Confirmations)
else if (isSinglePageWithNegativeOption)
{
ActivateHeader(headerText);
ActivateBody(needBodyImage, true, bodyImageSprite, bodyText);
ActivateFooter(true, false, true, footerNegativeButtonText, footerAlternateButtonText, footerPositiveButtonText,
negativeActionOption, alternateActionOption, positiveActionOption);
}
//SinglePageWithNegativeAndAlternateOption - Single page with negative option and an aditional alternate button (Eg: 3rd option in any choice making scenes)
else if (isSinglePageWithNegativeAndAlternateOption)
{
ActivateHeader(headerText);
ActivateBody(needBodyImage, true, bodyImageSprite, bodyText);
ActivateFooter(true, true, true, footerNegativeButtonText, footerAlternateButtonText, footerPositiveButtonText,
negativeActionOption, alternateActionOption, positiveActionOption);
}
_isIntroModalScreenActive = true;
}
void ActivateHeader(string headerText)
{
//Only if the header text has some value, this component will be active... Implemented this only for header & footer, as header & footer is used for all types of modal screen layouts.
if(headerText != "" && headerText != null)
{
//HEADER
_introModalScreenHeader.SetActive(true);//Header Object
_introModalScreenPanelImageHeaderImageHeaderText.gameObject.SetActive(true);//Header Text Object
_introModalScreenPanelImageHeaderImageHeaderText.text = headerText;//Header Text
}
}
void DeactivateHeader()
{
_introModalScreenPanelImageHeaderImageHeaderText.text = "";//Header Text
if (_introModalScreenPanelImageHeaderImageHeaderText.gameObject.activeSelf)
{
_introModalScreenPanelImageHeaderImageHeaderText.gameObject.SetActive(false);//Header Text Object
}
if (_introModalScreenHeader.activeSelf)
{
_introModalScreenHeader.SetActive(false);//Header Object
}
}
void ActivateBody(bool needBodyImage, bool needBodyText, Sprite bodyImageSprite, string bodyText)
{
//BODY
_introModalScreenBody.SetActive(true);//Body Object
_introModalScreenPanelImageBodyImageBodyImage.gameObject.SetActive(needBodyImage);//Body Image Object
if (_introModalScreenPanelImageBodyImageBodyImage.gameObject.activeSelf)//Body Image Object Image Sprite
{ _introModalScreenPanelImageBodyImageBodyImage.sprite = bodyImageSprite; }
_introModalScreenPanelImageBodyImageBodyText.gameObject.SetActive(needBodyText);//Body Text Object
if (_introModalScreenPanelImageBodyImageBodyText.gameObject.activeSelf)//Body Text Object Text
{ _introModalScreenPanelImageBodyImageBodyText.text = bodyText; }
}
void DeactivateBody()
{
_introModalScreenPanelImageBodyImageBodyText.text = "";
if (_introModalScreenPanelImageBodyImageBodyText.gameObject.activeSelf)
{
_introModalScreenPanelImageBodyImageBodyText.gameObject.SetActive(false);//Body Text Object
}
_introModalScreenPanelImageBodyImageBodyImage.sprite = null;
if (_introModalScreenPanelImageBodyImageBodyImage.gameObject.activeSelf)
{
_introModalScreenPanelImageBodyImageBodyImage.gameObject.SetActive(false);//Body Image Object
}
if (_introModalScreenBody.activeSelf)
{
_introModalScreenBody.SetActive(false);//Body Object
}
}
void ActivateFooter(bool needFooterNegativeButton, bool needFooterAlternateButton, bool needFooterPositiveButton,
string footerNegativeButtonText, string footerAlternateButtonText, string footerPositiveButtonText,
Action negativeActionOption, Action alternateActionOption, Action positiveActionOption)
{
//FOOTER
_introModalScreenFooter.SetActive(true);//Footer Object
//When this footer button is needed, only if the footer text and action has some value, this component will be active... Implemented this only for header & footer, as header & footer is used for all types of modal screen layouts.
if (needFooterNegativeButton && footerNegativeButtonText != null && footerNegativeButtonText != "" && negativeActionOption != null)
{
_introModalScreenPanelImageFooterImageFooterNegativeButton.gameObject.SetActive(needFooterNegativeButton);//Footer Negative Button
if (_introModalScreenPanelImageFooterImageFooterNegativeButton.gameObject.activeSelf)
{
_introModalScreenPanelImageFooterImageFooterNegativeButtonText.text = footerNegativeButtonText;//Footer Negative Button Text
_introModalScreenPanelImageFooterImageFooterNegativeButton.onClick.AddListener(new UnityEngine.Events.UnityAction(negativeActionOption));//Add listener to the button's OnClick
}
}
else
{
_introModalScreenPanelImageFooterImageFooterNegativeButton.gameObject.SetActive(needFooterNegativeButton);//Footer Negative Button
}
//When this footer button is needed, only if the footer text and action has some value, this component will be active... Implemented this only for header & footer, as header & footer is used for all types of modal screen layouts.
if (needFooterAlternateButton && footerAlternateButtonText != null && footerAlternateButtonText != "" && alternateActionOption != null)
{
_introModalScreenPanelImageFooterImageFooterAlternateButton.gameObject.SetActive(needFooterAlternateButton);//Footer Alternate Button
if (_introModalScreenPanelImageFooterImageFooterAlternateButton.gameObject.activeSelf)
{
_introModalScreenPanelImageFooterImageFooterAlternateButtonText.text = footerAlternateButtonText;//Footer Alternate Button Text
_introModalScreenPanelImageFooterImageFooterAlternateButton.onClick.AddListener(new UnityEngine.Events.UnityAction(alternateActionOption));//Add listener to the button's OnClick
}
}
else
{
_introModalScreenPanelImageFooterImageFooterAlternateButton.gameObject.SetActive(needFooterAlternateButton);//Footer Alternate Button
}
//When this footer button is needed, only if the footer text and action has some value, this component will be active... Implemented this only for header & footer, as header & footer is used for all types of modal screen layouts.
if (needFooterPositiveButton && footerPositiveButtonText != null && footerPositiveButtonText != "" && positiveActionOption != null)
{
_introModalScreenPanelImageFooterImageFooterPositiveButton.gameObject.SetActive(needFooterPositiveButton);//Footer Positive Button
if (_introModalScreenPanelImageFooterImageFooterPositiveButton.gameObject.activeSelf)
{
_introModalScreenPanelImageFooterImageFooterPositiveButtonText.text = footerPositiveButtonText;//Footer Positive Button Text
_introModalScreenPanelImageFooterImageFooterPositiveButton.onClick.AddListener(new UnityEngine.Events.UnityAction(positiveActionOption));//Add listener to the button's OnClick
}
}
else
{
_introModalScreenPanelImageFooterImageFooterPositiveButton.gameObject.SetActive(needFooterPositiveButton);//Footer Positive Button
}
}
void DeactivateFooter()
{
#region COMMENTED PART - NEDD TO RESOLVE LATER - KEPT FOR FUTURE UPGRADE...
//To make the button not be in selected state after clicking once: is to set it's Navigation drop down option from inspector to none.
//Or can do it by code as done for each button below.
//Unfortunately, I tried, but it doesn't work that way. Maybe I did it wrong. For now lets do the inspector method.
//https://forum.unity.com/threads/clicking-a-button-leaves-it-in-mouseover-state.285167/
#endregion
_introModalScreenPanelImageFooterImageFooterNegativeButton.onClick.RemoveAllListeners();//Remove all listeners to the button's OnClick
//var nav = _introModalScreenPanelImageFooterImageFooterNegativeButton.navigation;
//nav.mode = Navigation.Mode.None;
if (_introModalScreenPanelImageFooterImageFooterNegativeButton.gameObject.activeSelf)
{
_introModalScreenPanelImageFooterImageFooterNegativeButton.gameObject.SetActive(false);//Footer Negative Button
}
_introModalScreenPanelImageFooterImageFooterAlternateButton.onClick.RemoveAllListeners();//Remove all listeners to the button's OnClick
//nav = _introModalScreenPanelImageFooterImageFooterAlternateButton.navigation;
//nav.mode = Navigation.Mode.None;
if (_introModalScreenPanelImageFooterImageFooterAlternateButton.gameObject.activeSelf)
{
_introModalScreenPanelImageFooterImageFooterAlternateButton.gameObject.SetActive(false);//Footer Alternate Button
}
_introModalScreenPanelImageFooterImageFooterPositiveButton.onClick.RemoveAllListeners();//Remove all listeners to the button's OnClick
//nav = _introModalScreenPanelImageFooterImageFooterPositiveButton.navigation;
//nav.mode = Navigation.Mode.None;
if (_introModalScreenPanelImageFooterImageFooterPositiveButton.gameObject.activeSelf)
{
_introModalScreenPanelImageFooterImageFooterPositiveButton.gameObject.SetActive(false);//Footer Positive Button
}
if (_introModalScreenFooter.activeSelf)
{
_introModalScreenFooter.SetActive(false);//Footer Object
}
}
}
2条答案
按热度按时间vmdwslir1#
脚本的运行顺序不受保证,并且很可能在编辑器和构建之间有所不同。
唯一的保证是所有的Awakes()都会在第一个Start()之前运行,利用它来为你的优势。作为一个经验法则,在Awake中初始化对象,但只与Start()中的其他对象交互,而永远不要在Awake()中,因为其他对象可能还没有初始化,特别是如果你使用Singletons。
很可能是因为您的脚本在构建中的启动顺序不同,
vc9ivgsu2#
打开“编辑/项目设置”并转到“脚本执行顺序”
将所有这些脚本添加到列表中,并按照需要的顺序排列它们。然后,在编辑器中测试它。现在它在编辑器中的行为应该与在构建中的行为相同,所以如果它在编辑器中工作,它应该在构建中工作。如果它不工作,首先改变顺序。