我有一个包含各种场景的Unity项目。我的第一人称控制器有一个脚本,我保留了几个我希望为整个游戏保留的变量。
我会不断改变场景,所以我的剧本有
void Awake() { DontDestroyOnLoad(transform.gameObject); }
让我的变数'价值不会丢失。现在,我将对象放在场景1上,当我加载第一个场景时,我的对象可用。当我改变场景时,一切都表现得像预期的那样:我的变量'价值是守恒的。然而,当我返回场景1时,我的第一人称控制器对象没有被破坏,现在我有两个第一人称控制器(我从另一个场景带来的那个和场景1里面的那个)。相机没有& #39;知道要跟随哪一个。
如何在第一次加载场景时才实例化我的GameObject?
答案 0 :(得分:3)
如果您使用该对象重新加载场景,则无法避免重复的Awake调用。您可以采用两种方法处理:
第二个选项的示例:
static private MyClass instance = null;
void Awake() {
if (instance != null) {
Destroy(this);
return;
}
instance = this;
}
答案 1 :(得分:0)
如果要在加载开始时实例化第一人称控制器,则在实例化时,可以进行条件检查以查看它是否已存在于场景中(然后删除或不实例化)。就跨场景保存信息而言,我建议您改为使用PlayerPrefs。
答案 2 :(得分:0)
你可以把你的第一人控制器(事实上,你喜欢的整个球员)放在预制件中。
然后,不要在场景中使用实例预制件,而是将带有参考的Spawner组件写入预制件。 Spawner可以检查(在Awake中)第一个人控制器是否已经存在,并且只有在预制件已经存在的情况下才会实例化该预制件。
答案 3 :(得分:0)
我知道这是一篇较老的帖子,但当我在寻找一种自动实例化一个静态GameObject的方法时,谷歌的结果很少。不确定旧版本,但这与5.6.1完美配合。我需要一种方法来存储游戏设置并从许多场景中访问它们。我还需要访问某些只能从MonoBehaviour访问的统一函数(如屏幕res等),因此不能选择普通的静态类。我提出的基本上是单例类型的统一GameObject,如果您获得对Instance的引用,并且场景中没有其中一个,它会自动创建它。如果存在,(更改回创建它的场景),重复的自我破坏,以便游戏中只有其中一个。
我想要这个的原因是因为我使用Unity ScriptableObjects存储数据,因为它们可以在编辑和运行时从编辑器中进行编辑,并且运行时的更改不会恢复(如果您使用旧的OnGUI,则非常方便)可以将rect位置存储在可编写脚本的对象中,并观察控件在运行时移动,并且当您停止播放模式时位置不会恢复)
这是我非常基础的课程(从中删除了我的具体数据)
using UnityEngine;
public class GameSettings : MonoBehaviour
{
private static GameSettings _instance;
public static GameSettings Instance
{
get
{
if (_instance != null) return _instance;
else
{
Setup();
return _instance;
}
}
}
public void Start ()
{
DontDestroyOnLoad(this);
}
public void Awake()
{
if (_instance != null) Destroy(this);
}
public static void Setup()
{
GameObject settings = GameObject.Find("GameSettings");
if (settings == null)
{
settings = new GameObject("GameSettings");
settings.AddComponent<GameSettings>();
}
_instance = settings.GetComponent<GameSettings>();
}
}
您可以使用以下两种方式:
1:将它添加到第一个场景中的GameObject(这样您就可以修改检查器中的值)。如果您更改回该场景,则由于检查_instance而不会创建重复项。如果你确实手动将它添加到场景中,请确保将GameObject.Find字符串编辑为GameObject的名称,否则它将创建一个新的。
2:只需创建对ClassName.Instance的引用,如果该对象不存在,它将自动创建该对象。
场景的示例实现脚本:
public class TestScene : MonoBehaviour
{
private GameSettings _settings;
public void Awake()
{
_settings = GameSettings.Instance;
}
public void Start()
{
}
public void Update()
{
}
}
现在你要做的就是将你的公共数据(字符串,整数等)添加为GameSettings类的公共非静态成员,只需使用_settings.MemberName来访问数据。
希望这有助于某人寻找一种动态自动创建GameObjects的方法。如果您构建预制件并将此脚本附加到其任何对象,这也适用。可以方便地在特定场景中自动创建UI元素。
如果你只需要在一个场景中并且不需要它在级别加载中持续存在(例如在某些场景中自动实例化某些UI元素,比如说npc对话框等),只需从类的start函数中删除DontDestroyOnLoad即可。附在预制件上的那些。
答案 4 :(得分:0)
使用属性RuntimeInitializeOnLoadMethod和属性RuntimeInitializeLoadType.BeforeSceneLoad创建一个静态void函数,它将在第一个场景加载之前被调用。通过该功能,您应该能够创建所需的游戏对象等。
using UnityEngine;
public class GameStartupHelper
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void OnBeforeSceneLoad()
{
Debug.Log("OnBeforeSceneLoad(");
// Create your stuff from here...
}
}
ps。无需将类添加到任何场景,只需将脚本文件保留在项目中就可以调用回调。
有关更多说明,请参见this post。