Как сделать рандомный спавн объектов в unity
Перейти к содержимому

Как сделать рандомный спавн объектов в unity

Добавление случайных элементов в игру

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

Выбор случайного элемента в массиве

Выбор случайного элемента массива водится к выбору случайного значения в диапазоне от нуля до максимального значения индекса в массиве (который на 1 меньше длины массива). Это сделать довольно просто, используя встроенный метод Random.Range:-

Учтите, что диапазон, из которого метод Random.Range возвращает значение, включает первый аргумент, но не включает второй аргумент. Так что, если в качестве второго аргумента передавать myArray.Length, вы получите правильный результат.

Выбор элементов с разной вероятностью

Иногда, вам требуется случайно выбрать элементы, но при этом некоторые из них должны выбираться с большей вероятностью, чем другие. Например, NPC может реагировать по-разному при встрече с игроком:-

  • с вероятностью 50% он дружелюбно поприветствует игрока
  • с вероятностью 25% он убежит
  • с вероятностью 20% он немедленно начнёт атаковать
  • с вероятностью 5% он предложит деньги в качестве подарка

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

В коде, кусочек бумажной ленты — это на самом деле массив float чисел, содержащий упорядоченный список вероятностей различных элементов. Случайная точка получается с помощью умножения Random.value на сумму всех float значений в массиве (в сумме они не должны превышать 1; нам важен относительный размер различных значений). Чтобы определить, в какой элемент массива “попала” точка, сперва проверьте не меньше ли она значения первого элемента. Если меньше, тогда первый элемент и выбирается. Иначе, вычтите значение первого элемента массива из значения полученной точки и сравните результат со вторым элементом и так далее, до тех пор, пока не найдётся правильный элемент. В коде это может выглядеть как-то так:-

Заметьте, что в данном случае необходимо наличие последнего оператора возврата, т.к. Random.value может вернуть 1 и тогда поиск никогда не найдёт случайно выбранную точку. Изменение строки

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

Weighting continuous random values

The array of floats method works well if you have discrete outcomes, but there are also situations where you want to produce a more continuous result — say, you want to randomize the number of gold pieces found in a treasure chest, and you want it to be possible to end up with any number between 1 and 100, but to make lower numbers more likely. Using the array-of-floats method to do this would require that you set up an array of 100 floats (i.e. sections on the paper strip) which is unwieldy; and if you aren’t limited to whole numbers but instead want any number in the range, it’s impossible to use that approach.

A better approach for continuous results is to use an AnimationCurve to transform a ‘raw’ random value into a ‘weighted’ one; by drawing different curve shapes, you can produce different weightings. The code is also simpler to write:

A ‘raw’ random value between 0 and 1 is chosen by reading from Random.value. It is then passed to curve.Evaluate(), which treats it as a horizontal coordinate, and returns the corresponding vertical coordinate of the curve at that horizontal position. Shallow parts of the curve have a greater chance of being picked, while steeper parts have a lower chance of being picked.

A linear curve does not weight values at all; the horizontal coordinate is equal to the vertical coordinate for each point on the curve.A linear curve does not weight values at all; the horizontal coordinate is equal to the vertical coordinate for each point on the curve. This curve is shallower at the beginning, and then steeper at the end, so it has a greater chance of low values and a reduced chance of high values. You can see that the height of the curve on the line where x=0.5 is at about 0.25, which means theres a 50% chance of getting a value between 0 and 0.25.This curve is shallower at the beginning, and then steeper at the end, so it has a greater chance of low values and a reduced chance of high values. You can see that the height of the curve on the line where x=0.5 is at about 0.25, which means there’s a 50% chance of getting a value between 0 and 0.25. This curve is shallow at both the beginning and the end, making values close to the extremes more common, and steep in the middle which will make those values rare. Notice also that with this curve, the height values have been shifted up: the bottom of the curve is at 1, and the top of the curve is at 10, which means the values produced by the curve will be in the 1-10 range, instead of 0-1 like the previous curves. This curve is shallow at both the beginning and the end, making values close to the extremes more common, and steep in the middle which will make those values rare. Notice also that with this curve, the height values have been shifted up: the bottom of the curve is at 1, and the top of the curve is at 10, which means the values produced by the curve will be in the 1–10 range, instead of 0–1 like the previous curves.

Notice that these curves are not probability distribution curves like you might find in a guide to probability theory, but are more like inverse cumulative probability curves.

