Как сделать объект static unity

Обновлено: 08.07.2024

В редакторе Unity вы изменяете свойства Компонента используя окно Inspector. Так, например, изменения позиции компонента Transform приведет к изменению позиции игрового объекта. Аналогично, вы можете изменить цвет материала компонента Renderer или массу твёрдого тела (RigidBody) с соответствующим влиянием на отображение или поведение игрового объекта. По большей части скрипты также изменяют свойства компонентов для управления игровыми объектами. Разница, однако, в том, что скрипт может изменять значение свойства постепенно со временем или по получению ввода от пользователя. За счет изменения, создания и уничтожения объектов в заданное время может быть реализован любой игровой процесс.

Обращение к компонентам

В UnityScript синтаксис немного отличается:

Как только у вас есть ссылка на экземпляр компонента, вы можете устанавливать значения его свойств, тех же, которые вы можете изменить в окне Inspector:

Дополнительная возможность, недоступная в окне Inspector – вызов функций экземпляра компонента:

Имейте ввиду, что нет причины, по которой вы не можете иметь больше одного пользовательского скрипта, присоединенного к одному и тому же объекту. Если вам нужно обратиться к одному скрипту из другого, вы можете использовать, как обычно, GetComponent, используя при этом имя класса скрипта (или имя файла), чтобы указать какой тип Компонента вам нужен.

Если вы попытаетесь извлечь Компонент, который не был добавлен к Игровому Объекту, тогда GetComponent вернет null; возникнет ошибка пустой ссылки при выполнении (null reference error at runtime), если вы попытаетесь изменить какие-либо значения у пустого объекта.

Обращение к другим объектам

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

Связывание объектов через переменные

Самый простой способ найти нужный игровой объект – добавить в скрипт переменную типа GameObject с уровнем доступа public:

Переменная будет видна в окне Inspector, как и любые другие:


Теперь вы можете перетащить объект со сцены или из панели Hierarchy в эту переменную, чтобы назначить его. Функция GetComponent и доступ к переменным компонента доступны как для этого объекта, так и для других, то есть вы можете использовать следующий код:

Кроме того, если объявить переменную с доступом public и заданным типом компонента в вашем скрипте, вы сможете перетащить любой объект, который содержит присоединенный компонент такого типа. Это позволит обращаться к компоненту напрямую, а не через игровой объект.

Соединение объектов через переменные наиболее полезно, когда вы имеете дело с отдельными объектами, имеющими постоянную связь. Вы можете использовать массив для хранения связи с несколькими объектами одного типа, но связи все равно должны быть заданы в редакторе Unity, а не во время выполнения. Часто удобно находить объекты во время выполнения, и Unity предоставляет два основных способа сделать это, описанных ниже.

Нахождение дочерних объектов

Иногда игровая сцена может использовать несколько объектов одного типа, таких как враги, путевые точки и препятствия. Может возникнуть необходимость отслеживания их в определенном скрипте, который управляет или реагирует на них (например, все путевые точки могут потребоваться для скрипта поиска пути). Можно использовать переменные для связывания этих объектов, но это сделает процесс проектирования утомительным, если каждую новую путевую точку нужно будет перетащить в переменную в скрипте. Аналогично, при удалении путевой точки придется удалять ссылку на отсутствующий объект. В случаях, наподобие этого, чаще всего удобно управлять набором объектов, сделав их дочерними одного родительского объекта. Дочерние объекты могут быть получены, используя компонент Transform родителя (так как все игровые объекты неявно содержат Transform):

Вы можете также найти заданный дочерний объект по имени, используя функцию Transform.Find:

Это может быть полезно, когда объект содержит дочерний элемент, который может быть добавлен или удален в игровом процессе. Хороший пример – оружие, которое может быть подобрано и выброшено.

I’m creating a game that have multiples references to scripts, one to another.

  1. Controller script
  2. SomeBehavior script
  3. GUI script

My doubt enter when I can do two different things:

    In SomeBehavior access/edit GUI variable/function that I whant. Like:

1.1. variable = GameObject.Find("GuiTag").GetComponent ();
variable.score. and go on.

In SomeBehavior access/edit GUI variable/function by Controller.gui (gui a public variable on controller script). Centralization all the base scripts to one, in that way, having less variables in the scripts, less memory (perraps).

