Enemies stop spawning after x amount have spawned/been destroyed? - c#

I am very new to c# and I've come across a problem with my enemy spawner. I am making an endless top-down shooter, and after 20 enemies have been spawned and then destroyed, the enemies stop appearing. My score counter continues to increase though, which leads me to believe they're somehow being destroyed.
Here is the enemy spawn controller:
void Update()
{
if (!spawningObject && GameController.EnemyCount < spawnSettings[0].maxObjects)
{
spawningObject = true;
float pick = Random.value * totalWeight;
int chosenIndex = 0;
float cumulativeWeight = enemySpawnables[0].weight;
while(pick > cumulativeWeight && chosenIndex < enemySpawnables.Count - 1)
{
chosenIndex++;
cumulativeWeight += enemySpawnables[chosenIndex].weight;
}
StartCoroutine(SpawnObject(enemySpawnables[chosenIndex].type, Random.Range(spawnSettings[0].minWait / GameController.DifficultyMultiplier, spawnSettings[0].maxWait / GameController.DifficultyMultiplier)));
Spawn();
}
}
private IEnumerator SpawnObject(string type, float time)
{
yield return new WaitForSeconds(time);
randomSpawnPoint = Random.Range(0, enemySpawners.Length);
randomEnemy = Random.Range(0, enemy.Length);
enemyPool.SpawnObject(enemySpawners[randomSpawnPoint].position, transform.rotation);
spawningObject = false;
GameController.EnemyCount++;
}
And here is the enemy controller (attached to enemy prefab):
public void Start()
{
myRB = GetComponent<Rigidbody>();
player = FindObjectOfType<PlayerController>();
}
private void OnEnable()
{
player = FindObjectOfType<PlayerController>();
}
void Update()
{
if (health <= 0)
{
Die();
}
}
void FixedUpdate()
{
transform.LookAt(player.transform.position);
myRB.velocity = (transform.forward * moveSpeed);
//Falling
if(myRB.velocity.y < 0)
{
myRB.velocity += Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
}
}
public void Die()
{
print("Enemy" + this.gameObject.name + " has died!");
EnemySpawn.instance.enemyPool.ReturnObject(this.gameObject);
player.GetComponent<PlayerController>().points += pointsToGive;
ScoreController.scoreValue += 1;
}
The only thing that should affect enemy health is the bullet. Here is the part of the bullet controller that affects enemy health:
public void OnTriggerEnter(Collider other)
{
if(other.tag == "Enemy")
{
triggeringEnemy = other.gameObject;
triggeringEnemy.GetComponent<EnemyController>().health -= damage;
PlayerController.instance.bulletPool.ReturnObject(gameObject);
}
}
The issue always happens after 20 enemies have been spawned/destroyed and 20 points have been achieved. Before then, enemy movement is normal and everything seems to be working as it should. It could very well be something very simple that I'm missing, but I'd appreciate any help!

When you do engage logic mistake good way to find it is Visual Studio debugging.
Here is good official article about whole process - https://docs.unity3d.com/Manual/ManagedCodeDebugging.html.
I would place breakpoint right at start of Update method to see that EnemyCount increases over time and then you will understand that you forgot to do decrement it.

Related

My rb2d gravity scale is set to 0 yet I still fall when I press the down arrow on my ladder

I'm making a ladder for my Unity game. Nothing much happens when you hover over it (that's normal). I want to freeze gravity by setting gravityscale 0 whenever the up arrow key is pressed (or w). Thankfully that works. Unfortunately though whenever I go down, gravity is still 0 but somehow my character falls back to the ground.
Here's my player code. Sorry the formatting is very bad; I just deleted the things that didn't have to do with ladders so you won't read irrelevant details.
// ladder
public float climb;
public float climbspeed;
public float gravitystore;
public bool laddered;
public GameObject laddercheck;
public float upaxis;
public xpositionladdercheck ladderx;
// Start is called before the first frame update
void Start()
{
ladderx = FindObjectOfType<xpositionladdercheck>();
jumptimecounter = Jumptime;
jumpscriptbetter = FindObjectOfType<BetterJump>();
gameover = false;
respawnscreen = FindObjectOfType<RespawnIntermission>();
lives = 5;
atkindex = FindObjectOfType<attackindex>();
scale =transform.localScale;
basicattackscript = FindObjectOfType<BasicAttack>();
basicattacksupply = 0;
rb = GetComponent<Rigidbody2D>();
gravitystore = rb.gravityScale;
}
// Update is called once per frame
private void Update()
{
horimove = Input.GetAxis("Horizontal");
if (isDead == false)
{
upaxis = Input.GetAxis("Vertical");
anim.SetFloat("run", Mathf.Abs(horimove));
if (Input.GetKeyDown(KeyCode.Space) && laddered)
{
jumpladder();
}
anim.SetFloat("run", Mathf.Abs(horimove));
if (laddered && Mathf.Abs(upaxis) > .01)
{
rb.gravityScale = 0;
climbm();
} else if (!laddered)
{
rb.gravityScale = gravitystore;
}
if (laddered&&Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine("jumpable");
}
rb.velocity = new Vector2(speed * horimove * Time.fixedDeltaTime, rb.velocity.y);
if (Input.GetKey(KeyCode.Space) && OnGround)
{
jump();
}
}
}
IEnumerator jumpable()
{
laddercheck.SetActive(false);
yield return new WaitForSeconds(.8f);
laddercheck.SetActive(true);
}
void climbm()
{
if (laddered)
{
if (upaxis > .1f) {
} else if (!laddered)
{
rb.constraints = RigidbodyConstraints2D.FreezeRotation;
}
rb.velocity = Vector2.up * climbspeed * upaxis *Time.deltaTime;
transform.position = new Vector2(ladderx.ladderxpos, rb.position.y);
// the ladder.x things is just a script that gets the x position of the ladder but it works well so ignore that.
}
}
public void jump()
{
}public void jumpladder()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector2.up * jumpforce * Time.fixedDeltaTime);
}
}
}
}
I set mass to the lowest (.0001) and still the same thing happens. I didn't include the ladderx position script or the sensing that I'm even on a ladder script but that's irrelevant to the question. It senses everything just fine and the xposition script works well as well.
I figured it out. For some reason I had to set the Physics2D.gravity to new Vector2 (0,0); whenever I climb the ladder. Then I made a vector 2 physgravity variable that stores the natural gravity and set it back to that whenever I leave the ladder.
public Vector2 physgravity;
physgravity = Physics2D.gravity;
Physics2D.gravity = new Vector2(0f, -9.81f);
private void Update()
{
if (!laddered)
{
Physics2D.gravity = new Vector2(0f, -9.81f);
}
____________________ (later on in the script)
if (laddered && Mathf.Abs(upaxis) > .01)
{
rb.gravityScale = 0;
Physics2D.gravity = new Vector2(0, 0);
rb.velocity = new Vector2(0, 0);
climbm();

Moving Object Not Stopping On Collision Unity

I am developing an infinite tower jumping game using Unity2D, and currently working on a continually moving object which causes the player to die if contact is made. The player can also die if they either fall off of a platform or off-screen. All methods of death rely on a BoxCollider2D I am using as a Killbox (tagged accordingly) - the player sprite has a RigidBody2D and BoxCollider2D attached to it - so there is one attached to the main camera (it moves as the player sprite progresses through the level) and to the top of the moving object.
The current code I have works up to the point where the game over screen appears on player death, but the object continues to move whilst everything else stops.
Here is my code for the moving object:
public class Water : MonoBehaviour {
private Collider2D playerCollider;
public ControllerNew thePlayer;
private float speed = 2f;
public GameManager theGameManager;
//reference scoremanager
private ScoreManager theScoreManager;
bool shouldMove = true;
// Start is called before the first frame update
void Start()
{
theScoreManager = FindObjectOfType<ScoreManager>();
thePlayer = FindObjectOfType<ControllerNew>();
lastPlayerPosition = thePlayer.transform.position;
}
// Update is called once per frame
void Update()
{
if (shouldMove = true)
{
transform.position += Vector3.up * speed * Time.deltaTime;
if (theScoreManager.scoreCount > 100 && shouldMove)
{
transform.position += Vector3.up * (speed+1) * Time.deltaTime;
}
if (theScoreManager.scoreCount > 250 && shouldMove)
{
transform.position += Vector3.up * (speed +2) * Time.deltaTime;
}
if (theScoreManager.scoreCount > 500 && shouldMove)
{
transform.position += Vector3.up * (speed+4) * Time.deltaTime;
}
if (theScoreManager.scoreCount > 1000 && theScoreManager.scoreCount > theScoreManager.hiScoreCount && shouldMove)
{
transform.position += Vector3.up * (speed+5) * Time.deltaTime;
}
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Player New")
{
transform.position += Vector3.zero * (speed * 0) * Time.deltaTime;
}
//call object by its tag
if (other.gameObject.tag == "Killbox")
{
shouldMove = false;
if (shouldMove = false){
theGameManager.RestartGame();
transform.position += Vector3.zero * (speed * 0) * Time.deltaTime;
}
}
}
Edit (Issue resolved)
So it turns out that after adding the Water.StopMoving() method into my controller script, the water had not been called as a GameObject in void Start(). Once this was added, the water object stopped on collision.
Just want to say thank you #D.B for your help and bearing with me - apologies if the info I gave wasn't everything you needed to be able to assist me
You made a mistake on the first line of the Update() method :
if (shouldMove = true)
You set the bool to true, not comparing it. Use double = otherwise it will set the bool to true at every frame.
if (shouldMove == true)
By the way you can simplify this part :
//call object by its tag
if (other.gameObject.tag == "Killbox")
{
shouldMove = false;
theGameManager.RestartGame();
transform.position += Vector3.zero * (speed * 0) * Time.deltaTime;
}
(You forgot a = too)
I made a test with this simplified script
void Update()
{
if (shouldMove == true)
{
Debug.Log("move");
transform.position += Vector3.up * speed * Time.deltaTime * GetDifficultyFactor();
}
}
private float GetDifficultyFactor()
{
float factor = 1f;
if(theScoreManager.scoreCount > 100)
{
factor += 1f;
}
if (theScoreManager.scoreCount > 250)
{
factor += 2f;
}
// Add all your speed modification condition here
return factor;
}
void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("trigger");
//call object by its tag
if (other.gameObject.tag == "Killbox")
{
Debug.Log("die");
shouldMove = false;
}
}
And it work fine. Are you sure you have a collider2D set to trigger on your charactert with the tag "Killbox" (with the first letter in uppercase ?). You should have a rigidbody2d on the character too.
Mistake come frome another part of your code or with some trouble with collider2D/tag/RigidBody2D. Without seeing all it's difficult to help you more.
You should try to add some Debug.Log() or use debugeur with breakpoint to be sure code enter into your "die" statement and then not going on the Update if statement. If yes, it's mean you probably set the shouldMove variable in another part of your script.
Answer regarding discussion in comments
I think you want to make this OnTriggerEnter2D logic in both script.
Without seeing all your project I suggest you to make a reference bewteen your character and your water script. Then when the player die the player script will call a method on water to stop it.
public class Player : MonoBehaviour
{
public Water Water;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Killbox")
{
Debug.Log("die");
Water.StopMoving();
}
}
}
public class Water : MonoBehaviour
{
private bool shouldMove;
public void Update()
{
...
}
public void StopMoving()
{
shouldMove = false;
}
// No Trigger logic here
}

Two way Platform Unity 2D Game Development

I am trying to make a platform that you can jump through and then when you press "Down" you can jump off the platform.
The problem is that when you press "Down" all the GameObjects on the platform fall down along with the player.
I managed to make a script using some tutorials that uses the "Platform Effector 2D" using this script.
private PlatformEffector2D effector;
public float waitTime;
void Start()
{
effector = GetComponent<PlatformEffector2D>();
}
void Update()
{
if(Input.GetKeyUp(KeyCode.S))
{
waitTime = 0.5f;
}
if(Input.GetKey(KeyCode.S))
{
if(waitTime <= 0)
{
effector.rotationalOffset = 180f;
waitTime = 0.5f;
}
else
{
waitTime -= Time.deltaTime;
}
}
if (Input.GetButtonDown("Jump"))
{
effector.rotationalOffset = 0;
}
}

Why my enemy not moving towards target

Here is a Video also - http://tinypic.com/r/mmagki/9
Here is my start () function
void Start()
{
target = GameObject.FindGameObjectWithTag("Player").transform;
}
and update() function
void Update()
{
transform.LookAt(target);
float step = speed * Time.deltaTime;
distance = (transform.position - target.position).magnitude;
//Debug.Log("Now distance -" + distance);
if (distance < 20)
{
// print("In Range");
transform.GetComponent<Animation>().Play("attack", PlayMode.StopAll);
if (isAttacking == false)
{
isAttacking = true;
Hit.playerHealth -= Random.Range(20f, 25f) * Time.deltaTime;
Hit.playerHealth -= Random.Range(20f, 25f);
// StartCoroutine(MyCoroutine(4));
// print("Player Health Status = " + Hit.playerHealth);
if (Hit.playerHealth <= 0)
{
// print("Player dead");
}
}
else
{
}
}
else
{
// print("Out of Range");
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
transform.GetComponent<Animation>().Play("walk", PlayMode.StopAll);
}
}
My Zombie (Enemy) is approaching Player, when Zombie gets hit with the wall, he should go to gate.
What i did, as soon as Zombie (Set Trigger = checked) hit with the wall, i have changed the reference of 'target' to Object with tag 'gate'.
Now the Zombie is not moving towards gate object (i have set tag 'gate' also). he is still moving towards player only. Not able to change the reference of target.
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "wall")
{
target = GameObject.FindGameObjectWithTag("gate").transform;
Debug.Log("Yes its a onTrigger Enter function , hitting with wall");
}
}
It looks like you don't have a collider on your gate. Adding a collider to the gate should do the trick.
first verify the tags of all are seted correctly, then you need to add a rigidbody component at least in one of the objects as Unity Docs say: OnTriggerEnter . I recomend to add it to the zombie and set UseGravity to false. and with this it should work... sorry for bad english.

