I writing simple runner game.
I have game object (quad).
I want it to generate.
I wrote spawnscript:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
//public GameObject obj;
public float spawnMin = 1f;
public float spawnMax = 2f;
// Use this for initialization
void Start () {
Spawn();
}
void Spawn()
{
//for (int i = 0; i < 10; i++)
// Instantiate(obj, new Vector3(i * 2.0f, 0, 0), Quaternion.identity);
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
But my quad spawning one time.I need it to spawn multiple times.
Where is my problem?
Use InvokeRepeating instead of Invoke in start event:
// Invokes the method methodName in time seconds, then repeatedly every repeatRate seconds.
InvokeRepeating("Spawn", 3, 3);
If you do InvokeRepeating("Function", 1.0f, 1.0f), it will call Function one second after the InvokeRepeating call and then every one second thereafter.
Hence, you can control the spawn timings.
Update
As asked in comments:
You can also cancel InvokeRepeating any time by calling below code. More information here.
CancelInvoke("Spawn");
There is no problem with code. All GameObjects instantiated same position so you can use code below:
public float spawnDistanceFactor = 2f; //Value is your choice. You can change it.
void Spawn()
{
float startPosX = 0f; // I assume your camera look at 0,0,0 point.
for (int i = 0; i < 10; i++){
Vector3 spawnPos = new Vector3(startPosX,0f,0f);
Instantiate(obj, spawnPos, Quaternion.identity);
startPosX+=spawnDistanceFactor;
}
}
It is only moves positions on X axis you can move it x,y,z.
Also
You can use Random function for moving spawn position
public float randomMin = 2f;
public float randomMax = 4f;
void Spawn()
{
float startPosX = 0f; // I assume your camera look at 0,0,0 point.
for (int i = 0; i < 10; i++){
Vector3 spawnPos = new Vector3(startPosX,0f,0f);
Instantiate(obj, spawnPos, Quaternion.identity);
float randomX = Random.Range(randomMin,randomMax);
startPosX+=randomX;
}
}
You can do a lot of things.
For destroying prefabs you can add Destroy script to object (You should create prefab with script) Like:
void DestroyObject(){
Destroy(this.gameObject);
}
or use list to hold pointers to the GameObjects. Like:
using System.Collections.Generic; // For list
private List<GameObject> objectList;
public float randomMin = 2f;
public float randomMax = 4f;
void Start(){
objectList = new List<GameObject>();
Spawn();
}
void Spawn()
{
objectList.Clear(); ///For multiple spawn purpose dont dublicate items.
float startPosX = 0f; // I assume your camera look at 0,0,0 point.
for (int i = 0; i < 10; i++){
Vector3 spawnPos = new Vector3(startPosX,0f,0f);
GameObject newObject = Instantiate(obj, spawnPos, Quaternion.identity) as GameObject;
objectList.Add(newObject);
float randomX = Random.Range(randomMin,randomMax);
startPosX+=randomX;
}
}
void DestroyObject(){
for(int i=0;i<objectList.Count;i++){
Destroy(objectList[i]);
}
}
Related
I'm making a "player fish eats smaller fish and grows" game as practice. But I'm struggling with making the npc fish not spawn on or too close to the player.
This is the code for the spawner, atm fish can still spawn on the player.
public class Spawner : MonoBehaviour
{
public GameObject[] itemsToPickFrom;
public int numberToSpawn;
float placeX;
float placeY;
float minDistance;
void Start()
{
Spawn();
minDistance = 5f;
}
void Spawn()
{
for (int i = 0; i < numberToSpawn; i++)
{
int randomIndex = Random.Range(0, itemsToPickFrom.Length);
placeX = Random.Range(-10f, 9f);
placeY = Random.Range(-4f, 4f);
while (Vector2.Distance(GameObject.FindGameObjectWithTag("Player").transform.position, new Vector3(placeX, placeY, 0)) < minDistance)
{
placeX = Random.Range(-10f, 9f);
placeY = Random.Range(-4f, 4f);
}
Instantiate(itemsToPickFrom[randomIndex], new Vector3(placeX, placeY, 0), quaternion.identity);
}
}
I guess it's Unity, if so numberToSpawn is probably set on the editor interface, so it shouldn't be a problem.
The issue I can see is that you set minDistance after Spawn().
void Start()
{
Spawn();
minDistance = 5f;
}
If you set minDistance before Spawn(), it could be correct. The other logics seems correct at least.
float minDistance = 5f;
void Start()
{
Spawn();
}
so I'm making a 2D platformer and I would like to spawn enemies on the whole map but not in the camera range.
I have to mention I am using Cinemachine to follow the player.
This is my script for the spawner:
*public class MobSpawner : MonoBehaviour
{
public GameObject Mob;
float randX;
Vector2 whereToSpawn;
public float spawnRate = 2f;
float nextSpawn = 0.0f;
public GameObject Camera;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Time.time > nextSpawn)
{
nextSpawn = Time.time + spawnRate;
randX = Random.Range(-36f, 62);
whereToSpawn = new Vector2(randX, transform.position.y);
Instantiate(Mob, whereToSpawn, Quaternion.identity);
}
}
}*
As you can see I'm taking 2 points and in between them I spawn enemies. As this range would basically be the entire map, the camera will always be in it.
I want enemies to NOT spawn inside the camera yet spawn outside of it. How can I manage to do this?
I'd say the simplest solution would be to just calculate vector distance between the player position and spawning position. Since this is a 2d space and you are spawning them only on one axis it should be fine.
So you could do
float distanceAwayFromCameraView = 5;
// you will need a method, reference or just get the object via tag
var playerPos = GameObject.Find("Player").transform.position;
randX = Random.Range(-36f, 62);
whereToSpawn = new Vector2(randX, transform.position.y);
while ((Vector2.Distance(whereToSpawn, playerPos) < distanceAwayFromCameraView){
randX = Random.Range(-36f, 62);
whereToSpawn = new Vector2(randX, transform.position.y);
}
Instantiate...
I'm not at my pc to test this right now, please let me know if there's errors
I have a script that spawns my ground prefabs infinitely. The only problem is that occasionally there is a "bump" for the player to hit at the boundary of a new ground prefab.
It seems like one prefab is slightly higher than the previous one and when the player hits that small bump they go flying. How do I fix this?
I might just make the player a game object instead of a rigidbody and animate it instead of using actual physics.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GroundManager : MonoBehaviour
{
//oH is object height
public GameObject[] ground;
public GameObject[] obstacles;
private Transform playerTransform;
private float spawnZ = 0.0f;
private float spawnO = 0.0f;
public float oH;
private float tileLength = 40.0f;
private float oLength = 36.0f;
private int tilesOnScreen = 8;
void Start()
{
playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
for (int i = 0; i < tilesOnScreen; i++)
{
SpawnTile();
SpawnObstacle();
}
}
// Player must be tagged "Player"
void Update()
{
if (playerTransform.position.z > (spawnZ - tilesOnScreen * tileLength))
{
SpawnTile();
SpawnObstacle();
}
}
private void SpawnTile(int prefabIndex = -1)
{
GameObject go;
go = Instantiate(ground[0]) as GameObject;
go.transform.SetParent(transform);
go.transform.position = Vector3.forward * spawnZ;
spawnZ += tileLength;
}
private void SpawnObstacle()
{
GameObject go;
go = Instantiate(obstacles[Random.Range(0, obstacles.Length)]) as GameObject;
go.transform.SetParent(transform);
go.transform.position = new Vector3(0, oH, 1 * spawnO);
spawnO += oLength;
}
}
This code works to infinitely spawn the ground objects but has the bumps that I described. Just one bump is enough to screw up the whole game.
I am using EnemyScript to move the enemy towards the player and killing the player, but I'm unable to spawn it randomly in code. I am currently spawning it directly through screen by placing the prefab on the scene.
Here is my EnemyScript
using UnityEngine;
using System.Collections;
public class EnemyScript : MonoBehaviour {
public Transform target;
public float speed = 2f;
void Update ()
{
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
}
void OnTriggerEnter2D(Collider2D otherCollider)
{
PlayerControl shot = otherCollider.gameObject.GetComponent<PlayerControl>();
if (shot != null)
{
Destroy(shot.gameObject);
}
}
}
you could use something similar to this:
public GameObject myObj;
void Start ()
{
enemy = GameObject.Find("enemy");
InvokeRepeating("SpawnEnemy", 1.6F, 1F);
}
public void SpawnEnemy()
{
Vector3 position = new Vector3(Random.Range(35.0F, 40.0F), Random.Range(-4F, 2F), 0);
Instantiate(myObj, position, Quaternion.identity);
}
in the InvokeRepeating call you could possibly add the random range there also instead of a timed instantiate. This example is just a snippet of some prototype code i did a while ago, it may not suit your needs directly but hopefully will give you a general idea on what to do.
EDIT: to make sense, put this into a blank object somewhere in your scene, dont attach this to the actual enemy.
i programmed it like this.
public GameObject enemyPrefab;
public float numEnemies;
public float xMin = 20F;
public float xMax = 85F;
public float yMin = 3.5F;
public float yMax = -4.5F;
void Start () {
for (int i=0; i< numEnemies; i++) {
Vector3 newPos = new Vector3(Random.Range(xMin,xMax),Random.Range(yMin,yMax),0);
GameObject enemy = Instantiate(enemyPrefab,newPos,Quaternion.identity) as GameObject;
}
}
This will spawn a random number of enemies, at random locations, after random periods of time, all adjustable in the Inspector.
public float minTime = 1;
public float maxTime = 3;
public int minSpawn = 1;
public int maxSpawn = 4;
public Bounds spawnArea; //set these bounds in the inspector
public GameObject enemyPrefab;
private spawnTimer = 0;
Vector3 randomWithinBounds(Bounds r) {
return new Vector3(
Random.Range(r.min.x, r.max.x),
Random.Range(r.min.y, r.max.y),
Random.Range(r.min.z, r.max.z));
}
void Update() {
spawnTimer -= Time.deltaTime;
if(spawnTimer <= 0) {
spawnTimer += Random.Range(minTime, maxTime);
int randomSpawnCount = Random.Range(minSpawn, maxSpawn);
for(int i = 0; i < randomSpawnCount; i++) {
Instantiate(transform.transformPoint(enemyPrefab), randomWithinBounds(spawnArea), Quaternion.identity);
}
}
}
//bonus: this will show you the spawn area in the editor
void OnDrawGizmos() {
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.color = Color.yellow;
Gizmos.drawWireCube(spawnArea.center, spawnArea.size);
}
People on here seem to like using coroutines for time delays, but I personally prefer to track my own timers in Update() to maximize control and predictability.
I am making my first Unity game and I decided to make a 5 level shooter for mobile. I have made a random spawn script for my enemies, but the spawn is too frequent and generates too many at once.
Here is the script:
using UnityEngine;
using System.Collections;
public class CreateRandomOctodeamons : MonoBehaviour {
public GameObject enemyPrefab;
public GameObject enemyPrefab1;
public float numEnemies;
public float xMin = 19F;
public float xMax = 85F;
public float yMin = 3.5F;
public float yMax = -4.5F;
void Start () {
GameObject newParent = GameObject.Find("1-background elements");
for (int i = 0; i < numEnemies; i++)
{
Vector3 newPos = new Vector3(Random.Range(xMin, xMax), Random.Range(yMin, yMax), 0);
GameObject octo = Instantiate(enemyPrefab, newPos, Quaternion.identity) as GameObject;
octo.transform.parent = newParent.transform;
Vector3 newPos1 = new Vector3(Random.Range(xMin, xMax), Random.Range(yMin, yMax), 0);
GameObject octo1 = Instantiate(enemyPrefab1, newPos, Quaternion.identity) as GameObject;
octo1.transform.parent = newParent.transform;
}
}
Please look over it and let me know if I should change anything or add anything. I am also looking for a generic health script where I could just add my play prefab to allow his health to show above his head.
This sounds like 3 or more questions in one. I'll try to answer the question about "too many."
Try something like this:
void Start () {
if (numEnemies < YourThreshholdForNumberOfEnemies)
{
GameObject newParent = GameObject.Find("1-background elements");
for (int i = 0; i < numEnemies; i++)
{
Vector3 newPos = new Vector3(Random.Range(xMin, xMax), Random.Range(yMin, yMax), 0);
GameObject octo = Instantiate(enemyPrefab, newPos, Quaternion.identity) as GameObject;
octo.transform.parent = newParent.transform;
Vector3 newPos1 = new Vector3(Random.Range(xMin, xMax), Random.Range(yMin, yMax), 0);
GameObject octo1 = Instantiate(enemyPrefab1, newPos, Quaternion.identity) as GameObject;
octo1.transform.parent = newParent.transform;
}
}
}
well if you want you can use this
public GameObject[] obj; // for your enemies, using array so you can put many kind of enemy prefabs
public float spawnMin = 1f; //your minimum time enemies spawn
public float spawnMax = 2f; //your maximum time enemies spawn
void Start ()
{
spawn();
}
void spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], //instantiate random prefabs
new Vector3(transform.position.x, transform.position.y, z),
Quaternion.identity)
//this is the one that control how many times spawn called
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}