By defining a public AnimationCurve variable on one of your scripts, you will be able to see and edit the curve through the Inspector window visually, instead of needing to calculate values.

This technique produces floating-point numbers. If you want to calculate an integer result — for example, you want 82 gold pieces, rather than 82.1214 gold pieces — you can just pass the calculated value to a function like Mathf.RoundToInt().

Перемешивание списка

Довольно часто встречающаяся в играх механика — выбор из известного набора элементов, но со случайным порядком. Например, колода карт обычно перемешана, поэтому их не выбрать в предсказуемой последовательности. Вы можете перемешивать элементы в массиве путём “посещения” каждого из элементов и его обмена местами с другим элементом, случайно выбранным из массива:-

Выбор элементов из набора без повторений

Распространённая задача — случайно выбрать какое-то количество элементов из массива без повторного выбора одного и того же значения. Например, вы можете захотеть сгенерировать какое-то количество NPC в случайных точках генерации, но при этом вы желаете, чтобы только один NPC генерировался в каждой из точек. Это можно реализовать с помощью перебора последовательности элементов, решая для каждого случайным образом — быть ему добавленным в выбранный набор или нет. После “посещения” каждого элемента, вероятность того, что он будет выбран равна числу ещё требующихся элементов, разделённому на число оставшихся для выбора элементов.

В качестве примера, представьте, что существует десять точек генерации, но выбрать можно только пять. Вероятность выбора первого элемента будет равна 5 / 10 или 0.5. Если он выбран, то вероятность выбора второго элемента — 4 / 9, или 0.44 (то есть требуется ещё 4 элемента и ещё 9 доступно для выбора). Однако, если первый элемент не был выбран, то вероятность выбора второго элемента — 5 / 9, или 0.56 (то есть ещё требуется выбрать 5 элементов и ещё 9 доступно для выбора). Это продолжается до тех пор, пока набор не будет состоять из требуемых пяти элементов. Вы можете реализовать это в коде таким образом:-

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

Случайные точки в пространстве

Можно присвоить каждой компоненте Vector3 случайное значение, возвращаемое Random.value для получения случайной точки в пространстве куба:-

Это даст вам точку в кубе с ребром длиной в одну условную единицу. Куб можно масштабировать просто умножая X, Y и Z компоненты вектора на требуемые длины сторон. Если одна из осей имеет нулевое значение, точка всегда будет лежать на плоскости. Например, получение случайно точки “на земле” обычно достигается с помощью получения случайных компонент X и Z с установкой Y компоненты в ноль.

Random spawning in Unity (C#)

Hi I am making my first unity game in 2D and I have this code now. I have 3 different GameObjects (call them a, b , c) in the array arrows and i would want to know which one of them is spawned ( so i can use it in another function) and delete the previous one from the scene. Now it just spawns one GameObject on another every 5 seconds and I don’t know which one of them did it randomly spawn. Any idea?

user avatar

2 Answers 2

To keep track of what objects you instantiated you could create a List of GameObject and then when you instantiate an object you can add it in the List . Then you can use any GameObject in that list to do whatever you need.

And for spawning object like that it would be better to use InvokeRepeating , you can pass it the repeat rate and when you want it to start. More information on InvokeRepeating

Unity spawn object at random position

One of the fundamental concepts in game development is randomness. If you can create random scenes which conform to rules you already have a good base for procedural worlds. Welcome to this tutorial where I show you how to use unity to spawn an object at random position. This tutorial will be more focused on 2D however if you want to look at how to do this in 3D you can go and have a look at this video.

Unity spawn object at random position 2d

So let us now start off by creating a make shift terrain to spawn our objects onto. To do this we will use a simple 3d quad to place into our 2d world. So go ahead and right click in the hierarchy and create a new 3d quad.

You will now end up with a quad in the middle of the screen like this.

Go ahead and resize it up so that it fills the whole camera view like this.

Next we want to create a UI so we can generate random objects at random positions on the click of a button.

UI for our unity spawn an object at a random position tutorial

To create some UI for our scene we need to add a canvas inside of our scene. To do this right click in the hierarchy again and go to ui and click on canvas.

Select the canvas in the hierarchy and go over the inspector on the right and change this option. As well as drag your camera into your render camera slot.

Once that is done your canvas should snap to the size of your camera view. Next we want to create a button. So on your canvas in the hierarchy right click on the canvas and go to ui and button.

Click on the little drop down and click on the text ui element or game object.

On the right in the inspector change your text to generate.

Once done you might notice that your button is not showing in your scene this is because of the depth of field of your canvas. To fix this click on the 2d button to switch over into 3d mode.

Then double click on your Quad and zoom out using your mouse wheel button.

You will see something like this.

Use the blue arrow to drag your quad behind your canvas like this.

Your button should now be visible like this.

Position it using the move tool in the top left. So that you have something like this.

That is it for our UI for now. Let’s now look at creating our 2d objects which we want to place in random positions in our scene.

Creating objects for random placement in unity

For this tutorial we want to create two basic shapes in unity so we can go and instantiate them in our scene. We will then convert them to prefabs which we can re use in our c# script to place them in a given area.

So right click in assets and go ahead and create a object by going to create->sprites->square.

Do the same again and create a triangle. Now drag these into your hierarchy like this.

Now click on each and do the following steps.

Change the color to something you like. I will change mine to red for the triangle and blue for the square. Next you need to tag each of these objects as a spawnable. To do that go over to the Tag option in the inspector and add or select Spawnable.

So first add Spawnable.

Then go tag each of them like this.

Now drag each one of them into your Assets folder like this to make them a prefab.

Then finally delete them out of your hierarchy so that your hierarchy looks like this.

Once that is done we are ready to setup our spawner.

Creating the random position spawner

To do this we are going to create an empty object in our hierarchy like this.

Rename it to be Spawner.

Our spawner is now basically setup in our scene let’s go ahead and create our script.

Unity spawn object at random position c# script

Right click on your assets folder and create a c# script called spawner and rename it to spawner.

Open it up in visual studio and paste this code in there.

So to explain this code. We declare 3 public variables, numberToSpawn will tell our script how many objects we want to spawn in our scene.

Spawnpool we will use to allocate all our prefabs which we randomly want to place at random positions.

Gameobject quad will just hold our terrain, level or quad from our scene to give us some bounds on where we can spawn our different and various objects.

In start we just call spawnObjects so when we start our scene it will create some initial random objects.

Then we go on to define the spawnObjects method. We call destroyObjects to clean out our scene each time this method runs. We set some variables. toSpawn will contain our object we want to spawn. Randomitem will contain the index of the item we want to instantiate from our pool. Finally we will get the mesh collider of our quad to get the dimensions of our quad. Screen x and y will hold our x and y positions where we want to spawn our objects. The pos variable will just hold the position we want to spawn in.

Then we start off with a loop which will loop until the number of objects have been spawned. Inside the loop we will first use a random range to select a random object from our pool. Then once that is done we set our toSpawn from our pool. We then use another random range using the mesh collider to get random positions between the min and max of x and y.

From there we setup our pos for our vector2 using our random positions. We then simply instantiate our toSpawn object with that position and we re use the toSpawn rotation since we are spawning in 2d.

Finally we just go ahead and define our destroyObjects method as a private because we will only be using it in this class. We will loop over the objects in our scene which have the Spawnable tag and delete or destroy them in our scene.

Setting it all up

Save off your code and get back into unity and attach your c# script to the spawner object by clicking on the spawner and dragging the c# script into the inspector.

For our settings we will make the number to spawn 10. The size needs to be two so we can drag our triangle and square into our scene. Then also supply our quad so we can have our code detect the dimensions of our quad or terrain.

You should end up with this.

If you hit play now you should get this.

Hooking up the UI

We have to now just hookup the button so we can click generate and our scene will change. To do that click on your button in your hierarchy and go click on the plus in the inspector here.

Drag your spawner into the slot like this.

The from the drop down select spawnObjects like this.

Now hit play and your should be able to generate objects in different places each time you click your button.

That’s it the end of this tutorial I hope it has been useful. I will close off with some FAQ and some final words.

Frequently asked questions

What can I use unity instantiation for?

You can use it to bring objects into your scene on run time while your game is running. You can do this using code.

Why would I want to spawn objects at a random position?

Some infinite scenario generator type games rely on random scenarios to give players new and exciting content. Random positioning in your games can really help you with that.

Final words

If you liked this beginners tutorial to on how to spawn objects in unity in random positions. Why not support me by subscribing to my youtube channel here: YouTube

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *