我正在為一個學校專案和我的成就系統制作一個 cookie clicker 游戲,我希望彈出一個簡單的影片,并在一個單獨的選單腳本中顯示文本,它已經可以正常作業了。
我遇到的問題是前兩個成就運行良好,但在第二個成就彈出后,它只是重復“測驗 B”和“測驗 C”在控制臺中無限重復。
我試圖讓價值觀嘗試使“if”陳述句無效,但似乎沒有任何效果。
我覺得我只是在用我創造的所有布林值來吃自己的尾巴。
這是我下面的代碼,僅來自我的 Unity 檔案中的一個腳本。希望這有足夠的指導資訊。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Achievements : MonoBehaviour
{
[SerializeField] GameObject achievementBanner;
[SerializeField] GameObject achievementText;
[SerializeField] GameObject achievementBannerAnimation;
[SerializeField] GameObject achievementTextAnimation;
[SerializeField] GameObject achiOne;
[SerializeField] GameObject achiTwo;
[SerializeField] GameObject achiThree;
[SerializeField] GameObject achiFour;
[SerializeField] GameObject achiFive;
[SerializeField] GameObject achiSix;
[SerializeField] public static int achiementcount;
bool achievementrec = false;
bool achievementani = false;
bool achidone = false;
// Start is called before the first frame update
void Start()
{
achiOne.SetActive(false);
achiTwo.SetActive(false);
achiThree.SetActive(false);
achiFour.SetActive(false);
achiFive.SetActive(false);
achiSix.SetActive(false);
achievementBanner.SetActive(false);
achievementText.SetActive(false);
achievementText.GetComponent<Text>().text = "Achievement: First cookie!";
}
// Update is called once per frame
void Update()
{
print(achiementcount);
print(achidone);
if (achiementcount == 1)
{
if (!achievementani)
{
if (!achievementrec)
{
print("Test D");
achiOne.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
StartCoroutine(AchievementGot());
///achidone = true;
}
}
}
if (achidone == true)
{
///print("Test");
///achidone = false;
if (achiementcount == 2)
{
achievementText.GetComponent<Text>().text = "Achievement: First Clicker!";
achievementani = false;
achievementrec = false;
if (!achievementani)
{
if (!achievementrec)
{
print("Test C");
achiTwo.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
///achidone = true;
StartCoroutine(AchievementGot());
}
}
}
}
///print(achidone);
if (achidone == true)
{
///achidone = false;
if (achiementcount == 3)
{
achievementText.GetComponent<Text>().text = "Achievement: First Upgrade!";
achievementani = false;
achievementrec = false;
if (!achievementani)
{
if (!achievementrec)
{
print("Test A");
achiThree.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
StartCoroutine(AchievementGot());
}
}
}
}
}
IEnumerator AchievementGot()
{
///achievementrec = true;
achievementBannerAnimation.GetComponent<Animation>().Play("Achievement");
achievementTextAnimation.GetComponent<Animation>().Play("AchiText");
yield return new WaitForSeconds(6);
achidone = true;
print("Test B");
///print(achidone);
achievementBanner.SetActive(false);
achievementText.SetActive(false);
achievementani = true;
achievementrec = true;
///achidone = false;
}
}
uj5u.com熱心網友回復:
首先,您應該使用串列/陣列。
然后,您可能還希望在第一次解鎖成就時僅顯示一次橫幅,因此您還應該跟蹤您已經顯示的橫幅。
例如像
[Serializable]
public class Achievement
{
// text to display in the banner
public string Label;
// the object to enable
public GameObject GameObject;
// has this been achieved
public bool Unlocked;
// has this achievement been displayed
public bool Displayed;
}
public class Achievements : MonoBehaviour
{
// in general instead of many GetComponent calls use the correct type right away in the Inspector
[SerializeField] private GameObject achievementBanner;
[SerializeField] private Text achievementText;
[SerializeField] private Animation achievementBannerAnimation;
[SerializeField] private Animation achievementTextAnimation;
[SerializeField] private Achievement[] achievements;
// is currently a display routine running already?
private bool currentlyDisplaying;
private void Start()
{
// initially hide all objects
foreach (var achievement in achievements)
{
achievement.GameObject.SetActive(false);
}
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
}
private void Update()
{
// if currently a display routine is running do nothing
if (currentlyDisplaying) return;
// otherwise go through all achievements
foreach (var achievement in achievements)
{
// check if one is unlocked but hasn't been displayed yet
if (achievement.Unlocked && !achievement.Displayed)
{
// set to displayed and display it
StartCoroutine(DisplayAchievement(achievement));
// break to only handle one at a time
break;
}
}
}
private IEnumerator DisplayAchievement(Achievement achievement)
{
// just in case if other routine is already running do nothing
if (currentlyDisplaying) yield break;
// block other routines from being started
currentlyDisplaying = true;
// set displayed so it is not displayed again
achievement.Displayed = true;
// Enable your objects and set the text accordingly
achievementText.text = achievement.Label;
achievementText.gameObject.SetActive(true);
achievementBanner.SetActive(true);
achievement.GameObject.SetActive(true);
achievementBannerAnimation.Play("Achievement");
achievementTextAnimation.Play("AchiText");
yield return new WaitForSeconds(6);
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
// allow the next routine to start
currentlyDisplaying = false;
}
}
甚至比內部投票檢查更好的Update
是寧愿參加諸如此類的事件
[Serializable]
public class Achievement
{
// text to display in the banner
public string Label;
// the object to enable
public GameObject GameObject;
// has this been achieved
// private but (de)serializable e.g. for saving via Json etc later on
// and editable via Inspector
[SerializeField] private bool unlocked = false;
// public read-only access
public bool Unlocked => unlocked;
public void Unlock()
{
// is this already unlocked anyway?
if(!unlocked)
{
// if not unlock and invoke event
unlocked = true;
OnUnlocked?.Invoke(this);
}
}
// global event to subscribe to for all achievement unlocks
public static event Action<Achievement> OnUnlocked;
}
然后聽這個
public class Achievements : MonoBehaviour
{
// in general instead of many GetComponent calls use the correct type right away in the Inspector
[SerializeField] private GameObject achievementBanner;
[SerializeField] private Text achievementText;
[SerializeField] private Animation achievementBannerAnimation;
[SerializeField] private Animation achievementTextAnimation;
[SerializeField] private Achievement[] achievements;
// is currently a display routine running already?
private bool currentlyDisplaying;
// First-In first-out collection to work off the unlocked achievements in the UI
private readonly Queue<Achievement> achievementsToDisplay = new ();
private void Start()
{
// initially hide all objects
foreach (var achievement in achievements)
{
achievement.GameObject.SetActive(false);
}
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
// listen to the event
Achievement.OnUnlocked = OnAchievementUnlocked;
}
private void OnDestroy()
{
// to avoid exceptions unregister the listener from the event
Achievement.OnUnlocked -= OnAchievementUnlocked;
}
// called everytime an achievement is unlocked
private void OnAchievementUnlocked(Achievement achievement)
{
// add achievement to the queue to work
achievementsToDisplay.Enqueue(achievement);
// if there isn't a worker routine running already anyway
if (!currentlyDisplaying)
{
// start one now
StartCoroutine(DisplayAchievements());
}
}
private IEnumerator DisplayAchievement()
{
// just in case if other routine is already running do nothing
if (currentlyDisplaying) yield break;
// block other routines from being started
currentlyDisplaying = true;
// as long as there are new achievements in the queue simply continue directly with the next one
while(achievementsToDisplay.Count > 0)
{
var achievement = achievementsToDisplay.Dequeue();
// Enable your objects and set the text accordingly
achievementText.text = achievement.Label;
achievementText.gameObject.SetActive(true);
achievementBanner.SetActive(true);
achievement.GameObject.SetActive(true);
achievementBannerAnimation.Play("Achievement");
achievementTextAnimation.Play("AchiText");
yield return new WaitForSeconds(6);
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
}
// when queue is worked off terminate for now
// and allow the next routine to be started later
currentlyDisplaying = false;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/521520.html
標籤:C#unity3d