Counter is not decremented in Unity 3D - unity3d

Basically this game is a brick breaker in which I will be giving a quick basic background about it. The game will spawn 10 bricks at random locations, and if the all hits the brick
once, the brick is destroyed. If all 10 bricks are destroyed then the user will be taken to the other scene (gamewon).
My main problem is that when I destroy all the bricks, I am not being redirected to the scene. However if I set the numberOfBricks to 1, it will work.. I can't really understand what's happening.
Thanks alot guys!
-HurpaDurpa
using UnityEngine;
using System.Collections;
public class BrickScript : MonoBehaviour {
public int position_x = 0;
public int position_y = 0;
public GameObject Brick;
public int brickDamage = 0;
public int numberOfBricks = 10;
// Use this for initialization
void Start () {
Brick = GameObject.Find ("Brick");
position_x = Random.Range (-6, 6);
position_y = Random.Range(-1, 4);
transform.position = new Vector3 (position_x, position_y, transform.position.z);
}
// Update is called once per frame
void Update () {
if (brickDamage == 1) { //destroy brick on 1 hit
numberOfBricks--;
Object.Destroy (gameObject); //so it will destroy the hit object
}
if (numberOfBricks == 0) {
Application.LoadLevel (1);
numberOfBricks = 10;//Variable resetted
}
}
void OnCollisionEnter(Collision collision)
{
brickDamage++;
}
}

This is happening because you seem to have attached the script above to each brick.
So what is really happening is when any one of your bricks get hit, the numberOfBricks reduces by 1, resulting the value going to 9. This will happen to each brick.
Rather, what you need to do is to keep this numberOfBricks counter in another script. In the OnCollisionEnter portion of your code, you should reduce the numberOfBricks variable in the other script by 1.
Do that and you'll see the result you expect.

Related

2D Instantiated object stops moving when used with timer

Hello I'am trying to make a system that instantiate and object, and the moves it to a set of waypoints. When i use intantiate in the Start() function it travels like intended through the waypoints, but when i add the instantiate line to my update() function it only travels a little while and then stops, the same goes for the rest of the instantiated objects. It has something to do with timer i guess, but i have tried a few approaches, but they all lead to the same thing. Hope someone can help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class waypointTest : MonoBehaviour
{
[SerializeField] private Transform[] waypoints;
public GameObject waypointInvader;
GameObject go;
private int nextUpdate = 1;
public float speed = 5f;
private int waypointIndex;
void Start()
{
}
void Update()
{
if (Time.time >= nextUpdate)
{
nextUpdate = Mathf.FloorToInt(Time.time) + 1;
go = Instantiate(waypointInvader, transform.position, transform.rotation) as GameObject;
}
if (go.transform.position != waypoints[waypointIndex].transform.position)
{
Vector3 newPos = Vector3.MoveTowards(go.transform.position, waypoints[waypointIndex].transform.position, speed * Time.deltaTime);
go.transform.position = newPos;
if (newPos == waypoints[waypointIndex].transform.position)
{
waypointIndex += 1;
}
if (waypointIndex == waypoints.Length)
{
waypointIndex = 0;
}
}
}
}
The problem is that you are loosing the reference to the object you want to move.
If instantiate is inside Start():
go is set to be the instantiated object
go is moved to every waypoint
go is moved to the very first waypoint
go is moving through the waypoints again
If instantiate is inside Update():
go is set to be the first instantiated object
go is moved to a few waypoints until Time.time >= nextUpdate returns true
go is set to be the second instantiated object and will loose its reference to the first go
The first go stops moving
The second go starts moving
Repeat
One way to solve this problem is to give the moving object go its own movement script. That way you just have to instantiate go and it will handle its movement by itself. If go does not know where the waypoints are you can give it to it after instantiating (For example waypointInvader is a prefab). E.g.:
if (Time.time >= nextUpdate)
{
nextUpdate = Mathf.FloorToInt(Time.time) + 1;
go = Instantiate(waypointInvader, transform.position, transform.rotation) as GameObject;
go.GetComponent<GoMovement>().ListOfWaypoints = waypoints;
}

Destroying Prefabs Object After Spawn Using collision

I currently have some objects spawning from a prefab and am attempting to destroy only one of the spawned items of that prefab. I was searching online and I found tons of different examples but I have been unable to get any of them to work. I tried setting up an instance of the Instantiate and destroying that instance but I am unable to get it to work. The spawn/collision script is attached to the main camera if that matters. Collision with other items in my game work and the prefab does have a box collider set to isTrigger. Again, I know there are plenty of examples explaining this etc, but I can't get it to work and maybe I am not understanding what I actually should be doing.
Spawner code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bloodVialSpawner : MonoBehaviour
{
public GameObject vialOfBlood;
private GameObject vialss;
private int hunger =10;
public int numOfVials;
public int minSpawnRange, maxSpawnRange;
public int minSpawnRange2, maxSpawnRange2;
// Start is called before the first frame update
float timeSpawns = 2;
List<GameObject> vialsInstantiated = new List<GameObject>();
void Start()
{
StartCoroutine(becomeHungry());
InvokeRepeating("SpawnVials", timeSpawns, timeSpawns);
}
private void Update()
{
if (hunger == -1)
{
Debug.Log("sigh");
}
}
void SpawnVials()
{
for (int i = 0; i < numOfVials; i++)
{
vialsInstantiated.Add(Instantiate(vialOfBlood, SpawnPosition(), Quaternion.identity) as GameObject);
}
}
Vector3 SpawnPosition()
{
int x, y, z;
y = 59;
x= UnityEngine.Random.Range(minSpawnRange, maxSpawnRange);
z = UnityEngine.Random.Range(minSpawnRange2, maxSpawnRange2);
return new Vector3(x, y, z);
}
IEnumerator becomeHungry()
{
while (true)
{
hunger -= 1;
yield return new WaitForSeconds(1);
Debug.Log(hunger);
}
}
}
Spawner Script is on the Main Camera. Player used is the First Person Player Unity provides.
Code for destroying spawned object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class destroyVial : MonoBehaviour
{
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "vials")
{
Destroy(col.gameObject);
Debug.Log("yell");
}
}
}
Destroy code is on prefab. Note prefab is not in hierarchy as it should not be.
Firstly,
I see that you're spawning things in a for-loop and overwriting the vialss variable every time:
for (int i = 0; i < numOfVials; i++)
{
vialss = Instantiate(vialOfBlood,
SpawnPosition(),
Quaternion.identity) as GameObject;
}
And then, on collision, you're Destroying vialss, which in this case will be the latest spawned object. And if you collide with anything after 1 collision, vialss will already be deleted and probably throw an exception. Maybe that's fine in your game, but the logic looks a bit flawed.
Also, I'm assuming you want to destroy the object you're colliding with? Does something like this not work?
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "vials")
{
Destroy(col.gameObject); // <== Remove colliding object
Debug.Log("yell");
}
}
If you, for some unrelated reason, need a list of all your spawned vials, maybe you'd like to convert that to a list instead:
List<GameObject> spawnedVials = new List<GameObject>();
void SpawnVials()
{
for (int i = 0; i < numOfVials; i++)
{
var vial = Instantiate<GameObject>(vialOfBlood,
SpawnPosition(),
Quaternion.identity)
spawnedVials.Add(vial);
}
}
Finally,
make sure that the collision detection is working. You're saying that the script is attached to your camera. please make sure you have a Collider on the camera. But you're saying that other colliders are working, so I'm guessing you have this under control.
I'd guess your issue lies in the flawed logic I initially described.
OnTriggerEnter needs to be on a script attached to the object it's colliding with, or the vial itself. It can't be on the main camera as OnTriggerEnter will never get called.
I would recommend you to keep scripts to one job, you should split that script into a Spawn script and a Collider script. And create a empty GameObject with the sole purpose of spawning prefabs.
Also there's some errors in your code:
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "vials")
{
Destroy(col.gameObject); // Destroy the gameObject you're colliding with
Debug.Log("yell");
}
}
Also the variable vialss isn't doing what you're expecting, vialss is only referencing to the last instantiated vial, so better save all vials in a List:
List<GameObject> vialsInstantiated = new List<GameObject>();
And then:
void SpawnVials()
{
for (int i = 0; i < numOfVials; i++)
{
vialsInstantiated.Add(Instantiate(vialOfBlood, SpawnPosition(), Quaternion.identity) as GameObject);
}
}

