- Home /
Hello, Need some help with invoke methods!!
Here I am trying to create a basic arkanoid game where random powerups prefabs are generated after a brick gets destroyed,the logic for random powerups is done but i wanted to generated these powerups after a time interval and change those interval randomly but basically im stuck :( , i've created a invoke method which disables the bool that calls the Instantiate method (GeneratedPower) but after 5sec the bool value doesn't changes and powerups keeps on popping , something is going wrong I just can't figure it out , so please can some one help me with this Issue? Hope Im making sense I kinda new to forum and Unity..:P and thanks in advance. I've attached the Blocks.cs file.
**using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Block : MonoBehaviour
{
[SerializeField] AudioClip breaksound;
[SerializeField] GameObject particleeffectVFX;
[SerializeField] int timeHits;
[SerializeField] Sprite[] sprites;
[SerializeField] public GameObject[] Powers;
bool disablePower;
level level;
Rigidbody2D myRigidBody2D;
public void Start()
{
CountBreakableBlocks();
myRigidBody2D = GetComponent<Rigidbody2D>();
disablePower = false;
Invoke("DisablePower", 5f);
}
public void DisablePower()
{
disablePower = !disablePower;
}
private void CountBreakableBlocks()
{
level = FindObjectOfType<level>();
if (tag == "Breakable")
{
level.CountBlocks();
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag.Equals("NormalBall") == true && tag == "Breakable")
{
HandleHits();
}
}
private void HandleHits()
{
timeHits++;
int maxHits = sprites.Length + 1;
if (timeHits >= maxHits)
{
DestroyBricks();
}
else
{
FindObjectOfType<GameStatus>().AddtoScore();
ShowNextHitSprite();
}
}
private void ShowNextHitSprite()
{
int spriteIndex = timeHits - 1;
if(sprites[spriteIndex] != null)
{
GetComponent<SpriteRenderer>().sprite = sprites[spriteIndex];
}
else
{
Debug.LogError("array out of index" + gameObject.name);
}
}
private void DestroyBricks()
{
FindObjectOfType<GameStatus>().AddtoScore();
AudioSource.PlayClipAtPoint(breaksound, Camera.main.transform.position);
Destroy(gameObject);
level.DestroyBlocks();
TriggerParticleVFX();
if(disablePower == true)
{
GeneratePower();/bool disablePower remains true after invoking
}
}
public void TriggerParticleVFX()
{
GameObject sparkles = Instantiate(particleeffectVFX, transform.position, transform.rotation);
Destroy(sparkles, 1f);
}
public void GeneratePower()
{
Instantiate(Powers[UnityEngine.Random.Range(0, Powers.Length)], transform.position, Quaternion.identity);
disablePower = false; // the bool doesn't gets disabled and prefabs keeps on instantiating.
}
}**
Not sure why to use any invoke or repetetion anyway, why dont just after destroying brick do Random.Range (0,101) and if it's under 10 lets say generate a powerup for example. or am i missing something? :- ) or you could do every 10th destroyed brick gives you powerup in destroy() function say destroyedBricks++ and then if (destroyedBricks >= 10 ) generatePowerUp(); and destroyedBricks = 0; But if you really want it timed you can do in update() for example : Tick++; if Tick >= 300 (or what you want) generatePowerUP(); Tick = 0;
Thank you for your quick reply, but unfortunately there are setbacks in your suggestion. :( 1.In random.range the no. will be random and sometimes it might happen that two power-ups are generated and as a beginner i'm avoiding such complexities of having two powers active simultaneously. 2. Same goes for number of bricks destroyed as in some crowded area it might happen user destroys 20 bricks quickly and he gets 2 power-up so i'm back at my first problem.. 3. As of the timer option it was a good idea but after Tick>300 it will keep on generating powers for that Tick counter so it should be reset but the problem is once the player loses that particular time for example at exact 15-sec then he has to wait for next 15 sec and so. So basically i wanted the generatepower() to get active at time 15sec and remain active until 1 power up is generated and after that the function should go inactive for next 15 sec. something like that .. Anyways thanks for your suggestion and open for more :P.
int tick;
int option_1_or_2 = 0;
void Update()
{
tick++;
if (tick >= 300)
{
//do something here. it wont happen more than once every
5 seconds.
//OR
switch (option_1_or_2) {
case 0:
//Do Things A here
option_1_or_2 = 1;
break;
case 1:
//after next period do B here
option_1_or_2 = 0;
break;
}
tick = Random.Range(50,251); //for random interval
tick = 0; //for 5 second periods
}
}
Answer by Poi7ioN · Apr 19, 2019 at 02:02 PM
Thank you for your answers , i truly appreciate it but i made some slight changes and it seems to be working fine , this is what i did.
void Update()
{
PowerTimer += Time.deltaTime;
if (PowerTimer > 20f)
{
GeneratePowerup();
}
if(PowerTimer > 12f)
{
PowerDestroy();
}
}
public void GeneratePowerup()
{
GameObject pow = Instantiate(generatePower[UnityEngine.Random.Range(0, generatePower.Count)],
new Vector3(Random.Range(1f,15f),Random.Range(8f,11f),0f), Quaternion.identity);
PowerTimer = 0;
}
Here I created a dontdestroyonload script and it generates powerups at random location from the range provided withing 20 sec of counter and destroys the powerup in 12sec which is already present in the scene.
Answer by Sergio7888 · Apr 18, 2019 at 07:44 PM
Try replace Invoke with a coroutine.
public void Start()
{
CountBreakableBlocks();
myRigidBody2D = GetComponent<Rigidbody2D>();
disablePower = false;
StartCoroutine(DisablePower());
}
IEnumerator DisablePower()
{
yield return new WaitForSeconds(5);
disablePower = !disablePower;
}
Your answer
Follow this Question
Related Questions
Action not triggered after Invoke time passed (Invoke called in different script) 0 Answers
Moving instantiated prefab from randomly chosen startPoint to randomly chosen endPoint 1 Answer
Problem: Random Instantiating more than one prefab? 1 Answer
InvokeRepeating with a variable? 2 Answers
¿how to take all values from an array without order? 2 Answers