2.1. variable = GameObject.Find("ControllerTag").GetComponent ();
variable.gui.score.

Which one is better?

Создан 29 сен. 13 2013-09-29 13:26:14 user2828407

1 ответ

In the Scripts that you will only have one of you can set a public static variable in that class with a public get and private set. On the Start or Awake function you set that variable to this and then you can access that script easily from any other scripts.

Создан 29 сен. 13 2013-09-29 20:57:26 Shredder2500


Два основных компонента у объекта в Unity3D — это Transform и GameObject.

GameObject

GameObject — основа, контейнер, который содержит в себе все компоненты любой объект в Unity3D. Чтобы удалить, к примеру, игровой объект — удалять нужно именно GameObject этого объекта. Для доступа к GameObject — используется переменная, которая присутствует по умолчанию в любом скрипте, унаследованном от MonoBehaviour (то есть в любом скрипте, созданном через Unity3D).

Получение ссылки на игровой объект

Данным способом можно из одного скрипта получить ссылку на другие игровые объекты и управлять ими, их дочерними объектами, а также их компонентами.

Уничтожение игрового объекта

Данным способом можно удалить игровой объект.

Активация/деактивация игрового объекта

Деактивация объекта аналогична снятия галочки инспекторе Unity3D, которая обведена красным цветом на скриншоте ниже.


Деактивация элемента деактивирует также все его дочерние объекты и останавливает выполнение в их скриптов.

Добавление новых компонентов и скриптов игровому объекту

Таким образом можно добавить абсолютно любой компонент, либо скрипт, который можно добавить в редакторе Unity3D.

Получение доступа к компоненту игрового объекта

Таким же образом можно получить доступ к любому компоненту игрового объекта.

Переименование игрового объекта. Считывание имени объекта

Сделать объект статичным

Данный код аналогичен установке/снятию галочки в редакторе Unity3D (на скрине ниже).


Установить слои игровому объекту, а также считать их

Установить тэг игровому объекту, а также его считывание

Transform

Это единственные компонент, который невозможно удалить из GameObject.

Изменение положение объекта

За положение объекта на сцене отвечает элементы transform.position и transform.localPosition.

Они оба являются переменной типа Vector3 и имеют в себе 3 главных составляющих x,y и z, которые соответствуют координатам в трехмерном пространстве. Следует учитывать, что x, y и z невозможно менять напрямую — они только для чтения. Чтобы добавить единичку к x — нужно добавить к самому transform.position новый Vector3, который равен (1,0,0), что добавить к x единицу, а к y и z — нули.

Чем же отличаются transform.position и transform.localPosition?

Движение объекта

Сначала рассмотрим элементарные варианты.

Как мы уже говорили — position (буду далее использовать именно его, так как отличия от localPosition только в том, относительно чего эти координаты) является переменной типа Vector3. Поэтому для его изменения нужно либо прибавить к нему другой вектор, либо вычесть другой вектор, либо заменить его другим вектором.

Рекомендуется использовать функцию transform.Translate.

Это уже не переменная, как transform.position — это функция. У неё есть два входящих параметра:

  1. Vector3, который отвечает за то, в каком направлении будет двигаться объект;
  2. Space.Self/Space.World — то, относительно чего будет двигаться игровой объект. Space.Self — аналогичен transform.localPosition, а Space.World — аналогичен transform.position.

Вращение объекта

За вращение объекта отвечает компонент transform.rotation, transform.localRotation и функция transform.Rotate.

Здесь все аналогично transform.position. Кроме одного, несмотря на то, что в редакторе Unity3D Rotation представляет собой Vector3, то есть вращение относительно оси X, оси Y, оси Z. Но в коде оно представлено в виде кватернионов. Что такое кватернион — отдельная история. И обычно её изучают в вузах. По факту — знание кватернионов не обязательно для разработки игр. К счастью разработчики Unity3D это понимают и сделали две удобные для программистов вещи:

  1. Функция transform.Rotate(Vector3 vector, Space.World(либо Self));
  2. Функция Quaternion.Euler(float x,float y,float z), которая как раз возвращает кватернион;

Меньше слов — больше кода:

Вместо rotation можно применять localRotation, аналогично position.