Unity 2D - How to place obstacle in Running game?

I finish making running game. But I placed obstacle like this :
This way makes phone frozen often. So I make a prefeb is made of obstacle object like this :
I want to use function SetActive(bool) to appear/disappear obstacle. Finally, How it works is My runner is at a standstill and background, obstacle, coin, juwel is moved. But My creator script has a big problem.
My Prolem :
As you see, This code create blank(red box) between two obstacle prefebs. I can't find problem. Plz help me...
Creator Script :
using UnityEngine;
using System.Collections;
public class CsPartCreator : MonoBehaviour {
int count = 1;
float timer = 0.0f;
// Use this for initialization
void Start () {
for (int i = 1; i < 26; i++)//set Deactive all object excluding first object (Because This object is watched at first.)
transform.GetChild(i).gameObject.SetActive(false);
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
if (timer > 5f && count < 23)//every 5 seconds and count is smaller than the number of prefeb
{
transform.GetChild(count).gameObject.SetActive(true);//
count++;
timer = 0;
}
}
}
This is my Hierarchy :
I think , That missing prefab's Z value is more negative than background , Or you have used a sorting layer which is set to be behind background.
And Check if all obstacle gameobjects correctly orderered in Hirachy Part0, Part1, Part2, Part3 like that. Let me know if those are in correct order
Please check that :)
using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
public class CsPartCreator : MonoBehaviour
{
private GameObject player;
float timer = 0.0f;
private List<GameObject> obstacles;
void Awake()
{
player = GameObject.FindWithTag("Player");
obstacles = new List<GameObject>();
}
// Use this for initialization
void Start()
{
for (int i = 0; i < 26; i++)//set Deactive all object excluding first object (Because This object is watched at first.)
{
obstacles.Add(transform.GetChild(i).gameObject);
transform.GetChild(i).gameObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
if (obstacles == null || obstacles.Count() == 0)
return;
var toActivate = obstacles.Where(x => x.transform.position.x > transform.position.x && x.transform.position.x < transform.position.x + 10).ToList(); // +10 is the range
foreach (GameObject go in toActivate)
{
go.SetActive(true);
obstacles.Remove(go);
}
}
}
Set player gameobject to "Player" tag as in image below

Incorrect text on screen

Hi I'm new to this unity and I'm making a 2d game the problem.I'm facing is displaying the right text in the screen , e.g I have a score count for keeping track of score and then I'm displaying this text through count.text , HOWEVER the problem is that when the game starts the text on screen displays "0", score is 0 as well, then I shoot an apple and the score becomes 1 as well as the count.text also becomes 1 however the text is still 0 on the screen, when I shoot another arrow the score and count.text shows value of 2 however on the screen it shows 1 and so on. I followed unity tutorial of roll the ball. here is my code
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class arrowcounttutorial : MonoBehaviour {
public GameObject Arrow;
public GameObject apple;
public int score = 0;
public Text count;
// Use this for initialization
void Start () {
this.gameObject.GetComponent<Rigidbody2D> ().AddForce (transform.right*1500.0f);
//score = 0;
//showcounttext ();
count.text = score.ToString ();
}
// Update is called once per frame
void Update () {
Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
diff.Normalize();
float rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rot_z - 0);
if (Input.GetMouseButtonUp (0)) {
GameObject bullet_new;
bullet_new = Instantiate (Arrow,new Vector2 (-0.23f, -3.78f), Quaternion.identity) as GameObject;
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition),Vector2.zero);
if (hit.collider!= null ) {
LeanTween.move(bullet_new, hit.collider.transform.localPosition, 1);
if(hit.collider.tag == "fruit")
{
score++;
//showcounttext();
count.text = score.ToString ();
print(count.text);
Destroy(hit.collider.gameObject,1);
Destroy(bullet_new,1);
}
}
}
}
/*
void showcounttext(){
count.text = score.ToString ();
}
*/
}
Also if I initialize the score in void start the text remains 0 through out the level even if the score and count.text are 1,2,3,4,5 so on. What can I do?
UPDATE
I don't know how it worked but I called an invoke function Invoke ("showcounttext",1); and it worked. I won't delete the question in case someone else have this same problem :)
I see your answer, good that it is fixed but it is not the best solution.
Prior to Unity3D version 5.3.1p3 this engine had problems with updating canvases, and sometimes the UI content was disapearing. You didnt tell version you use, but I am almost sure in this case it would help calling
Canvas.ForceUpdateCanvases ();
In your code it should look like that:
if(hit.collider.tag == "fruit")
{
score++;
//showcounttext();
count.text = score.ToString ();
print(count.text);
Destroy(hit.collider.gameObject,1);
Destroy(bullet_new,1);
Canvas.ForceUpdateCanvases ();
}
Try this, or upgrade Unity3D.

Unity - Infinite sprite spawner stops spawning at a high speed

i wrote a script for my 2D car game for an infinite track. So i got a "killer" behind my car, that destroys all ground objects coming out the screen on the left and on the right i have a spawner that spawns all my blocky sprites in it and it works pretty good.
Here is my update function:
void Update()
{
if(Mathf.Round(this.transform.position.x) == limit)
{
//Debug.Log("Limit reached");
limit += 10;
Spawn();
}
}
I attached the script to my camera and i have a start limit set to 160 (because i already got 15 10x10 sprites as start). Everytime my spawner passes the x-axis-limit it spawns a new sprite at this position and sets the next limit 10 higher. This works good if I don't drive too fast. Because then it stops spawning and the world is cut off. When I drive back to get my spawner back into the already spawned area and drive slowly again to it, it works again. I believe the method is just to inefficient to spawn fast enough so I maybe need another style of doing it.
For the understanding here the rest of the script:
using UnityEngine;
using System.Collections;
public class Spawner : MonoBehaviour
{
public GameObject[] obj;
private int limit = 160;
public int yAxisValue = -1;
public bool isOnlyDirt;
private ArrayList rotationValues = new ArrayList();
void Start()
{
//Spawn ();
int value = 0;
for(int i = 0; i < 4; i++)
{
rotationValues.Add(value);
//Debug.Log(rotationValues[i]);
value += 90;
}
}
void Spawn()
{
Vector3 pos = new Vector3 (Mathf.Round(transform.position.x), yAxisValue, transform.position.z);
Quaternion rotation = new Quaternion (0, 0, 0, 0);
if(isOnlyDirt)
{
int zRot = (int)rotationValues[Random.Range(0, rotationValues.Count - 1)];
//Debug.Log(zRot);
rotation = new Quaternion(0, 0, zRot, 0);
}
var SpawnedGround = Instantiate(obj[Random.Range(0, obj.GetLength(0))], pos, rotation);
(SpawnedGround as GameObject).gameObject.tag = "Gro
I also have a one-liner to move my spawner in front of my car so it can spawn things:
public float yCoord;
void Start ()
{
this.transform.position = new Vector3 (transform.position.x + 160, -yCoord, transform.position.z);
}
I parented it so i just have to write it in the start function.
Any ideas to improve this one?
Thanks
Sorry can't post as comments. You should try
if(Mathf.Round(this.transform.position.x) >= limit)
instead of
if(Mathf.Round(this.transform.position.x) == limit)
I think the floating point precision is skipping the checking.