Coroutine still running even if game is paused and time scale set to 0 - unity3d

As the title pointed out, for some reason when my game is paused my co-routine still runs. I even went as far as to put the time scale condition in a while condition so that the while doesnt run if it paused but to no avail. I've added my code in it's entirety and hope that someone will be able to assist.
using UnityEngine;
using System.Collections;
using Chronos;
public class ObjectSpawn : BaseBehaviour //MonoBehaviour
{
public float minTime = 3f;
public float maxTime = 9f;
public float minX = -65.5f;
public float maxX = -5.5f;
public float topY = -5.5f;
public float z = 0.0f;
public int count = 50;
public GameObject prefab;
public bool doSpawn = true;
public float fallGrav =1.0f;
int first = 1;
void Start()
{
Clock clock = Timekeeper.instance.Clock("MovingOneWayPlatforms");
StartCoroutine(Spawner());
}
IEnumerator Spawner()
{
while (first == 1) {
yield return time.WaitForSeconds(8.0f);
first = 0;
}
while (doSpawn && count > 0 /*&& time.timeScale != 0 */)
{
Renderer renderer = GetComponent<Renderer>();
float min = renderer.bounds.min.x;
float max = renderer.bounds.max.x;
Vector3 v12 = new Vector3(Random.Range(minX, maxX), this.gameObject.transform.position.y, 0f);
prefab.GetComponent<Rigidbody2D>().gravityScale = fallGrav;
prefab = Instantiate(prefab, v12, Random.rotation);
count--;
// yield return new WaitForSeconds(Random.Range(minTime, maxTime));
yield return time.WaitForSeconds(Random.Range(minTime, maxTime));
Destroy(prefab, 6);
}
}
}

Try to uncomment your 2nd while statement, I think that is your problem.

I am new and still not used to Chronos.
Maybe I'm wrong but my guess is this line.
Destroy(prefab, 6);
In my understanding, Destroy's delay should not affected by chronos.
You better use new Coroutine to destroy it.
like this
StartCoroutine(DestroyRoutine(prefab))
IEnumurator DestroyRoutine(GameObject gameobject)
{
yield return time.WaitForSeconds(6);
Destroy(gameObject)
}

Related

How Can I Not Make Points Spawn In The Same Place Twice? (Unity)

guys so I'm trying to make an endless Map Generator for my 2D grappling Hook Game Kinda like Danis square Game and I was trying to generate a set number of swingable points in certain range to test.
Everything works fine except that some Points overlap each other when spawned So I was wondering how could I prevent this from happening?
Should I change my code or is there any method of spawning things I should try so they don't overlap?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGenerator : MonoBehaviour
{
public Transform Endpositin;
public int NumOfSwwingablePoints;
public GameObject SwinggablePoint;
public int MinX, MaxX;
public int MinY, MaxY;
public int Xpos;
public int Ypos;
Vector2 PointPos;
void Start()
{
for (int i = 0; i <= NumOfSwwingablePoints; i++)
{
Xpos = Random.Range(MinX, MaxX);
Ypos = Random.Range(MinY, MaxY);
PointPos = new Vector2(Xpos, Ypos);
Instantiate(SwinggablePoint, PointPos, Quaternion.identity);
}
}
// Update is called once per frame
void Update()
{
}
}
I have Tried this Method and I have also tried to increase values and giving the points colliders to see if they overlap but none of that works. I have also tried update function, but they just keep spawning, and it never stops
My suggestion is everytime you create a new block then save the position of the block in a list.
when next time you create a new block, check the new position with the list.
Here is the code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGenerator : MonoBehaviour
{
public Transform Endpositin;
public int NumOfSwwingablePoints;
public GameObject SwinggablePoint;
public int MinX, MaxX;
public int MinY, MaxY;
private int Xpos;
private int Ypos; // this can be private since we use only privatly
Vector2 PointPos;
List<Vector2> PointPosList = new List<Vector2>();
void Start()
{
for (int i = 0; i < NumOfSwwingablePoints; i++) // I change <= to < since we start from 0
{
Generating();
}
}
void Generating()
{
bool foundSamePosition;
do
{
foundSamePosition = false;
Xpos = Random.Range(MinX, MaxX);
Ypos = Random.Range(MinY, MaxY);
PointPos = new Vector2(Xpos, Ypos);
// finding the generated position is already exist
for (int i = 0; i < PointPosList.Count; i++)
{
if (SamePosition(PointPos, PointPosList[i]))
{
foundSamePosition = true;
}
}
} while (foundSamePosition);// if we found the position try again
// if not found, add the new position to a list for next time check
PointPosList.Add(PointPos);
Instantiate(SwinggablePoint, PointPos, Quaternion.identity);
}
private bool SamePosition(Vector2 v1, Vector2 v2)
{
return (v1.x == v2.x && v1.y == v2.y);
}
}

How can I prevent a certain piece of code from running when my player reaches a specific score for a certain time?

I'm currently developing a game in Unity and I have a problem. When my player reaches a certain score, in this case, the score of 5 I change the way the obstacles encounter behave. However, for some reason on certain specific occasions when the player reaches the score of 5, I'm assuming when the score of 5 is reached at the exact same time as when the obstacles are being spawned the Obstacles spawn according to the the behaviour required before the score reached 5 but move according to the behaviour required after the score reached 5 instantly as the score of 5 is reached. This shouldn't happen. As the score of 5 is reached the game should keep the behaviour of the obstacles the same as if the score was still smaller than 5 for a second and then switch.
I've already tried to using a coroutine to solve this issue as shown in the code below, however this obviously doesn't work unless I find a way to put the entire class into the coroutine, which will be very messy. I've also tried to suspend the spawning of the obstacles for a second while the score increments from 4 to 5 using a coroutine in the class responsible for spawning the obstacles. However this didn't work
This is the class responsible for the movement of the obstacles:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InteractControl : MonoBehaviour, IPooledObject
{
private Rigidbody2D rb;
GameObject target;
Vector3 directionToTarget;
public static int LevelStart = 0;
//public GameObject[] Balls;
Renderer m_Renderer;
public static float moveSpeed = 5f;
public static bool isSlowMotion = true;
public void OnObjectSpawn()
{
if (ScoreScript.scoreValue > 4 && isSlowMotion)
{
moveSpeed = 10f;
}
target = GameObject.FindWithTag("White Ball");
rb = GetComponent<Rigidbody2D>();
MoveInteract(moveSpeed);
}
void MoveInteract(float moveSpeed)
{
if (target != null)
{
if (ScoreScript.scoreValue > 4 && ScoreScript.scoreValue < 11 && BallSpawnerControl.LevelTrans > 1)
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
else if (ScoreScript.scoreValue < 4)
{
directionToTarget = new Vector3(0, -1, 0);
rb.velocity = new Vector2(0, directionToTarget.y * moveSpeed);
}
}
else
{
GameObject.FindWithTag("ColouredBall Highress").SetActive(false);
}
}
void Update()
{
if (target != null)
{
if (ScoreScript.scoreValue > 10) //Determine when RedBall goes from going down in a straight line to following white ball
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
}
}
}
This is the class responsible for the spawning of the obstacles:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/*
* ObjectPooler.Instance.SpawnFromPool("Ball", Posi, Quaternion.identity );
* ObjectPooler.Instance.SpawnFromPool("Star", Posi, Quaternion.identity );
*/
public class BallSpawnerControl : MonoBehaviour
{
public static bool spawnAllowed;
public static int TimerOn = 1;
public Transform[] spawnPoints;
// public GameObject[] interact;
int randomSpawnPoint, Interact;
int index = 1;
ObjectPooler objectPooler;
public static int LevelTrans = 1;
// Use this for initialization
public void Start()
{
objectPooler = ObjectPooler.Instance;
spawnAllowed = true;
InvokeRepeating("SpawnAInteract", 0f, 1f);
}
void SpawnAInteract()
{
// Change this if statement to only run 1 second after the transition to level 2 has been initiated
if (spawnAllowed)
{
if(ScoreScript.scoreValue > 4 && LevelTrans == 1)
{
StartCoroutine(LevelTransition());
}
else
{
if (index % 5 != 0)
{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
Interact = 1;
// var i = Instantiate(interact[Interact], spawnPoints[randomSpawnPoint].position, Quaternion.identity);
objectPooler.SpawnFromPool("Ball", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
//randomSpawnPoint = Random.Range(0, spawnPoints.Length);
index++;
}
/*if (index % 5 != 0)
{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
objectPooler.SpawnFromPool("Clock", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
} */
else
{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
Interact = 0;
// var i = Instantiate(interact[Interact], spawnPoints[randomSpawnPoint].position, Quaternion.identity);
objectPooler.SpawnFromPool("Star", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
//if (TimerOn == 1)
//{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
objectPooler.SpawnFromPool("Clock", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
objectPooler.SpawnFromPool("Heart", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
// TimerOn++;
// }
index++;
}
}
}
}
private IEnumerator LevelTransition()
{
yield return new WaitForSeconds(1f);
LevelTrans++;
Debug.Log( "Level Trans :" + LevelTrans);
}
}
Thanks in advance
This is the interface from which OnObjectspawn derives from:
using UnityEngine;
public interface IPooledObject
{
void OnObjectSpawn();
}

Unity 2D Camera Zooms in when character moves, but properties of the camera do not change

After I click play the camera stays as it should be, but when I move my character the camera zooms in for no reason
The properties of the camera do not change at all, zoom and everything stays the same. Tryed changing from orthographic to perspective no change, move z axis no change, change scale no change, change resolution and no change, making the camera not a parent and no change it behaves the same as parent and as child
before character walks
after character walks
I dont think that there is something to do with the code but here is the code attached to my character, the camera behaves the same as child and as parent
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
public float speed = 5f;
public float jumpSpeed = 8f;
private float movementX = 0f;
private Rigidbody2D rigidBody;
public Transform groundCheckPoint;
public float groundCheckRadius;
public LayerMask groundLayer;
public bool isTouchingGround;
public SpriteRenderer box;
private bool canSpawn = true;
private bool canAnimateWalk = true;
private bool canAnimateIdle = true;
private bool canAnimateJump = true;
private bool stopJump = true;
private int spawningSpeed = 1000;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
isTouchingGround = Physics2D.OverlapBox(groundCheckPoint.position,new Vector2(0.9f,0.1f),0f, groundLayer);
movementX = Input.GetAxis("Horizontal");
if (movementX > 0f)
{
if(canAnimateWalk==true && isTouchingGround)
{
canAnimateWalk = false;
StartCoroutine(AnimateWalk());
}
GetComponent<SpriteRenderer>().transform.localScale = new Vector3(2, 2, 1);
rigidBody.velocity = new Vector2(movementX * speed, rigidBody.velocity.y);
}
else if (movementX < 0f)
{
if (canAnimateWalk == true && isTouchingGround)
{
canAnimateWalk = false;
StartCoroutine(AnimateWalk());
}
GetComponent<SpriteRenderer>().transform.localScale = new Vector3(-2, 2, 1);
rigidBody.velocity = new Vector2(movementX * speed, rigidBody.velocity.y);
}
else
{
if(isTouchingGround)
{
StopCoroutine(AnimateWalk());
if(canAnimateIdle==true)
{
canAnimateIdle = false;
StartCoroutine(AnimateIdle());
}
}
rigidBody.velocity = new Vector2(0, rigidBody.velocity.y);
}
if (Input.GetButtonDown("Jump") && isTouchingGround)
{
canAnimateJump = false;
rigidBody.velocity = new Vector2(rigidBody.velocity.x, jumpSpeed);
StartCoroutine(AnimateJump());
}
else if(!isTouchingGround)
{
StopCoroutine(AnimateWalk());
}
}
IEnumerator AnimateJump()
{
Debug.Log("Animating Jump");
int counter = 0;
while (counter < 10)
{
counter++;
GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("img/j" + counter);
yield return new WaitForSeconds(0.1f);
if(isTouchingGround==true)
{
break;
}
}
while(!isTouchingGround)
{
GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("img/j10");
yield return new WaitForSeconds(0.1f);
}
GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("img/i1");
canAnimateWalk = true;
canAnimateJump = true;
}
IEnumerator AnimateIdle()
{
int counter = 0;
while(Input.GetAxis("Horizontal")==0 && counter <10 && rigidBody.velocity.y==0)
{
counter++;
GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("img/i"+counter);
yield return new WaitForSeconds(0.2f);
}
canAnimateIdle = true;
}
IEnumerator AnimateWalk()
{
int counter = 0;
while (Input.GetAxis("Horizontal")!=0 && counter < 8 && rigidBody.velocity.y==0)
{
counter++;
GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("img/g" + counter);
yield return new WaitForSeconds(0.08f);
}
canAnimateWalk = true;
}
}
What could it be? I tried everything I think
GetComponent<SpriteRenderer>().transform.localScale = new Vector3(-2, 2, 1);
If your movement script is attached to your "guy" gameobject, then you are changing the (local) scale of it. All children will also scale accordingly.
Since your camera is a child of guy, it will scale and produce the result you see.
Try unparenting the Camera from your guy and create a seperate script that follows your guy and attach that to your Camera.
I solved my problem
The issue was in the character scaling. The camera did not change but the size of the character did making me believe that there was a zoom in.
My character x and y scale is 1 and 1 but I used 2 and 2 scale on move
The scale was used to rotate my character when it moves left and right

Unity- Moving an Object to the left on a Scrolling Background

I am trying to create a simple Infinite Runner game on Unity and ran into a problem. The task is to make a ball spawn on the floor and immediately begin to roll to the left towards the Player. I have tried a number of ways to implement it, but it does not seem to work. Here is my most recent attempt:
public class ObstaclePool : MonoBehaviour {
public GameObject columnPrefab;
public GameObject ballPrefab;
public int obstaclePoolSize = 5;
public float spawnRate = 3f;
private GameObject[] obstacles;
private int currentObstacle = 0;
private Vector2 objectPoolPosition = new Vector2(-15, -25);
private float timeSinceLastSpawned;
private float spawnXPosition;
private bool hasCalled = false;
private int dice;
bool beforeBall = false;
// Use this for initialization
void Start () {
timeSinceLastSpawned = 0f;
SetupObstacles();
}
private void SetupObstacles()
{
obstacles = new GameObject[obstaclePoolSize];
for (int i = 0; i < obstaclePoolSize; i++)
{
dice = Random.Range(1, 3);
if (dice == 1)
{
obstacles[i] = (GameObject)Instantiate(columnPrefab, objectPoolPosition, Quaternion.identity);
}
else if (dice == 2)
{
obstacles[i] = (GameObject)Instantiate(ballPrefab, objectPoolPosition, Quaternion.identity);
}
}
}
// Update is called once per frame
void Update () {
timeSinceLastSpawned += Time.deltaTime;
if (GameControl.instance.gameOver == false && timeSinceLastSpawned >= spawnRate)
{
timeSinceLastSpawned = 0f;
if (hasCalled == false)
{
spawnXPosition = 10f;
hasCalled = true;
}
else
{
spawnXPosition = Random.Range(6f, 10f);
}
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
else {
if (beforeBall == true)
{
spawnXPosition = Random.Range(9f, 10f);
beforeBall = false;
}
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -7.08f);
Debug.Log(spawnXPosition);
}
currentObstacle++;
if (currentObstacle >= obstaclePoolSize)
{
currentObstacle = 0;
SetupObstacles();
hasCalled = false;
}
}
}
}
For a quick explanation of my code: I have an array of size 5. It holds the obstacles that I have created. When deciding what to put inside the array, I generated a random number (1 or 2). If it's a 1, I put in a column. If it's a 2, I put in a ball. These obstacles are spawned off-screen. Then, I move them in the actual scene after using random number to determine the X position.
This part in particular is where I try to implement it:
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
I may have some remnants of stuff that I have been testing out, so some of the code may seem redundant and messy.
I also tried using Translate and Velocity with no success. I also have a ScrollingObject code and a RepeatingBackground code. I placed the ScrollingObject code in the Ball prefab too. (Also, tried taking it out -> ball rolls to the right). These codes come from the Unity tutorial.
RepeatingBackground:
public class RepeatingBackground : MonoBehaviour {
private BoxCollider2D groundCollider;
private float groundHorizontalLength;
// Use this for initialization
private void Awake () {
groundCollider = GetComponent<BoxCollider2D>();
groundHorizontalLength = groundCollider.size.x;
}
// Update is called once per frame
private void Update () {
if (transform.position.x < -groundHorizontalLength)
{
RepositionBackground();
}
}
private void RepositionBackground()
{
Vector2 groundOffSet = new Vector2(groundHorizontalLength * 2f, 0);
transform.position = (Vector2)transform.position + groundOffSet;
}
}
ScrollingObjects:
public class ScrollingObject : MonoBehaviour {
private Rigidbody2D rb2d;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D>();
rb2d.velocity = new Vector2(GameControl.instance.scrollSpeed, 0);
}
// Update is called once per frame
void Update () {
if (GameControl.instance.gameOver == true)
{
rb2d.velocity = Vector2.zero;
}
}
}
It looks like you simply named the wrong object in your first example.
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
Notice how here you added the force to the prefab, not an instantiated version of the prefab.
I played around a bit more and got it to work. I just wrote another script that added force to the object. I still do not understand why my original way did not work though.

