1

私が作っているゲームに奇妙な問題があります。何らかの理由で、メニューから別のシーンに変更するたびに、メニューが背景に表示され、そのボタンがアクティブになります。そのため、プレイヤーはメニュー ボタンがあったスペースを (実際にはメニュー画面にないときに) タップすると、意図しない応答が返される可能性がありました。この 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;
        }
    }
}

この問題は、現場にある 2 番目のスクリプトである可能性があると思いましたが、それを無効にしたところ、同じ問題が発生しました。これが他のスクリプトです。

   /* 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();


}

私を悩ませているのは、この問題がこの 1 つのシーンでのみ発生していることです。他のすべてのシーンは正常に動作します。回避策を使用しましたが、この 1 つのシーンにそのようなことを行う必要はないと思います。誰でもこれを手伝ってもらえますか?

4

1 に答える 1

0

Menu クラスをリファクタリングして、2 つの理由で不要なときに全体を無効にできるようにします。

  1. コード オンUpdateは、実際にメニュー シーンにいる場合にのみ必要です。
  2. OnGui はフレームごとに数回呼び出されるため、かなり高価です。

Object.DontDestroyOnLoadを使用して、空のゲーム オブジェクトを作成しMenuManagerたり、さらに優れたSceneManager種類の永続化を作成したりできます。したがって、オブジェクトの有効化と無効化はこのクラスで行うことができます。Menu

おそらく、Unity シングルトン マネージャー クラスがインスピレーションを与えてくれるでしょう。このアプローチを使用して、階層を小さくきれいに保ちます。_ApplicationStartup私のすべてのシーンには、最初のブートストラップ コードと開発用の拡張機能を含むプレハブのゲーム オブジェクトが含まれています。プロジェクトが成長しており、シーンがいくつかある場合は、シーンを直接テストできるようにシーンを設計することを強くお勧めします。シーン レベル 5 で作業しているときに、テストのためにメイン シーンに戻らなければならない場合、非常に面倒です。

于 2013-05-20T08:11:40.880 に答える