Stuck with spawning objects in Unity

I'm making a 'run' game in Unity and I'm making a prototype with a ball, that has other balls following him. If the followers hit an object they get destroyed after some time. To make it so you don't run out of enemies I made a trigger that spawns new enemies. In the code this is the function Addzombies.
How do I make them spawn not on the same point, if i run it now they
start on eachother and bounce around as an explosion.
How do i make some start in the air, i tried it but they don't
spawn.
My code:
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
public float InputForce;
public GUIText guiText;
public float rotationHorizontal;
public AudioClip ACeffect2;
public GameObject zombiePrefab;
void FixedUpdate() {
rigidbody.AddForce( Camera.main.transform.right * Input.GetAxis("Horizontal") * InputForce);
rigidbody.AddForce( Camera.main.transform.forward * Input.GetAxis("Vertical") * InputForce);
transform.position += Vector3.forward *InputForce * Time.deltaTime;
rotationHorizontal = Input.GetAxis("Horizontal") * InputForce;
rotationHorizontal *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotationHorizontal);
}
void OnCollisionEnter(Collision col){
if (col.gameObject.name == "Zombie") {
Debug.Log ("Player geraakt, nu ben je eigenlijk dood");
}
if (col.gameObject.name == "Obstakel1") {
Debug.Log ("Obstakel1 geraakt");
audio.PlayOneShot(ACeffect2);
InputForce = 0;
}
if (col.gameObject.name == "Obstakel2") {
Debug.Log ("Obstakel2 geraakt");
}
}
void AddZombies(int aantal){
for (int i = 0; i < aantal; i++){
GameObject go = GameObject.Instantiate(zombiePrefab, transform.position - new Vector3(0, 0, 7 + i),Quaternion.identity) as GameObject;
Zombie zb = go.GetComponent<Zombie>();
zb.target = gameObject.transform;
}
}
void OnTriggerEnter(Collider col) {
Debug.Log ("Enter" +col.name);
if (col.tag == "AddZombies"){
AddZombies(4);
}
}
void OnTriggerExit(Collider col) {
Debug.Log ("Leaving with" +col.name);
}
}
I will advice on how things could be done, but you will have to make changes to make it suit your requirement
public Transform zombiePrefab; // From the editor drag and drop your prefab
void addZombies()
{
// as you need them to be not on the same point
int randomX = Random.Range(-10.0F, 10.0F);
for (int i = 0; i < aantal; i++){
// make a transform
var zombieTransform = Instantiate(zombiePrefab) as Transform;
zombieTransform.position = new Vector3(randomX, 0, 7 + i);
transform.GetComponent<Rigidbody>().enabled = false;
// make it enable when you need and add force to make them fall
}
}
I would suggest passing the number of zombies to pass, and an integer representing the range of space that they can spawn in. Then just use UnityEngine.Random with said integer for each zombie to produce several different co-ordinates for spawning the zombies.
As for getting them to spawn in the air, just increase the y co-ordinate when you instantiate the zombie.

Categories

Resources