Такой подход аналогичен transform.Translate и также является более производительным.

Поиск других объектов на сцене

Есть два подхода поиска объекта на сцене.

Также можно запрашивать дочерние элементы по их номеру:

Также дочерний элемент может запросить родительский, а также родительский родительского и так далее:

12 комментариев для “Скрипты в Unity3D. Урок 0. Основы”

Отличный урок! Планируется ли продолжение?

Здравствуйте! Да, продолжение планируется и уже есть заготовки, но времени, увы, нет совсем =(

Присоединяюсь к предыдущем комментатору, очень жду продолжения.
Ну и отдельное спасибо за этот урок.

А так-то нормуль, есть что законспектировать.

А вот другой пример:
public GameObject MyGameObject;
Это публичное свойство класса типа GameObject. Сам экземпляр данного класса называется MyGameObject и может быть доступен как и изнутри самого класса, так и из других классов, у которых есть ссылка на данный экземпляр класса.

2) Почему objectBoxCollider с маленькой, а BoxCollider с большой? ObjectBoxCollider — это имя класса, а objectBoxCollider — это его экземпляр..

transform.position += new Vector3(1,0,0); // добавляем к X единице (смещаем на единицу)
transform.position += new Vector3(1,0,2)*Time.deltaTime; // двигаем объект в реальном времени с установленными значениями
по осям х и z

int speed = 5;
void Start()
transform.position += new Vector3(speed,0,0)*Time.deltaTime;//движение по оси х с заданием параметра(скорости) через переменную speed
transform.position += new Vector3(1,0,1)*speed*Time.deltaTime;// движение по заданным осям со скоростью установленной переменной speed

вот типа того бы, с пояснениями и дальнейшим развитием их применения
ещё поподробней бы про кватернионы и ейлеры, каким образом кватернион вывести в вектор3
про ригидбоди — нет нигде информации, как ограничивать угол поворота по осям,матф.кламп
как использовать драг по разным осям с разным значением
гравитация и енерция их ограничения и направления,
почему объект в вертикальном положении может подвергаться гравитации а в горизонтальном уже нет..+-

Отдельное спасибо за темы для новых статей.

Спасибо очень сильно помог, ещё раз большое спасибо.

есть vector3 как взять по нему gameObject?

Здравствуйте. К сожалению никак. Vector3 это структура данных, которая содержит информацию о точках X,Y,Z.
Vector3, как и Vector2 стоит рассматривать наравне с int, string, bool, float..

Например. Контейнер gameObject всегда содержит ссылку на компонент (обязательный) transform.
А transform содержит много свойств, отвечающих за позицию и размер объекта на сцене. Одно из свойств, как раз position — является Vector3.

Через любой компонент можно получить ссылку на gameObject, как и через gameObject можно получить ссылку на любой компонент, который данный gameObject содержит внутри себя.
Например: var boxColl >();
Но Vector3 не является компонентом в Unity3D.

Являются компонентами только те объекты, которые можно добавить к gameObject’у, используя графический интерфейс редактора Unity3D.

Спасибо за хорошо изложенную информацию) Сделал по туторам три простеньких игру, просто повторяя все за автором курса. Но во многое не въехал. Тут почитал, многое встало на свои места сразу. У вас талант к ясному изложению. Не бросайте это дело)

Вчера я написал небольшой скрипт, но он не работает. (Сериализованные поля не отображаются в единстве и несколько ошибок, например, я не могу использовать ссылку на нестатический элемент (сериализующее поле)). Не могли бы вы мне помочь, пожалуйста.

Это должно сработать. Я думаю, что вы не можете использовать static, если хотите выставить что-то в Редактор.

Редактировать:

image showing the debug view

Edit2:

Объяснение того, что делает Serializeable, взято из документации единства.

В этой статье попробуем разобрать что такое Scriptable object, зачем они нужны и как их использовать.

Файлы и данные

Работать с файлами в редакторе unity достаточно просто. Каждый файл отображает только свои параметры, если это изображение, то мы видим настройки разрешения, детализации и тд, если это текст, то мы можем увидеть, что написано в нем, а если это 3D модель, то можем увидеть ее в окошке Preview и даже покрутить. Все это конечно удобно, но что если нам понадобится особый объект который мог бы сочетать в себе несколько типов данных одновременно, к примеру сделать так, чтобы в одном файле хранилась и картинка и, допустим, текст с ее описанием? Для решения этой проблемы и был введен особый тип объектов в unity – Scriptable object.

