我在层次结构中有一个场景和3个父对象。 3个父对象是:
游戏数据(所有游戏对象都是其中的子对象)
主菜单
游戏管理器(在某些情况下可控制暂停/取消游戏)
这个想法的主要目标是当游戏开始时从主菜单开始,然后单击“开始新游戏”按钮,当按下逃逸键时它将开始游戏,它将回到主菜单,我可以再次开始新游戏或恢复游戏。我也这样做是在游戏运行时,如果您按下P按钮,它将暂停/取消暂停游戏。
首先,附加到游戏管理器的脚本:
在这里,我正在为“对话系统”,“景深”,“主菜单”做参考。在底部,我使用find来查找“景深”和“对话系统”,因为我销毁了游戏数据对象。开始新游戏时:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameController : MonoBehaviour
{
public GameObject dialogueSystem;
public DepthOfField depthOfField;
public static bool gamepaused = false;
public GameObject mainMenu;
private void Start()
{
Time.timeScale = 0f;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
gamepaused = !gamepaused;
if (gamepaused)
{
Time.timeScale = 0f;
}
else
{
Time.timeScale = 1f;
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
if(depthOfField == null || dialogueSystem == null)
{
depthOfField = GameObject.Find("Player Camera").GetComponent<DepthOfField>();
dialogueSystem = GameObject.Find("Dialogue System");
}
depthOfField.DepthOfFieldInit(3f);
Time.timeScale = 0f;
dialogueSystem.SetActive(false);
mainMenu.SetActive(true);
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
}
}
问题是对话系统和景深存在于游戏数据中,当我销毁游戏数据并再次使用预制实例化游戏数据以制作新游戏以启动丢失的GameController脚本中的变量时,参考,我需要使用查找。但是,使用多次查找是个好主意吗?
此脚本的下一个附加到主菜单:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenu : MonoBehaviour
{
public GameObject gameDataPrefab;
public GameObject gameData;
public GameObject mainMenu;
public void StartNewGame()
{
var gdata = GameObject.Find("Game Data");
if (gdata != null)
{
Destroy(gdata);
}
GameObject go = Instantiate(gameDataPrefab);
go.name = "Game Data";
mainMenu.SetActive(false);
GameController.gamepaused = false;
Time.timeScale = 1f;
}
public void ResumeGame()
{
}
public void QuitGame()
{
Application.Quit();
}
}
在这里,当我单击UI按钮以在功能StartNewGame中启动新游戏时,我销毁了游戏数据并创建了一个新游戏。这会使GameController脚本中的变量丢失参考。
最后一个脚本附加到游戏数据上,该脚本是我在将逃逸键击回到主菜单时调用的方法DepthOfFieldInit才能生效。
问题是由于游戏数据被破坏,一些变量丢失了引用。例如,我在:
playerLockMode.PlayerLockState(true, true);
由于playerLockMode也位于已被破坏的游戏数据上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfField : MonoBehaviour
{
public UnityEngine.GameObject player;
public PostProcessingProfile postProcessingProfile;
public bool dephOfFieldFinished = false;
public LockSystem playerLockMode;
private Animator playerAnimator;
private float clipLength;
private Coroutine depthOfFieldRoutineRef;
// Start is called before the first frame update
void Start()
{
if (depthOfFieldRoutineRef != null)
{
StopCoroutine(depthOfFieldRoutineRef);
}
playerAnimator = player.GetComponent<Animator>();
AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
foreach (AnimationClip clip in clips)
{
clipLength = clip.length;
}
DepthOfFieldInit(clipLength);
// Don't forget to set depthOfFieldRoutineRef to null again at the end of routine!
}
public void DepthOfFieldInit(float duration)
{
var depthOfField = postProcessingProfile.depthOfField.settings;
depthOfField.focalLength = 300;
StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, duration));
postProcessingProfile.depthOfField.settings = depthOfField;
}
public IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
{
playerLockMode.PlayerLockState(true, true);
float counter = 0f;
while (counter < duration)
{
var dof = postProcessingProfile.depthOfField.settings;
counter += Time.deltaTime;
float val = Mathf.Lerp(fromVal, toVal, counter / duration);
dof.focalLength = val;
postProcessingProfile.depthOfField.settings = dof;
yield return null;
}
playerAnimator.enabled = false;
dephOfFieldFinished = true;
depthOfFieldRoutineRef = null;
}
}
但是我不明白在开始新游戏时是否立即实例化游戏数据,为什么变量会丢失引用?在销毁游戏数据后,是否可以在任何地方多次使用“查找”的更好方法?也许StartNewGame中的整个代码是错误的?
我的主要目标是单击StartNewGame重新开始一个新游戏。当按下逃逸键时,暂停游戏并返回主菜单。
这是我的层次结构的屏幕截图: