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));
}
Related
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 trying to make a doodle jump game in unity for fun and I have a question.
How could I change my script to spawn other platforms on top and destroy any platform that is under main camera.I'll let down my code for spawning random platforms
public class GradinariuZAHAR : MonoBehaviour
{
public Transform Player;
public GameObject platformPrefab;
private float minimY = 0.2f;
private float maximY = 1.6f;
public int numberOfPlatforms = 200;
public float levelWidth = 3f;
// Use this for initialization
void Start()
{
GenerateChunk(.2f, 1.5f);
}
void GenerateChunk(float minY, float maxY)
{
Vector3 spawnPosition = new Vector3(0f, 0f, 0f);
for (int i = 0; i < numberOfPlatforms; i++)
{
spawnPosition.y += Random.Range(minY, maxY);
spawnPosition.x = Random.Range(-levelWidth, levelWidth);
Instantiate(platformPrefab, spawnPosition, Quaternion.identity);
}
}
void Update()
{
if (Player.position.y > 160) {
Debug.Log("acum");
minimY = maximY;
maximY = maximY * 2;
GenerateChunk(minimY, maximY);
}
}
}
Just attach the following script to your platform. It'll destroy the platform once its entire sprite is completely below the camera, exactly how you want it.
using UnityEngine;
public class Platform : MonoBehaviour
{
SpriteRenderer sprite;
float bottomOfScreen;
private void Start()
{
sprite = GetComponent<SpriteRenderer>();
var cam = Camera.main;
var screen = new Vector2(Screen.width, Screen.height);
var camWorldPos = cam.ScreenToWorldPoint(screen);
bottomOfScreen = camWorldPos.y - cam.orthographicSize * 2;
}
private void Update()
{
var height = sprite.bounds.size.y;
var topOfPlatform = transform.position.y + height / 2;
if (topOfPlatform < bottomOfScreen)
Destroy(gameObject);
}
}
I am creating a simple 2D platform game where the player will be jumping upwards in an infinite mode. Something like Doodle Jump! I am currently trying to make a breakable platform and a normal one but I have been having some problems spawning 2 different platforms at once. I did this code below and it seems to have 2 of the platforms colliding on top of each other
using UnityEngine;
using System.Collections;
public class PlatformSpawner : MonoBehaviour{
[SerializeField]
GameObject PlatformPrefab;
public float radius = 0f;
[SerializeField]
GameObject PlayerPrefab;
[SerializeField]
CameraFollow cameraScript;
[SerializeField]
GameManager gameManagerScript;
BoxCollider2D playerBoxCol2d;
public float topPlatformYPos = 0;
void Start(){
SpawnPlatformStart();
SpawnBreakPlatformStart();
}
/*This is the Platform Spawner when start */
void SpawnPlatformStart(){
float yPos = -4f;
float xPos = 0f;
GameObject playerGo = Instantiate (PlayerPrefab, Vector3.zero, Quaternion.identity) as GameObject;
playerBoxCol2d = playerGo.GetComponent<BoxCollider2D> ();
for (int i = 0; i < 6; i++) {
xPos = Random.Range (-2f, 2f);
GameObject platformGo = Instantiate (PlatformPrefab, new Vector3 (xPos, yPos, 0f), Quaternion.identity) as GameObject;
cameraScript.player = playerGo.transform;
if (i <= 0) {
playerGo.transform.position = new Vector3 (xPos, yPos + 1f, 0f);
}
Platform platformScript = platformGo.GetComponent<Platform> ();
GetComponentForPlatformScript (platformScript);
topPlatformYPos = yPos;
yPos += 2f;
}
}
/*This is the different Platform to spawn */
void SpawnBreakPlatformStart(){
float yPos = -20f;
float xPos = f;
for (int i = 0; i < 6; i++) {
xPos = Random.Range (6f, -3f);
GameObject platformGo = Instantiate (BreakPlatformPrefab, new Vector3 (xPos, yPos, 0f), Quaternion.identity) as GameObject;
Platform platformScript = platformGo.GetComponent<Platform> ();
GetComponentForPlatformScript (platformScript);
topPlatformYPos = yPos;
yPos += 4f;
}
}
void GetComponentForPlatformScript(Platform _platformScript){
_platformScript.playerBoxCollider2d = playerBoxCol2d;
_platformScript.PlatformSpawnerScript = this;
_platformScript.cameraTrans = cameraScript.gameObject.transform;
}
void GetComponentForPlayerScript(PlayerController _playerScript){
_playerScript.cameraTrans = cameraScript.gameObject.transform;
_playerScript.gameManagerScript = this.gameManagerScript;
}
}
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]);
}
}
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.