Scriptable object (скриптовый объект) это по сути, объект определенного типа, который может хранить пользовательские данные любого типа в виде файла. Для тех кто знаком немного с сериализацией, может возникнуть небольшое противоречие, ведь зачем мне скриптовый объект, если я и так смогу посредством сериализации сохранить и картинку и текст, и что угодно в любой файл!? Дело в том что скриптовый объект работает по такому же принципу как и любой другой объект в unity, за счет чего между ними сохраняется взаимосвязь, где вам не нужно создавать дополнительные, специальные инструменты для того, чтобы разные объекты могли взаимодействовать со скриптовый объектом.

Попробуем на примере разобрать, как выглядят скриптовые объекты и чем они отличаются от любых других объектов unity. Создадим простой скрипт ImageData, который будет обычным классом и хранить в себе изображение Sprite, и текст с его описанием.

  1. publicsealedclass ImageData
  2. public Sprite image ;
  3. publicstring description = “Description here” ;
  4. >

Если создать экземпляр данного класса с помощью оператора new :

ImageData data = new ImageData ();

то этот экземпляр будет существовать только в оперативной памяти компьютера до тех пор, пока программа не завершит свою работу, после чего память очистится и объект ImageData будет уничтожен. Чтобы можно было постоянно хранить этот объект в проекте после создания, необходимо унаследовать ImageData от класса ScriptableObject и создать уже не просто “виртуальный” экземпляр объекта, а его постоянную форму в виде файла.

  1. publicsealedclass ImageData : ScriptableObject
  2. public Sprite image ;
  3. publicstring description = “Description here” ;
  4. >

Создавать экземпляры скриптовых объектов можно вызвав статический метод CreateInstance класса ScriptableObject. Выполнять это действие необходимо только в редакторе, для чего воспользуемся методами “быстрого” доступа – это статические методы, которые вызываются с помощью контекстного меню внутри редактора.

Атрибут MenuItem добавит статический метод CreateImageData в специальное контекстное меню которое будет доступно в разделе Assets -> Create -> New image data instance.


В самом методе создадим экземпляр скриптового объекта ImageData.

При вызове статического метода CreateInstance, в скобки передается тип создаваемого объекта, в нашем случае это тип ImageData. После того как экземпляр создан, необходимо его сохранить в проекте, для чего воспользуемся специальным классом по работе с ассетами в редакторе – AssetDatabase и его статичеким методом CreateAsset для сохранения объектов в виде файла.

В метод CreateAsset передаем объект ImageData, который необходимо создать и указываем путь, где он будет создан, в данном случае объект будет создан в корневой папке Assets. Чтобы протестировать процесс создания скриптового объекта, можно перейти в контекстное меню Assets -> Create -> New image data instance и нажать его.


Теперь в папке Assets у нас появился новый файл скриптового объекта в который мы можем поместить изображение и текст с описанием.


Итак, экземпляр скриптового объекта ImageData перешел из “виртуального” вида и хранится теперь в постоянной памяти вместо оперативной. Этот файл мы можем редактировать, удалять, перемещать и тд, в каком то смысле теперь объект стал “осязаем”, что намного облегчает работу с ним. Самое главное преимущество скриптовых объектов перед другими видами файлов в том, что эти объекты могут хранить самые необходимые данные, точнее – только те, которые вы укажете.

Для сравнения возьмем обычный префаб. Префаб – это сложный GameObject который может содержать в себе другие GameObject’ы, а также кучу компонентов, которые вам могут показаться совершенно бесполезными.


В скриптовом объекте вы указываете только те данные, которые вас интересуют, без лишних компонентов и других данных, при этом сохраняются все возможности работы со скриптовым объектом как и с любым другим unity объектом.


Во вторых – скриптовые объекты очень хорошо оптимизируют процесс работы игры, тем что отлично экономят память, когда большое кол-во объектов ссылаются на одни и те же данные.

