我对我正在制作的游戏有一个奇怪的问题。出于某种原因,每当我从菜单中切换到另一个场景时,都可以在后台看到菜单并且其按钮处于活动状态。因此,玩家可以点击菜单按钮所在的空间(而实际上不在菜单屏幕上)并获得意外响应。它只发生在这一个场景上;所有其他场景都正常工作。这是带问题的脚本。
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();
}
让我烦恼的是,这个问题只发生在这一个场景中。我所有的其他场景都很好。我使用了一种解决方法,但我认为我不需要为这一个场景做这样的事情。任何人都可以帮忙吗?
答案 0 :(得分:0)
我会重构Menu类,这样你就可以在不需要的时候整个禁用它,原因有两个:
Update
上的代码您可以使用Object.DontDestroyOnLoad制作一个空的游戏对象MenuManager
甚至更好的SceneManager
种持续。因此,可以在此类中启用和禁用Menu
对象。
也许Unity singleton manager classes可以给你一些灵感。我使用这种方法来保持层次结构小而干净。我的所有场景都包含来自预制件的游戏对象_ApplicationStartup
,其中包含初始引导代码和一些开发增强功能。当您的项目不断增长并且有几个场景时,我强烈建议您以可以直接测试场景的方式设计场景。当您在第5级场景中工作时,如果您必须切换回主场景进行测试,则会非常烦人。