unity instance что это
Object.Instantiate
Success!
Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.
Submission failed
For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.
Declaration
Declaration
Declaration
Declaration
Declaration
Parameters
original | An existing object that you want to make a copy of. |
position | Position for the new object. |
rotation | Orientation of the new object. |
parent | Parent that will be assigned to the new object. |
instantiateInWorldSpace | When you assign a parent Object, pass true to position the new object directly in world space. Pass false to set the Object’s position relative to its new parent.. |
Returns
Object The instantiated clone.
Description
Clones the object original and returns the clone.
This function makes a copy of an object in a similar way to the Duplicate command in the editor. If you are cloning a GameObject you can specify its position and rotation (these default to the original GameObject’s position and rotation otherwise). If you are cloning a Component the GameObject it is attached to is also cloned, again with an optional position and rotation.
When you clone a GameObject or Component, all child objects and components are also cloned with their properties set like those of the original object.
By default the parent of the new object is null; it is not a «sibling» of the original. However, you can still set the parent using the overloaded methods. If a parent is specified and no position and rotation are specified, the original object’s position and rotation are used for the cloned object’s local position and rotation, or its world position and rotation if the instantiateInWorldSpace parameter is true. If the position and rotation are specified, they are used as the object’s position and rotation in world space.
The active status of a GameObject at the time of cloning is maintained, so if the original is inactive the clone is created in an inactive state too. Additionally for the object and all child objects in the hierarchy, each of their Monobehaviours and Components will have their Awake and OnEnable methods called only if they are active in the hierarchy at the time of this method call.
These methods do not create a prefab connection to the new instantiated object. Creating objects with a prefab connection can be achieved using PrefabUtility.InstantiatePrefab.
Instantiate can be used to create new objects at runtime. Examples include objects used for projectiles, or particle systems for explosion effects.
Instantiate can also clone script instances directly. The entire game object hierarchy will be cloned and the cloned script instance will be returned.
After cloning an object you can also use GetComponent to set properties on a specific component attached to the cloned object.
Object.Instantiate
Успех!
Благодарим вас за то, что вы помогаете нам улучшить качество документации по Unity. Однако, мы не можем принять любой перевод. Мы проверяем каждый предложенный вами вариант перевода и принимаем его только если он соответствует оригиналу.
Ошибка внесения изменений
По определённым причинам предложенный вами перевод не может быть принят. Пожалуйста попробуйте снова через пару минут. И выражаем вам свою благодарность за то, что вы уделяете время, чтобы улучшить документацию по Unity.
Параметры
original | An existing object that you want to make a copy of. |
position | Position for the new object (default Vector3.zero). |
rotation | Orientation of the new object (default Quaternion.identity). |
Возврат значений
Object A clone of the original object.
Описание
This function makes a clone of an object in a similar way to the Duplicate command in the editor. If you are cloning a GameObject, or something attached to a GameObject, then you can also optionally specify its position and rotation.
If you are cloning a Component, then the GameObject it is attached to will also be cloned.
When you clone a GameObject or Component, all child objects and components will also be cloned, along with their properties. However, the parent property of the cloned object will be null, so it will not be part of the object hierarchy of the original.
The active status of a GameObject at the time of cloning will be passed, so if the original is inactive then the clone will be created in an inactive state too.
For an in-depth tutorial of Instantiate and its uses, visit: In depth Prefab Instantiate discussion.
In this example, we instantiate 10 copies of a prefab object in a line along the x axis.
Instantiate can also clone script instances directly. The game object hierarchy will be cloned and the cloned script instance will be returned.
After cloning an object you can also use GetComponent to set properties on a specific component attached to the cloned object.
Instantiating Prefabs at run time
Prefabs come in very handy when you want to instantiate complicated GameObjects or collections of GameObjects at run time. Compared with creating GameObjects from scratch using code, instantiating Prefabs using code has many advantages because you can:
Instantiate a Prefab using one line of code. Creating equivalent GameObjects from scratch requires many more lines of code.
Set up, test, and modify the Prefab quickly and easily using the Scene view, Hierarchy and Inspector.
Change which Prefab is instantiated without changing the code. You can make a simple rocket into a super-charged rocket, without any code changes.
Note: You can download a Unity Project containing all the examples on this page, here:
Basics of instantiating a Prefab
To instantiate a Prefab at run time, your code needs a reference to that Prefab. You can make this reference by creating a public variable in your code to hold the Prefab reference. The public variable in your code appears as an assignable field in the Inspector. You can then assign the actual Prefab you want to use in the Inspector.
The script example below has a single public variable, “myPrefab”, that is a reference to a Prefab. It creates an instance of that Prefab in the Start() method.
Чтобы использовать этот пример:
Create a new C# script in your Project, and name it “InstantiationExample”.
Copy and paste in the script example above into your new script, and save it.
Create an empty GameObject using the menu GameObject > Create Empty.
Add the script to the new GameObject as a component by dragging it onto the empty GameObject.
Create any Prefab, and drag it from the Project window into the My Prefab field in the script component.
Dragging a Prefab from the Project window into the My Prefab field in the script component
When you start Play Mode, you should see your Prefab instantiate at position (0, 0, 0) in the Scene.
You can drag a different Prefab into the My Prefab field in the Inspector to change which Prefab is instantiated, without having to change the script.
Because this first example is very simple, it may not seem to provide any advantage over just placing a Prefab into the Scene yourself. However, being able to instantiate Prefabs using code provides you with powerful abilities to dynamically create complex configurations of GameObjects while your game or app is running, as shown in the following examples.
Common scenarios
To illustrate the strength of instantiating Prefabs at run time, here are some basic situations where they are useful:
Building a structure out of a single Prefab by replicating it multiple times in different positions, for example in a grid or circle formation.
Firing a projectile Prefab from a launcher. The projectile Prefab could be a complex configuration containing a Mesh, Rigidbody, Collider, AudioSource, Dynamic Light, and a child GameObject with its own trail Particle System.
A vehicle, building or character, for example a robot, breaking apart into many pieces. In this scenario, the example script deletes and replaces the complete, operational robot Prefab with a wrecked robot Prefab. This wrecked Prefab consists of separate broken parts of the robot, each set up with Rigidbodies and Particle Systems of their own. This technique allows you to blow up a robot into many pieces, with just one line of code, which replaces the original GameObject with a wrecked Prefab.
The following sections show you how to implement these scenarios.
Building a structure
You can use code to create many copies of a Prefab in a particular configuration almost instantaneously. Using code to generate structures like this is called procedural generation. The example below creates a wall of block instances.
To try this example, create the script below, name it Wall, and place it on an empty GameObject in your Scene.
When you have done this, you should see the Block variable in the Inspector, with the word None in the field. A value of “None” means that no Prefab has been assigned to this variable yet.
The Block variable, with no Prefab assigned yet
The example script above won’t work until you assign a Prefab to the Block variable. To create a simple block Prefab:
Choose GameObject > 3D Object > Cube.
Drag the cube from the Hierarchy window into the Assets folder in the Project window. This creates a Prefab Asset.
Rename your Prefab to “Block”.
Now that your Block Prefab exists as an Asset, you can safely delete the cube from your Hierarchy.
Now that you have created a Block Prefab, you can assign it to the Block variable. Select your original GameObject (the one with the “Wall” script attached to it). Then drag the “Block” Prefab from the Project window into the “Block” variable slot (where it says “None”).
The Block variable, with the Block Prefab assigned to it
When you have finished this set-up, click Play and you’ll see that Unity builds the wall using the Prefab:
A wall built from 4 rows of 10 blocks, as generated by the example above.
This is a flexible workflow pattern that you can use over and over again in Unity. Because you are using a Prefab in this script, you can easily replace or edit the Prefab to modify the properties of the bricks in the wall, without needing to touch the script. You can also use your Wall script on other GameObjects in your Scene with different Prefabs assigned to them to have various walls made from different types of Prefab.
You can use code to place a GameObject in a grid, in circle pattern, randomly scattered, or any other configurations that you can think of to fit whatever game or app you are creating. Here’s another example showing how to place instances in a circular formation:
A circular arrangement of blocks, as generated by the example above
Instantiating projectiles & explosions
A “Launcher” GameObject instantiates a projectile Prefab when the player presses the fire button. The Prefab contains a mesh, a Rigidbody, and a Collider, so it can fly through the air and detect when a collision occurs.
The projectile collides with something and instantiates an explosion Prefab. The explosion Prefab contains a Particle System effect and a script that applies a force to surrounding GameObjects.
In the same way as the Block Prefab above, you can instantiate the projectile in just one line of code, no matter how complex the projectile Prefab is. After instantiating the Prefab, you can also modify any properties of the instantiated GameObject. For example, you can set the velocity of the projectile’s Rigidbody.
As well as being easier to use, you can modify the Prefab later on without touching the code. So if your projectile is a rocket, later on you could add a Particle System to it to make it leave a cloud trail. After you do this, all your instantiated rockets have particle trails.
This script shows how to launch a projectile using the Instantiate() function.
In the code, the Prefab variable type is a Rigidbody, and not GameObject. This has two useful effects:
Only GameObjects that have a Rigidbody component can be assigned to this variable. This is useful because it helps make sure you’re assigning the correct GameObject to the variable.
The Instantiate method returns a reference to the Rigidbody component on the new instance. This is useful because it makes it simple to set the velocity of the Rigidbody immediately after instantiating it.
When making a public Prefab variable, the variable type can be a GameObject, or it can be any valid Component type (either a built-in Unity component or one of your own MonoBehaviour script).
For GameObject type variables, you can assign any GameObject to the variable, and the Instantiate function returns a reference to the new GameObject instance.
For component type variables (such as Rigidbody, Collider, and Light), you can only assign GameObjects of that component type to the variable, and the Instantiate function returns a reference to that specific component on the new GameObject instance.
The following script (placed on the projectile Prefab) performs the action of instantiating the explosion at the projectile’s current position and removing the projectile GameObject when the projectile collides with something.
An example of projectile Prefabs being instantiated, and replaced with explosion Prefabs when they impact
Notice in the image above, which shows the scripts running in Play mode, the instantiated GameObjects appear in the Hierarchy, with the word “(Clone)” appended to the name.
Replacing a character with a ragdoll or wreck
Often in games, you might want to switch a character, vehicle, building or other Asset from an “intact” state to a “destroyed” state. Rather than trying to modify the intact version of the GameObject (such as removing scripts, adding Rigidbody components and so on), it’s often much more efficient and effective to delete the entire intact GameObject and replace it with an instantiated destroyed Prefab. This gives you a lot of flexibility. You could use a different Material for the destroyed version, attach completely different scripts, or instantiate a Prefab containing the GameObject broken into many pieces to simulate a wrecked and shattered version of the original GameObject. Any of these options can be achieved with a single call to Instantiate(), to bring your destroyed version into the Scene, while deleting the original.
Most importantly, you can create the destroyed version which you Instantiate() with completely different GameObjects compared to the original. For example, to create a breakable robot, you would model two versions: one that consists of a single GameObject with Mesh Renderer
and scripts for robot movement, and the other that consists of several skeletal parts that can be controlled individually by physics. Your game runs faster when using the model with just one GameObject, because the model contains fewer triangles and so it renders faster than the robot that has many small parts. Also while your robot is happily walking around, there is no reason to have it in separate parts.
To build a wrecked robot Prefab, you could:
Model your robot with lots of different skeletal parts in your favorite 3D modeling software, and export it into the Assets folder of your Unity Project.
Create an empty Scene in the Unity Editor.
Drag the model from the Project window into the empty Scene.
Add Rigidbodies to all parts, by selecting all the parts and choosing Component > Physics > Rigidbody.
Add Colliders to all parts by selecting all the parts and choosing Component > Physics > Mesh Collider (enable the Convex option for faster performance).
Make sure you parent all the parts of your wrecked robot to a single root GameObject.
For an extra special effect, add a smoke-like Particle System as a child GameObject to each of the parts.
Now you have a robot with multiple explodable parts. The parts can fall to the ground because they are controlled by physics, and each part creates a Particle trail due to the attached Particle System.
Click Play to preview how your model reacts, and make any necessary tweaks.
Drag the root GameObject into the Assets folder in the Project window to create a new Prefab.
The following example shows how you can model these steps in code.
An example of a robot Prefab being swapped for a wrecked Prefab when hit by a projectile
Unity: отрисовываем множество полосок здоровья за один drawcall
Недавно мне нужно было решить задачу, достаточно распространённую во многих играх с видом сверху: рендерить на экране целую кучу полосок здоровья врагов. Примерно вот так:
Очевидно, что я хотел сделать это как можно эффективнее, желательно за один вызов отрисовки. Как обычно, прежде чем приступать к работе, я провёл небольшое онлайн-исследование решений других людей, и результаты были очень разными.
Я не буду никого стыдить за код, но достаточно сказать, что некоторые из решений были не совсем блестящими, например, кто-то добавлял к каждому врагу объект Canvas (что очень неэффективно).
Метод, к которому я в результате пришёл, немного отличается от всего того, что я видел у других, и не использует вообще никаких классов UI (в том числе и Canvas), поэтому я решил задокументировать его для общества. А для тех, кто хочет изучить исходный код, я выложил его на Github.
Почему бы не использовать Canvas?
По одному Canvas для каждого врага — это очевидно плохое решение, но я мог использовать общий Canvas для всех врагов; единственный Canvas тоже бы привёл к батчингу вызовов отрисовки.
Однако мне не нравится связанный с таким подходом объём выполняемой в каждом кадре работы. Если вы используете Canvas, то в каждом кадре придётся выполнять следующие операции:
Вкратце о моём решении
Краткое описание процесса моей работы:
Что такое Instancing?
В работе с графикой уже давно используется стандартная техника: несколько объектов объединяются вместе, чтобы они имели общие данные вершин и материалы и их можно было отрендерить за один вызов отрисовки. Нам нужно именно это, потому что каждый вызов отрисовки — это дополнительная нагрузка на ЦП и GPU. Вместо выполнения по одному вызову отрисовки на каждый объект мы рендерим их все одновременно и используем шейдер для добавления вариативности в каждую копию.
Можно делать это вручную, дублируя данные вершин меша X раз в одном буфере, где X — максимальное количество копий, которое может быть отрендерено, а затем использовав массив параметров шейдера для преобразования/окраски/варьирования каждой копии. Каждая копия должна хранить знание о том, каким нумерованным экземпляром она является, чтобы использовать это значение как индекс массива. Затем мы можем использовать индексированный вызов рендера, который приказывает «рендерить только до N», где N — это число экземпляров, которое на самом деле нужно в текущем кадре, меньшее, чем максимальное количество X.
В большинстве современных API код для этого уже есть, поэтому вручную это делать не требуется. Эта операция называется «Instancing»; по сути, она автоматизирует описанный выше процесс с заранее заданными ограничениями.
Движок Unity тоже поддерживает instancing, в нём есть собственный API и набор макросов шейдеров, помогающие в его реализации. Он использует определённые допущения, например, о том, что в каждом экземпляре требуется полное 3D-преобразование. Строго говоря, для 2D-полосок оно нужно не полностью — мы можем обойтись упрощениями, но поскольку они есть, мы будем использовать их. Это упростит наш шейдер, а также обеспечит возможность использования 3D-индикаторов, например, кругов или дуг.
Класс Damageable
Объект HealthBar: позиция/поворот
Объект полосы здоровья очень прост: по сути, это всего лишь прикреплённый к врагу Quad.
Мы используем scale этого объекта, чтобы сделать полоску длинной и тонкой, и разместим её прямо над врагом. Не беспокойтесь о её повороте, мы исправим его с помощью кода, прикреплённого к объекту в HealthBar.cs :
Этот код всегда направляет quad в сторону камеры. Мы можем выполнять изменение размера и поворота в шейдере, но я реализую их здесь по двум причинам.
Во-первых, instancing в Unity всегда использует полный transform каждого объекта, и поскольку мы всё равно передаём все данные, можно их и использовать. Во-вторых, задание масштаба/поворота здесь гарантирует, что ограничивающий параллелограмм для усечения полоски всегда будет верным. Если бы мы сделали задание размера и поворота обязанностью шейдера, то Unity мог бы усекать полоски, которые должны быть видимы, когда они находятся близко к краям экрана, потому что размер и поворот их ограничивающего параллелограмма не будут соответствовать тому, что мы собираемся рендерить. Разумеетсяя, мы могли бы реализовать свой собственный способ усечения, но обычно при возможности лучше использовать то, что у нас есть (код Unity является нативным и имеет доступ к большему количеству пространственных данных, чем мы).
Я объясню, как рендерится полоска, после того, как мы рассмотрим шейдер.
Шейдер HealthBar
В этой версии мы создадим простую классическую красно-зелёную полоску.
Я используют текстуру размером 2×1, с одним зелёным пикселем слева и одним красным справа. Естественно, я отключил mipmapping, фильтрацию и сжатие, а для параметра addressing mode задал значение Clamp — это значит, что пиксели нашей полоски всегда будут идеально зелёными или красными, а не растекутся по краям. Это позволит нам изменять в шейдере координаты текстуры для сдвига линии, разделяющей красный и зелёный пиксели вниз и вверх по полоске.
(Так как здесь всего два цвета, я мог просто использовать в шейдере функцию step для возврата в точке одного или другого. Однако в этом методе удобно то, что при желании можно использовать более сложную текстуру, и это будет работать аналогично, пока переход находится в середине текстуры.)
Для начала мы объявим необходимые нам свойства:
_MainTex — это красно-зелёная текстура, а _Fill — значение от 0 до 1, где 1 — это полное здоровье.
Далее нам нужно приказать полоске рендериться в очереди overlay, а значит, игнорировать всю глубину в сцене и рендериться поверх всего:
Следующая часть — это сам код шейдера. Мы пишем шейдер без освещения (unlit), поэтому нам не нужно беспокоиться об интеграции с различными моделями поверхностных шейдеров Unity, это простая пара вершинного/фрагментного шейдеров. Для начала напишем бутстреппинг:
Вершинная структура должна включать в себя данные экземпляров, поэтому мы сделаем следующее:
Также нам нужно задать, что именно будет находиться в данных экземляров, кроме того, что за нас обрабатывает Unity (transform):
Можно использовать и несколько буферов; это стоит делать, если у вас есть несколько свойств, обновляемых с разной частотой; разделив их, можно, например, не менять один буфер при изменении другого, что более эффективно. Но нам этого не требуется.
UNITY_SETUP_INSTANCE_ID и UNITY_ACCESS_INSTANCED_PROP выполняют всю магию, осуществляя доступ к нужной версии свойства _Fill из буфера констант для этого экземпляра.
Мы знаем, что в обычном состоянии UV-координаты четырёхугольника (quad) покрывают весь интервал текстуры, и что разделительная линия полоски находится посередине текстуры по горизонтали. Поэтому небольшие математические расчёты по горизонтали сдвигают полоску влево или вправо, а значение Clamp текстуры обеспечивают заполнение оставшейся части.
Фрагментный шейдер не мог быть проще, потому что вся работа уже выполнена:
Полный код шейдера с комментариями доступен в репозитории GitHub.
Материал Healthbar
Дальше всё просто — нам всего лишь нужно назначить нашей полоске материал, который использует этот шейдер. Больше почти ничего делать не нужно, достаточно только выбрать нужный шейдер в верхней части, назначить красно-зелёную текстуру, и, что самое важное, поставить флажок «Enable GPU Instancing».
Обновление свойства HealthBar Fill
Если вы ещё не использовали MaterialPropertyBlock для передачи данных в шейдеры, даже без instancing, то вам нужно изучить его. Он не так хорошо объяснён в документации Unity, но является самым эффективным способом передачи данных каждого объекта в шейдеры.
В нашем случае, когда используется instancing, значения для всех полосок здоровья упаковываются в буфер констант, чтобы их можно было передать их все вместе и отрисовать за один раз.
Здесь нет почти ничего, кроме бойлерплейта для задания переменных, и код довольно скучный; подробности см. в репозитории GitHub.
В репозитории GitHub есть тестовое демо, в котором куча злых синих кубиков уничтожается героическими красными сферами (ура!), получая урон, отображаемый описанными в статье полосками. Демо написано в Unity 2018.3.6f1.
Эффект от использования instancing можно наблюдать двумя способами:
Панель Stats
Нажав Play, щёлкните на кнопку Stats над панелью Game. Здесь вы можете увидеть, сколько вызовов отрисовки экономится благодаря instancing (батчингу):
Запустив игру, вы можете нажать на материал HealthBar и снять флажок с «Enable GPU Instancing», после чего число сэкономленных вызовов снизится до нуля.
Отладчик кадров
Запустив игру, перейдите в меню Window > Analysis > Frame Debugger, а затем нажмите в появившемся окне «Enable».
Слева внизу вы увидите все выполняемые операции рендеринга. Заметьте, что пока там есть множество отдельных вызовов для врагов и снарядов (при желании можно реализовать instancing и для них). Если прокрутить до самого низа, то вы увидите пункт «Draw Mesh (instanced) Healthbar».
Этот единственный вызов рендерит все полоски. Если нажать на эту операцию, а затем на операцию над ней, то вы увидите, что все полоски исчезнут, потому что они отрисовываются за один вызов. Если находясь во Frame Debugger, вы снимете у материала флажок «Enable GPU Instancing», то увидите, что одна строка превратилась в несколько, а после установки флажка — снова в одну.