Lifting platforms is not working as it should

I would like to make some lifting platforms in my game, so if the platform went down, the characters can't go over it. I have written a script for it, but for some reason the "lifting up" is not working as intended. It won't go back to its starting place, but it will go a bit below. And for some reason it won't go smoothly to the place where it should, just "teleport" there and done. I thougt multiplying Time.deltaTime with a const will help, but it is the same.
Here is my code, any help would be appreciated:
public class LiftingPlatform : MonoBehaviour {
private Transform lift;
private bool isCanBeLifted;
private float timeToLift;
public float timeNeededToLift = 5f;
private Vector3 startPos;
private Vector3 downPos;
private Vector3 shouldPos;
private bool isDown;
public GameObject[] collidingWalls;
// Use this for initialization
void Start () {
lift = transform;
isCanBeLifted = true;
timeToLift = 0f;
isDown = false;
startPos = transform.position;
downPos = new Vector3(startPos.x, startPos.y - 5f, startPos.z);
}
// Update is called once per frame
void Update () {
timeToLift += Time.deltaTime;
if (timeToLift >= timeNeededToLift) {
if (isCanBeLifted) {
if (isDown) {
shouldPos = Vector3.Lerp(startPos, downPos, Time.deltaTime * 10);
lift.position = new Vector3(shouldPos.x, shouldPos.y, shouldPos.z);
isDown = true;
}
else if (!isDown) {
shouldPos = Vector3.Lerp(downPos, new Vector3(startPos.x, startPos.y, startPos.z), Time.deltaTime * 10);
lift.position = new Vector3(shouldPos.x, shouldPos.y, shouldPos.z);
isDown = false;
}
}
timeToLift = 0;
}
if (!isDown) {
for (int i = 0; i < collidingWalls.Length; i++) {
collidingWalls[i].SetActive(true);
}
}
else if (isDown) {
for (int i = 0; i < collidingWalls.Length; i++) {
collidingWalls[i].SetActive(false);
}
}
}
void OnTriggerEnter(Collider collider) {
if (collider.tag == "Player" || collider.tag == "Enemy") {
isCanBeLifted = false;
}
}
void OnTriggerExit(Collider collider) {
if (collider.tag == "Player" || collider.tag == "Enemy") {
isCanBeLifted = true;
}
}
}
These lifting platforms are a child of another Platforms object.
It doesn't look like you are updating the object's position every frame. You are only checking if the total time passed is greater than the time needed to lift, and then updating the position to a value that is dependent on the delta time (using the Vector3.Lerp function).
What I would do is in the update step, if timeToLift is greater then timeNeededToLift, subtract the latter from the former and invert the value of isDown. Then, in your Vector3.Lerp, make the third argument (timeToLift / timeNeededToLift) instead of (Time.deltaTime * 10). Can you try that and see if it works?
The third argument for Vector3.Lerp is the "blending factor" between the two vectors, 0 is the first vector, 1 is the second, and 0.5 is in between. If the total time is greater than the time needed to lift, but the delta time is not greater than 1, it will get the position of the platform using a blending factor of less than 1, resulting in a platform that didn't move fully.