К примеру: на сцене есть 1000 GameObject’ов, у каждого объекта есть компонент, в котором необходимо указать ссылку на изображение, ее размеры Vector2 и текст с ее описанием, в этом случае все 1000 объектов будут создавать свои уникальные ссылки на эти данные, что в общем кол-ве будет давать 3000 (1000 объектов умножить на 3 вида данных) уникальных ссылок, что совершенно не нужно, так как достаточно просто создать один скриптовый объект со всеми этими данными и передавать в компонент одну ссылку на скриптовый объект вместо 3х.

И в третьих – заменяемость. Для создания копий экземпляра скриптового объекта, достаточно использовать Instantiate, как и при создании копии любого префаба, после чего получаем абсолютно новую и независимую копию объекта.

Использовать скриптовый объекты так же легко как и любые другие объекты в unity.

В примере используется массив скриптовых объектов, чтобы переключать изображения по щелчку мыши. Панель UI с изображениями на сцене одна как и текст с описанием, а компонент, в свою очередь, просто имеет ссылки на скриптовые объекты с другими изображениями и описаниями к ним.


В самом компоненте, для получения ссылок на скриптовые объекты необходимо просто указать тип ImageData.

  1. publicsealedclass ImageControl : MonoBehaviour
  2. public ImageData [] data = new ImageData [ 5 ];
  3. >

Мы уже разобрали способ создания скриптовых объектов через статический метод. Есть еще один способ создания экземпляров скриптовых объектов – через специальный атрибут CreateAssetMenu .

  1. [ CreateAssetMenu ( fileName = “New image data” , menuName = “New image data” , order = 0 )]
  2. publicsealedclass ImageData : ScriptableObject
  3. public Sprite image ;
  4. publicstring description = “Description here” ;
  5. >

Результат будет такой же, как если бы создавали через статический метод контекстного меню. Достаточно просто поместить данный атрибут вверху класса ImageData, после чего указать название файла при создании и места, где будет располагаться его контекстное меню. В данном случае там же в Assets -> Create -> New image data. Единственный недостаток такого решения в том, что нельзя будет указать место создания файла, по умолчанию это будет корневая папка Assets.

Скриптовые объекты и ООП

В начале статьи мы разбирали простой класс ImageData, который еще не был унаследован от ScriptableObject, и создавали экземпляры данного класса с помощью оператора new. Экземпляры скриптовых объектов также можно создавать с помощью этого оператора.

К примеру, усовершенствуем немного класс ImageData и добавим ему конструктор, в котором будет указывать изображение и текст с описанием.

Теперь можно создать экземпляр класса ImageData использую его конструктор.

  1. Sprite image ;
  2. string description ;
  3. ImageData data = new ImageData ( image, description );

Данная конструкция создает “виртуальный” экземпляр скриптового объекта, это именно то, с чем мы боролись использую скриптовые объект – перейти от “виртуального” типа к “физическому”. Хотя такая конструкция создания очень удобная при создании сложных экземпляров, сохранять такие экземпляры нельзя. Для решения данной проблемы необходимо поместить “виртуальный” экземпляр в “физический” шаблон, созданный через статический метод CreateInstance.

В методе CreateImageData создается новый экземпляр скриптового объекта ImageData, только в этот раз с помощью оператора new. После чего экземпляр передаем в метод SaveInstance для сохранения его в виде постоянного файла. Так как сохранять “виртуальные” экземпляры не получится, необходимо создать его “физический” шаблон скриптового объекта такого же типа как и оригинал, после чего просто передать на него ссылку и сохранить.

В переменную saveObject помещаем новый “физический” шаблон такого же типа как и оригинал, для этого в новом статическом метод CreateInstance указываем тип передаваемого объекта, вызвав его метод GetType.

После создания шаблона, достаточно передать ему ссылку на оригинал после чего можно сохранять объект в виде файла в проекте при помощи AssetDataBase.

Скриптовые объекты могут вам очень пригодится когда необходимо создать постоянную базу данных в виде файла, которую удобно редактировать, перемещать и передавать другим объектам. Эти объекты одновременно совмещают два способа работы: программный – на уровне кода, и файловый.

Производительность игры может очень важна, так как она позволяет охватывать множество платформ, в том числе низкопроизводительные. Jonathan Gonzalez делится секретам из собственного опыта, как сделать игру без багов и с нормальным fps.

Чаще всего довольно индивидуальный процесс, но есть общие пункты, на которые стоит обратить внимание.

Чем проще, тем лучше

Когда вы разрабатываете игру, вам нужно конкретно обозначить, что вам нужно включать и что не нужно.
Jonathan возвращается к старым скриптам или проектам и найти способы сделать что-то продуктивнее и проще.
Если же вы делаете игру впервые, всё равно помните об этом пункте, но не слишком ограничивайте себя.

Используйте Profiler

Прежде чем вы начнете удалять строки кода, очищать ненужные файлы и пытаться сделать все, что вам нужно, необходимо знать, что на самом деле вызывает проблемы с производительностью.
Profiler – отличный способ получить подробный обзор того, как ваша игра работает. Ищите его тут: Window>Profiler.

Во время игры вы должны держать это окно видимым. Он будет отображать такие категории нагрузку на CPU и GPU, рендеринг, физику, аудио и другое.

Правильно задавайте тип объекта

Уменьшение разрешения и повторное использование текстур.

Множество текстур с высоким разрешением замедлят производительность. Текстуры нужно использовать правильно и по возможности объединять несколько объектов в одну большую текстуру.
Это обычная практика в AAA-играх. Таким образом вы можете уменьшить количество используемых текстурных карт, и упростить организацию. Например, игра Rage and Doom, с использованием Megatextures и виртуального текстурирования.

Используйте ограничение в рендере.

Мы можем сказать Unity не визуализировать объекты, которые скрыты. Это позволяет нам только визуализировать объекты, на которые у нас есть прямая видимость. Нет причин для рендеринга объекта в дальнем конце обзора нашей камеры, если мы не сможем увидеть его напрямую.
Для этого вы можете использовать Frustum Culling, Occlusion Culling и SECTR VIS.

Оптимизируйте видимые объекты.

LODs (Levels Of Detail) – способ рендеринга low poly сетки, когда она находится за пределами определенного расстояния.
MipMaps – это аналог LODs для текстур. Чем дальше текстура от камеры, тем меньше в нём разрешения.

Используйте правильные параметры сжатия и загрузки для аудио.


Unity поддерживает несколько типов аудио, по умолчанию он будет импортировать аудиоклипы для использования типа загрузки Decompress On Load вместе со сжатием Vorbis.

Для одного зацикливающегося аудиоклипа импортируемый размер составляет 3,3 МБ, что значительно увеличивает память, необходимую для нашей игры. Исходный размер – это количество ram, которое потребуется для воспроизведения этого клипа.
Звуковые эффекты обычно короткие и, следовательно, имеют небольшие требования к памяти. Для них настройка Decompress on Load будет работать лучше всего, но тип сжатия должен быть либо PCM, либо ADPCM. PCM обеспечивает более высокое качество, но поставляется с большим размером файла, что отлично подходит для очень короткого, но важного звукового эффекта. ADPCM имеет коэффициент сжатия в 3,5 раза меньше, чем PCM, и лучше всего используется для аудиоэффектов, которые используются очень часто, таких как шаги, удары, оружие и т. Д.
Для более длинных аудиоклипов, таких как фоновая музыка или другие большие файлы, лучше использовать сжатым в памяти, что приводит к распаковке файла прямо перед воспроизведением. Потоковая передача (streaming) – еще один вариант. Согласно документам Unity, потоковая передача использует минимальный объем памяти для хранения сжатых данных, которые затем постепенно считываются с диска.

Оптимизация физических вычислений.


В Unity вы можете использовать несколько разных коллайдеров, такие как box colliders, capsule colliders, mesh colliders, и различные 2D colliders. По возможности используйте примитивные коллайдеры. Это ваши основные формы для коллайдеров, такие как коробка, сфера или капсула.
Mesh Colliders принимают форму какой-либо сетки, которую вы указываете. Примером этого может служить человеческий персонаж с коллайдером, который соответствует их форме. Его следует избегать, если это возможно. Если без этого никак, создайте низкополигональную версию сетки и назначьте Mesh Colliders.

Rigidbodies обычно используются для добавления веса к объекту. Если объект привязан к Rigidbody, он может зависеть от физики, такой как сила тяжести других сил. Важно отметить, что слишком много объектов Rigidbody, это повлияет на производительность отрицательно.

Читайте также: