2015-03-24 5 views
0

У меня есть проект Unity с различными сценами. У моего контроллера первого лица есть сценарий, в котором я сохраняю несколько переменных, которые я хочу сохранить для всей игры.Создавать объект при первой загрузке сцены в Unity

Я буду изменение сцены постоянно, так что мой сценарий имеет

void Awake() { DontDestroyOnLoad(transform.gameObject); } 

так, что значение моих переменных не будут потеряны. Теперь я поместил объект на сцену 1, и мой объект доступен, когда я загружаю первую сцену. Когда я меняю сцены, все ведет себя так, как ожидалось: значения моих переменных сохраняются. Однако, когда я вернусь на сцену 1, мой объект Control Person не разрушен, и теперь у меня есть два контроллера первого лица (тот, который я привез из другой сцены и тот, который находится внутри сцены 1). Камера не знаете, какой из них следует соблюдать.

Как я могу создать экземпляр объекта GameObject только при первом загрузке сцены?

ответ

0

Если вы создаете экземпляр своих контроллеров первого лица в начале загрузки, при создании экземпляра вы можете выполнить условную проверку, чтобы убедиться, что она уже существует в сцене (затем удалите или не создайте экземпляр). Что касается сохранения информации в разных сценах, я предлагаю вместо этого использовать PlayerPrefs.

2

Невозможно избежать дублирования вызова Awake, если вы перезагрузите сцену этим объектом. Два способа справиться с этим:

  • Есть сцена, посвященная статической инициализации. Поместите все ваши постоянно загруженные скрипты здесь с помощью DontDestroyOnLoad и всегда запускайте приложение с этой сценой.
  • Храните статическую ссылку на первый инициализированный объект. Уничтожьте себя в Awake, если экземпляр уже существует.

Пример для второго варианта:

static private MyClass instance = null; 
void Awake() { 
    if (instance != null) { 
     Destroy(this); 
    } 
    instance = this; 
} 
0

Вы можете поместить свой первый контроллер человек (на самом деле, весь ваш плеер, если вам нравится) в сборных.

Тогда вместо имеющих экземпляра из сборных в сцене, написать компонент Spawner с ссылкой к панэльным. Спайдер может проверить (в Awake), если контроллер первого лица уже существует, и только создайте экземпляр сборника, если он еще не существует.

0

Я знаю, что это более старое сообщение, но оно в нескольких лучших результатах Google, когда я искал способ автоматического создания статического GameObject в единстве. не уверен в более старых версиях, но это работает безупречно с 5.6.1. Мне нужен был способ хранения настроек игры и доступа к ним из многих сцен. Я также нуждался в доступе к определенным функциям единства (например, res экрана и т. Д.), Которые доступны только из MonoBehaviour, поэтому простой статический класс не был вариантом. то, что я придумал, - это в основном однопользовательское единство GameObject, что, если вы получаете ссылку на экземпляр, и нет ни одного из них в сцене, он автоматически создает его. если он существует (сменяется обратно на сцену, где он был создан), дубликат самоуничтожается, так что в игре есть только один из них.

Причина, по которой я хотел этого, заключалась в том, что я использую Unity ScriptableObjects для хранения данных, поскольку они могут быть отредактированы инспектором как во время редактирования, так и во время выполнения, а изменения во время выполнения не возвращаются (очень удобно, если вы работаете со старым OnGUI, вы можете сохранить местоположения прямоугольника в объекте, доступном для сценариев, и следить за тем, чтобы ваши элементы управления перемещались во время выполнения, и места не восстанавливаются при остановленном режиме воспроизведения)

это мой самый базовый класс (удалены мои конкретные данные из него)

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() 
     { 

     } 
    } 

теперь все вы делаете это добавить ваши общедоступные данные (строки, INT, и т.д.), как государственные, не являющиеся статические члены класса GameSettings и просто использовать _settings.MemberName для получить доступ к данным.

надеюсь, что это поможет кому-то искать способ автоматического создания GameObjects на лету. Это также работает, если вы создаете Prefab и привязываете этот скрипт к любому из его объектов. Может быть удобно для автоматического создания элементов пользовательского интерфейса «на лету» в определенных сценах.

Если вам это нужно только в одной сцене и не нужно, чтобы он сохранялся на разных уровнях нагрузки (например, автоматическое создание определенных элементов пользовательского интерфейса в определенных сценах, таких как npc-диалог и т. Д.), Просто удалите DontDestroyOnLoad из функции запуска класс, прикрепленный к сборке.