Unity-C# Instantiate is not working - c#

I use instantiate to create objects but it create object continuous.
Code is here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class instantiateObject: MonoBehaviour {
public int topSayi;
public Transform prefab;
void Start () {
for(int a = 0; a < topSayi; a++)
{
prefab.localPosition = new Vector3(0, a * -0.5f, 5);
Instantiate(prefab);
}
}
}
it create object continuous

It looks like it does not go inside the for loop. I would guess topSayi is the times you want to instantiate, so you wrote the for statement wrong. It should be like this:
for(int a = 0; a < topSayi; a++)
{
prefab.localPosition = new Vector3(0, a * -0.5f, 5);
Instantiate(prefab);
}
You were checking if a is bigger than topSayi, which would never be the case. therefore it will never go inside the for statement. It must be the other way around.

Revision 1:
Having a script on a prefab that creates a copy of that same prefab in either Start() or Awake() is the functional equivalent of creating an infinite recursion. Whenever a copy of the prefab is instantiated, it (almost) immediately creates another copy of itself ad infinitum. Simply put, don't do this! Have some other manager-type object to do the instantiating.
Original:
You don't instantiate transforms, you instantiate GameObjects:
public GameObject prefab;
Secondly, you should set the position AFTER or, preferably, during instantiation:
var go = Instantiate(prefab, position);
And finally, as #JackMini36 noted, the condition on your for loop is (edit: was) malformed:
for(int a = 0; a < numSayi; a++)

Related

Cannot reference a script on an array of gameobjects generated in another script

I want an array of game objects, each game object has a simple script to move it. I want a controlling script to be able to trigger the remote script by referencing the array coordinates / game object at that point.
I am missing something basic in referencing a "global" variable - so apologies in advance. I have spent several hours now reading and trying things out.
Example questions like here Accessing a variable from another script C#
or
https://answers.unity.com/questions/42843/referencing-non-static-variables-from-another-scri.html
I believe the array should be static as there is only one set of data, however I don't care if it isnt
CreateGrid.cs
public class CreateGrid : MonoBehaviour
{
public static GameObject[,] gridArray = new GameObject[5, 5];
public GameObject gridSpace;
// Start is called before the first frame update
void Start()
{
GenerateGrid();
}
void GenerateGrid()
{
for (int x = 0; x < 5; x++)
{
for (int z = 0; z < 5; z++)
{
gridArray[x, z] = Instantiate(gridSpace, new Vector3(x, 0, z), Quaternion.identity) as GameObject;
}
}
// test grid works
// gridArray[2, 2].transform.Translate(0.0f, 3.0f, 0.0f);
}
}
test code
public class Pulse : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
for (int x = 0; x < 5; x++)
{
CreateGrid.gridArray[x, 3].GetComponent<MoveObject>().StartBounce(5.0f);
}
}
}
The grid of objects works.
However the test code errors with Object reference not set to an instance of an object from the line
CreateGrid.gridArray[x, 3].GetComponent().StartBounce(5.0f);
specifically CreateGrid.gridArray
Given that I seem to be really struggling with a concept, please explain clearly.
Thanks
Unless you don't clearly define otherwise, you don't know when the Start method of two MonoBehaviours will run.
In your case, the Pulse's Start method is called before CreateGrid's.
To fix your problem, I advise you to call CreateGrid's Generate method inside the Awake method of the class.
I often use this method to initialize members of the class not relying on other classes instances and use the Start method to initialize members needing other instances to be self-initialized.

Can't figure out how to do this all in one function

I am creating a zoo simulation game in Unity 5.4.0f3 using C#. I am trying to spawn a bear prefab clone, do some math, wait for a period of time, do some more math, then destroy the clone object all in one function. Here is what I have right now. The math that I am trying to do in WaitForBearLife() does not happen. Thanks in advance!
using UnityEngine;
using System.Collections;
public class BuyBearButton : MonoBehaviour
{
[SerializeField] GameManager gameManager;
[SerializeField] GameObject bearPrefab;
[SerializeField] Visitor visitor;
GameObject bearClone;
float xMin = -15;
float xMax = 15;
float yMin = 5;
float yMax = 6;
public void BuyBear()
{
Vector2 pos = new Vector2 (Random.Range (xMin, xMax), Random.Range (yMin, yMax));
if (gameManager.myMoney >= gameManager.bearCost)
{
gameManager.numberOfBears++;
gameManager.myMoney = gameManager.myMoney - gameManager.bearCost;
visitor.spawnTime = visitor.spawnTime / visitor.bearAttraction;
bearClone = (GameObject) Instantiate (bearPrefab, pos, transform.rotation);
StartCoroutine (WaitForBearLife ());
Destroy (bearClone, gameManager.bearLife);
}
}
IEnumerator WaitForBearLife()
{
yield return new WaitForSeconds (gameManager.bearLife);
visitor.spawnTime = visitor.spawnTime * visitor.bearAttraction;
}
}
you need to move Destroy function from BuyBear to WaitForBearLife
The problem is that now StartCouroutine call immediately returns and Destroy() gets called right away
I've just copied your code in an empty project, and made placeholder classes for GameManager and Visitor, just with random values in the variables we need in this script. It works just fine... really.So, I'll make you some questions (as I don't have the reputation yet to comment in your post...)
First, there's a script in the bear prefab of any sorts?
This is because it maybe have something that could interrupt the coroutine. It seems unlikely, but you can't know for sure until you try.
Next, how is the declaration of Visitor and GameManager?
The very beginning, when you define the class name and such. In fact, I would like to know more about the variables you used, like gameManager.bearLife and such.
Now, let's see the values.
I've tried with:
public int myMoney = 50000;
public int bearCost = 50;
public int numberOfBears = 0;
public float bearLife = 2.0f;
In GameManager. And:
public float spawnTime = 5;
public float bearAttraction = 2;
In Visitor. It does some weird math, and the logic of this script itself is clearly in development right now, I suppose. But the point is, it works, and with this:
IEnumerator WaitForBearLife()
{
yield return new WaitForSeconds (gameManager.bearLife);
print (visitor.spawnTime);
visitor.spawnTime = visitor.spawnTime * visitor.bearAttraction;
print (visitor.spawnTime);
}
I get 2.5 and 5 in the correspondant prints if I only click once. Some prints (As #Benjamin-lecomte stated) could help you to know if it's even executing that part.
For now, I can't help you without knowing much more. So I'll wait for your answer, then.

Why the property Range not exist in Random class in unity?

using System;
using UnityEngine;
using System.Collections;
using UnityStandardAssets.Characters.ThirdPerson;
public class Multiple_objects : MonoBehaviour {
public GameObject prefab;
public GameObject[] gos;
public int NumberOfObjects;
private ThirdPersonCharacter[] thirdPersonCharacter;
private Animator[] _animator;
private int count = 0;
void Awake()
{
Vector3 v3 = prefab.transform.position;
_animator = new Animator[NumberOfObjects];
gos = new GameObject[NumberOfObjects];
for(int i = 0; i < gos.Length; i++)
{
count = count + 2;
GameObject clone = (GameObject)Instantiate(prefab, Vector3.zero, Quaternion.identity);
gos [i] = clone;
gos [i].transform.position = new Vector3 (v3.x - count, v3.y, v3.z);
_animator [i] = gos[i].GetComponent<Animator> ();
Math.Round(Random
When i type point after the Random like: Random.
I have only Equals and ReferenceEquals
And if i create a variable of Random for example:
Random _random;
Then i type _random.
I get more propeties but not Range.
You are using both the UnityEngine and System namespace. Both of these namespaces contain a Random class, so Visual Studio/Unity doesn't know which one you want to use. To specify which random you want to use, you would simply do this:
UnityEngine.Random.Range(0.0f, 5.0f);
Write UnityEngine.Random.Range
You have to clarify the namespace.
Unless you want the .net Random ( in that case look at the other answer)
Why the property Range not exist in Random class in unity?
Random _random;
_random.Rand...
Range is a static function in the Random class. You don't need to create instance of the class to use static functions inside then. You call static functions directly.
This should do it: Random.Range(0f,3f);
If you are getting the Random' is an ambiguous reference betweenSystem.Random' and UnityEngine.Random' error then that's because you haveusing System;`(which you did in your code) and therefore you must use the full namespace to access Unity random function.
UnityEngine.Random.Range(0f, 3f);

spawn obstacles c# and accessing from another script

I'm Getting a error when i try to instantiate in the manager class. saying
Error CS1061: Type UnityEngine.Object' does not contain a definition forGetComponent' and no extension method GetComponent' of typeUnityEngine.Object' could be found. Are you missing an assembly reference? (CS1061) (Assembly-CSharp)
Add this to your Obstacle class:
void Start()
{
manager = GameObject.FindWithTag("ObstacleManager").GetComponent<ObstacleManager>();
}
The tag obviously has to be the tag of the gameobject the manager is attached to.
Also: Always start class names with a capital letter (I did that in the snippet, keep that in mind, you will get an error right know with that).
Maybe you want to actually change your spawning a bit though. Have two lists, one for free spawnpoints and one for occupied. When you destroy an obstacle, pass the position to the spawning function to move the position to the free list.
Edit:
Another option to create the reference is to set it in your ObstacleManager on spawning. You need to grab a reference to the instantiated obstacle for this. I believe this should work without actually grabbing the obstacle gameobject, but you could do that too.
Obstacle obs = ((GameObject)Instantiate(TypeOfObstacles[j], pointsAvailiable[pointsIndex].position, Quaternion.identity)).GetComponent<Obstacle>();
obs.SetManagerReference(this);
And in Obstacle add
public void SetManagerReference(ObstacleManager obsManager)
{
manager = obsManager;
}
For the free position you can do something like this:
// in Obstacle.cs
public void OnMouseDown()
{
manager.SpawnNewObstacle(transform.position); // you might be able to actually pass the transform, but I'm not sure if it will get destroyed before used in the other function
Destroy(gameObject);
}
In the Manager:
public int noOfObsacles;
public float[] xPercent;
public GameObject[] TypeOfObstacles;
float y;
// to keep track of which spawn points are free and which aren't use these lists
private List<Transform> freePositions;
private List<Transform> occupiedPositions;
private void Start()
{
freePositions = new List<Transform>(spawnPoints);
occupiedPositions = new List<Transform>();
SpawnObstacles();
}
private void SpawnObstacles()
{
// just use this for initial obstacles
// call Spawn as often as needed
for(int i = 0; i < noOfObstacles; i++)
{
Spawn();
}
}
// you call this function from the obstacle that gets destroyed
public void SpawnNewObstacle(Vector3 freePos)
{
// find the spawnpoint in the occupied points
// and move it to the free ones since the obstacle got destroyed
for(int i = 0; i < occupiedPositions.Count; i++)
{
if(occupiedPositions[i].position == freePos)
{
freePositions.Add(occupiedPositions[i]);
occupiedPositions.RemoveAt(i);
break;
}
}
// and call Spawn
Spawn();
}
private void Spawn()
{
y = Random.value;
int pointsIndex = Random.Range (0, freePositions.Count);
for (int j =0; j<xPercent.Length; j++)
{
if ( y < xPercent[j])
{
// these 4 lines are essential for the spawning
Obstacle obs = ((GameObject)Instantiate(TypeOfObstacles[j], freePositions[pointsIndex], Quaternion.identity).GetComponent<Obstacle>();
obs.SetManagerReference(this);
occupiedPositions.Add(freePositions[pointsIndex]);
freePositions.RemoveAt(pointsIndex);
break;
}
}
}
had a bracket issue! my bad
obstacle obs = ((GameObject)Instantiate(TypeOfObstacles[j], freePositions[pointsIndex].position, Quaternion.identity)).GetComponent();

Unity3D: Spawn random objects one after another (2D)

I want to create a terrain made out of randomly generated objects. I have created couple of prefabs and made a script that has all 3 prefabs in an array, and spawns them randomly.
The problem that I have is that the objects (of different sizes) are being spawned in 1 unit distance, so basically over each other, instead of right after each other.
The second problem is that I am not sure how to limit the spawning to a decent number. I have created a script that destroys the objects once I pass them, but in the code, at the moment, they are spawning infinitely, too fast (I know the code isn't the nicest, I am still practicing).
I did look for possible solutions or similar problems, but haven't found anything that can help me.
Here is the code from my script:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
public Vector3 pos = new Vector3(-8,-4,0);
public float size = 1.0f;
private Vector3 dir = Vector3.right;
void Start () {
Spawn();
}
void Spawn() {
for (int i = 0; i<30; i++)
{
Instantiate (obj [Random.Range (0, obj.Length)], pos, Quaternion.identity);
pos += dir * size;
}
Invoke ("Spawn", 2);
}
}
I hope I can get any advises, references or help.
They are being spawned at 1 unit distance because you defined size as 1.0f. Take the real size of the object instead:
GameObject go = obj[Random.Range(0, obj.Length)];
Vector3 size = go.renderer.bounds.size;
pos += new Vector3(dir.x * size.x, dir.y * size.y, dir.z * size.z);
Instantiate(go, pos, Quaternion.identity);
See: Find Size of GameObject

Categories