1

我正在制作的游戏有一个奇怪的问题。出于某种原因,每当我从菜单切换到另一个场景时,都可以在后台看到菜单,并且它的按钮处于活动状态。所以玩家可以点击菜单按钮所在的空间(虽然实际上不在菜单屏幕上)并得到意外的响应。它只发生在这一幕上;所有其他场景都正常工作。这是有问题的脚本。

    using UnityEngine;
    using System.Collections;



public class Menu : MonoBehaviour 
{
    //public Texture2D background;
    public GUITexture backgroundCopy;
    public GUITexture background;
    float bgPos, bgCopyPos;
    public GUISkin buttonSkin;
    public GUISkin recordSkin;
    public GUIText guiRecordLabel;
    public GUIText guiTime;
    public GUIText guiComplete;
    public GUIText guiTurns;
    public GUIText guiLosses;
    public GUIText guiQuits;

    Records records = new Records();

    //public static Menu instance = null;
    private bool onMenuScreen;              //this prevents the menu buttons from being pressed when I'm not on the menu. weird issue.

    void Awake()
    {
        //ScreenFader.fadeToBlack = false;
        //create a singleton so that there's only one instance of a menu at any time.
        //if (instance != null)
        //    DestroyObject(this);    //destroys the new instance
        //else
        //    instance = this;

        //menu needs to persist for the duration of the game because I want the music to keep playing across multiple screens. -THIS IS NO LONGER THE CASE
        //DontDestroyOnLoad(this);

        //load records
        records.LoadRecords();

    }
    // Use this for initialization
    void Start () 
    {
        bgPos = 0;                  //initial x Position of the background
        bgCopyPos = -Screen.width;  //this is placed before the original background.
        onMenuScreen = true;        //I SHOULDN'T NEED THIS

    }





    // Update is called once per frame
    void Update () 
    {
        if (!onMenuScreen)  //I need to do this check because the menu persists and remains on screen.
        {
            guiRecordLabel.enabled = false;
            guiTime.enabled = false;
            guiComplete.enabled = false;     //I shouldn't need any of this
            guiTurns.enabled = false;
            guiLosses.enabled = false;
            guiQuits.enabled = false;
        }
        else
        {
            guiRecordLabel.enabled = true;
            guiTime.enabled = true;
            guiComplete.enabled = true;
            guiTurns.enabled = true;
            guiLosses.enabled = true;
            guiQuits.enabled = true;
        }

        //show records
        guiRecordLabel.material.color = Color.red;
        guiTime.text = "Total Time: " + records.TotalTime;
        guiComplete.text = "Completion: " + records.CompletionRate + "%";
        guiTurns.text = "Turn Total: " + records.TurnTotal;
        guiLosses.text = "Total Losses: " + records.LossCount;
        guiQuits.text = "Rage Quits: " + records.RageCount;



        //scroll the background. TODO: provide different backgrounds
        bgPos = (bgPos > Screen.width) ? -Screen.width + 2 : bgPos += 1;
        bgCopyPos = (bgCopyPos > Screen.width) ? -Screen.width + 2 : bgCopyPos += 1;

        background.pixelInset = new Rect(bgPos, background.transform.position.y, Screen.width, Screen.height);
        backgroundCopy.pixelInset = new Rect(bgCopyPos, background.transform.position.y, Screen.width, Screen.height);


    }

    void OnGUI()
    {


        //buttons
        GUI.skin = buttonSkin;
        if (onMenuScreen && GUI.Button(new Rect(60 * Title.scale.x, 400 * Title.scale.y, 130 * Title.scale.x, 33 * Title.scale.y), "Level Select"))
        {           
            Application.LoadLevel("LevelSelectScreen");
            onMenuScreen = false;
        }

        if (onMenuScreen && GUI.Button(new Rect(300 * Title.scale.x, 400 * Title.scale.y, 130 * Title.scale.x, 33 * Title.scale.y), "Help & Options"))
        {         
            Application.LoadLevel("HelpScreen");
            onMenuScreen = false;
        }

        if (onMenuScreen && GUI.Button(new Rect(540 * Title.scale.x, 400 * Title.scale.y, 130 * Title.scale.x, 33 * Title.scale.y), "Back to Title"))
        {
            //DestroyObject(this);    //Kill the menu whenever I return to title screen.         
            Application.LoadLevel("TitleScreen");
            onMenuScreen = false;
        }
    }
}

我认为问题可能是我在现场的第二个脚本,但我禁用了它,我也遇到了同样的问题。这是另一个脚本。

   /* This script is used to allow music to persist between screens. It uses a singleton to prevent more than once instance
 * from being created. This script must be placed in MenuScreen scene. */

using UnityEngine;
using System.Collections;
using System.IO;
using System;

public class MusicPlayer : MonoBehaviour 
{

    public static MusicPlayer instance = null;
    AudioClip track;        //copy of the music currently playing.
    public AudioClip[] musicTracks;
    AudioSource source;
    private bool musicPlaying;
    private short trackNumber;

    void Awake()
    {
        //create a singleton so that there's only one instance of a music track at any time.
        if (instance != null)
            DestroyObject(this);    //destroys the new instance
        else
            instance = this;


        DontDestroyOnLoad(this);
    }
    // Use this for initialization
    void Start () 
    {
        source = GetComponent<AudioSource>();
        LoadTrackFile();
    }

    public string TrackName
    {
        get { return musicTracks[trackNumber].name; }
    }

    public short TrackNumber
    {
        get { return trackNumber; }
        set { trackNumber = value; }
    }

    public bool MusicPlaying
    {
        get { return musicPlaying; }
        set { musicPlaying = value; }
    }

    /* Create/update a file to save track number. */
    public void UpdateTrackFile()
    {
        string directory = Application.persistentDataPath + "/Tile Crusher/Data/";
        string fileName = "trackfile.savefile";

        //initialize track number if file doesn't exist.
        if (!File.Exists(directory + fileName))
        {
            trackNumber = 0;
        }

        FileStream fs = new FileStream(directory + fileName, FileMode.OpenOrCreate);
        StreamWriter writer = new StreamWriter(fs);

        //write track number to file
        writer.WriteLine(trackNumber);

        writer.Close();
        fs.Close();
    }

    void LoadTrackFile()
    {

        //start searching and reading files
        string directory = Application.persistentDataPath + "/Tile Crusher/Data/";
        string fileName = "trackfile.savefile";


        //locate the file.  If it doesn't exist, it will be created.
        if (!File.Exists(directory + fileName))
        {
            UpdateTrackFile();
        }

        //read data. The file is read in a specific order.
        FileStream fs = new FileStream(directory + fileName, FileMode.Open);
        StreamReader fileRead = new StreamReader(fs);

        //load track number
        string track = fileRead.ReadLine();
        trackNumber = Int16.Parse(track);

        //done   
        fileRead.Close();
        fs.Close();


    }

    // Update is called once per frame
    void Update () 
    {

        if (!musicPlaying && trackNumber >= 0)
        {
            //play music
            source.clip = musicTracks[trackNumber];
            source.Play();
            musicPlaying = true;
        }
        else if (trackNumber < 0)
            source.Stop();


}

困扰我的是这个问题只发生在这一场景中。我所有的其他场景都很好。我使用了一种解决方法,但我认为我不需要为这个场景做这样的事情。有人能帮忙吗?

4

1 回答 1

0

我会重构 Menu 类,以便您可以在不需要时将其整体禁用,原因有两个:

  1. Update仅当您实际在菜单场景中时才需要打开代码
  2. OnGui 非常昂贵,因为它每帧调用多次

您可以使用Object.DontDestroyOnLoad制作一个空的游戏对象MenuManager,甚至更好SceneManager持久化对象。所以启用和禁用对象可以在这个类中完成。Menu

也许Unity 单例管理器类可以给你一些启发。我使用这种方法来保持层次结构小而干净。我的所有场景都包含_ApplicationStartup来自预制件的游戏对象,其中包含初始引导代码和一些用于开发的增强功能。当您的项目正在增长并且有几个场景时,我强烈建议您以可以直接测试场景的方式设计您的场景。当您在场景 Level-5 上工作时,如果您必须切换回主场景进行测试,那是非常烦人的。

于 2013-05-20T08:11:40.880 回答