not exactly sure why. basically what I wanted to do is create a bullet hell game. so I would send a clone of a bullet to the gun, and then the gun would shoot the bullet depending on what direction it was facing. here is the code I used it is in c#. Edit: it crashes when I run the game.
using System.Collections.Generic;
using UnityEngine;
public class Bulletcontrol1 : MonoBehaviour
{
void Start()
{
StartCoroutine(Countinggggg());
}
// Update is called once per frame
void Shoot()
{
Debug.Log("clone");
GameObject prefab = Resources.Load("Picture1") as GameObject;
GameObject direction = GameObject.Find("b");
GameObject go = Instantiate(prefab) as GameObject;
go.transform.position = new Vector3(-23.25f, 8.75f, 1.494792f);
while (go.transform.position.x > -10)
{
Debug.Log("moving");
go.transform.position = new Vector3(go.transform.position.x + Mathf.Sin(direction.transform.rotation.z) * 5, go.transform.position.y + Mathf.Cos(direction.transform.rotation.z) * 5, go.transform.position.z);
}
}
IEnumerator Countinggggg()
{
yield return new WaitForSeconds(1);
Shoot();
Debug.Log("Bang");
}
}```
I have no idea what was wrong, but I changed the while loop to a for loop, and then noticed how the bullet did all it's moves at once: so I assume something with the while loop not ending and the bullet moving infinite spaces all at once caused it.
so I put in a a WaitForSeconds to slow it down, here is the code now
IEnumerator Shoot()
{
Debug.Log("clone");
GameObject prefab = Resources.Load("Picture1") as GameObject;
GameObject direction = GameObject.Find("b");
GameObject go = Instantiate(prefab) as GameObject;
go.transform.position = new Vector3(-10.13f, 3.52f, 1.494792f);
for (int i = 0; i < 100; i++)
{
Debug.Log("moving");
go.transform.position = new Vector3(go.transform.position.x + Mathf.Sin(direction.transform.rotation.z) * -0.1f, go.transform.position.y + Mathf.Cos(direction.transform.rotation.z) * -0.1f, go.transform.position.z);
yield return new WaitForSeconds(0.1f);
}
Related
I have a problem, I am trying to make the enemy shoot at the player every 5 seconds and right now it is just shooting lots of bullets constantly in a line.
This is my code, I would really appreciate some help!
void ShootAtPlayer()
{
StartCoroutine(bulletshooting());
IEnumerator bulletshooting()
{
shooting = true;
if (shooting == true)
{
GameObject tempBullet = Instantiate(enemyBullet, eyes.gameObject.transform.position, eyes.gameObject.transform.rotation) as GameObject; //shoots from enemies eyes
Rigidbody tempRigidBodyBullet = tempBullet.GetComponent<Rigidbody>();
tempRigidBodyBullet.AddForce(tempRigidBodyBullet.transform.forward * enemyBulletSpeed);
Destroy(tempBullet, 0.1f);
yield return new WaitForSeconds(5f);
}
shooting = false;
}
From your comment
shootAtPlayer is called in the update when the enemy is close enough to the player
The issue is: You are starting a new Coroutine every frame!
In your case I wouldn't use a Coroutine at all since you already have a code that is executed every frame. (Because otherwise you would need some code to also stop the running routine)
Rather use a simple timer:
[SerializeField] private float cooldown = 5;
private float cooldownTimer;
void ShootAtPlayer()
{
cooldownTimer -= Time.deltaTime;
if(cooldownTimer > 0) return;
cooldownTimer = cooldown;
GameObject tempBullet = Instantiate(enemyBullet, eyes.gameObject.transform.position, eyes.gameObject.transform.rotation) as GameObject; //shoots from enemies eyes
Rigidbody tempRigidBodyBullet = tempBullet.GetComponent<Rigidbody>();
tempRigidBodyBullet.AddForce(tempRigidBodyBullet.transform.forward * enemyBulletSpeed);
Destroy(tempBullet, 0.1f);
}
If you really want to use a Coroutine for that it would probably look like
private bool isShooting;
void ShootAtPlayer()
{
// Only allow a new routine if there is none running already
if(isShooting) return;
StartCoroutine (shootRoutine());
}
private IEnumerator shootRoutine()
{
// Just in case avoid concurrent routines
if(isShooting) yield break;
isShooting = true;
GameObject tempBullet = Instantiate(enemyBullet, eyes.gameObject.transform.position, eyes.gameObject.transform.rotation) as GameObject; //shoots from enemies eyes
Rigidbody tempRigidBodyBullet = tempBullet.GetComponent<Rigidbody>();
tempRigidBodyBullet.AddForce(tempRigidBodyBullet.transform.forward * enemyBulletSpeed);
Destroy(tempBullet, 0.1f);
yield return new WaitForSeconds (5f);
isShooting = false;
}
I am trying to get my GameObject (asteroid) to spawn continuously in the game. I looked up and followed this tutorial: https://pressstart.vip/tutorials/2018/09/25/58/spawning-obstacles.html. To make the asteroid move, I created this script (AsteroidObject) and to spawn the objects, I created this script (DeployAsteroids). There are no errors and the Debug.Log appears in the console. But the asteroid game object cannot be seen and will not spawn. Anyone can help? Thanks in advance!
Asteroid Object Codes:
public class AsteroidObject : MonoBehaviour
{
public float speed = 10.0f; //how fast the asteroid will move
private Rigidbody2D rb;
private Vector2 screenBounds; //screenbounds calculation
// Start is called before the first frame update
void Start()
{
rb = this.GetComponent<Rigidbody2D>(); //find rigidbody 2d and set it to rb reference by using the getcomponent
rb.velocity = new Vector2(-speed, 0); //moving the asteroid from right to left by setting the x value, leaving the y value 0 so that it will not move up and down
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z)); //defines the boundaries of the screen on the x and y axis
}
// Update is called once per frame
void Update()
{
//transform.position = new Vector3(Mathf.Clamp(transform.position.x, -9f, 9f),
//Mathf.Clamp(transform.position.y, -4f, 4f), transform.position.z);
if (transform.position.x < screenBounds.x) //check if it is moving to the left of the screen
{
Destroy(this.gameObject);
Debug.Log("hello world");
}
}
}
DeployAsteroid codes:
public class DeployAsteroids : MonoBehaviour
{
public GameObject asteroidPrefab;
public float respawnTime = 1.0f;
private Vector2 screenBounds;
// Start is called before the first frame update
void Start()
{
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
StartCoroutine(asteroidWave());
}
private void spawnEnemy()
{
GameObject a = Instantiate(asteroidPrefab) as GameObject;
a.transform.position = new Vector2(screenBounds.x * -2, Random.Range(-screenBounds.y, screenBounds.y));
}
IEnumerator asteroidWave()
{
while (true)
{
yield return new WaitForSeconds(respawnTime);
spawnEnemy();
//Debug.Log("Hello World");
}
}
}
You even say it yourself
the Debug.Log appears in the console.
Well, you log in the moment you destroy your object => it is already gone.
Destroy(this.gameObject);
Debug.Log("hello world");
Unless you mean the out commented log after the spawn method. You still immediately destroy the object. I think you would spot it immediately if you would use useful logs and not twice the same one
Debug.Log("Spawned a new object");
and
Debug.Log("Destroyed an object");
So what exactly is happening then?
You immediately destroy the new spawned objects!
you do
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
which stores the position at the right border of the screen.
Let's say e.g. somewhere at x = 2; (total random imaginary example number).
Then right after spawning you set it to
a.transform.position = new Vector2(screenBounds.x * -2, Random.Range(-screenBounds.y, screenBounds.y));
So for the x you set it to (using our example value) x = -4;
This is not even the left boarder of the screen but even beyond!
Additionally you tell the asteroid to move
rb.velocity = new Vector2(-speed, 0);
so assuming the value speed is positive even more into negative x direction.
And finally you do
// Even without the Rigidbody this is already comparing
// if(-2 * screenBounds.x < screenBounds.x)
// Or with our example numbers
// if(-4 < 2)
if (transform.position.x < screenBounds.x)
{
Destroy(this.gameObject);
Debug.Log("hello world");
}
=> This condition will always be true and immediately destroys your objects in the next frame.
So what should I do instead?
I assume you are trying to spawn the asteroid at the right boarder.
And want to destroy it after it passed the left boarder. So it should probably be
private void spawnEnemy()
{
GameObject a = Instantiate(asteroidPrefab);
Vector3 rightEdgeWorldPoint = Camera.main.ScreenToWorldPoint(
new Vector3(Screen.width, Random.Range(0, Screen.height),
Camera.main.nearClipPlane);
rightEdgeWorldPoint.z = 0f;
a.transform.position = rightEdgeWorldPoint;
}
And in the asteroid
if (Camera.main.WorldToScreenPoint(transform.position).x < 0)
{
Destroy(this.gameObject);
Debug.Log("Left the screen -> destroyed");
}
Note: Typed on smartphone but I hope the idea gets clear
Go to the scene hierarchy and check if the asteroids can be seen there. May be you do not see them within the game or the scene camera, but if they are in the scene they are spawn somewhere. It would be interesting info to update in the question.
I did not dig into the code but if they are there, you need to check or set the position in which they are spawned respect to the camera, for the asterioids to be in the field of view.
Check the posistion given in this line: a.transform.position = new Vector2(screenBounds.x * -2, Random.Range(-screenBounds.y, screenBounds.y)); and if it fits in the camera field of view.
I wanted to use a coroutine to make the player wait a little before shooting a new bullet but it never gets past the yield. Here's the code
protected override void Start () {
base.Start ();
animator = GetComponent<Animator> ();
score = GameManager.instance.playerScore;
playerLives = GameManager.instance.playerLife;
}
void Update(){
int horizontal = (int)Input.GetAxisRaw("Horizontal");
AttemptMove (horizontal, 0);
if (Input.GetKeyDown ("space")) {
if(canShoot){
Vector3 shootPosition = transform.position + new Vector3 (0, 0.5f, 0);
Instantiate (bullet, shootPosition, Quaternion.identity);
StartCoroutine(Shoot());
}
}
}
IEnumerator Shoot(){
Debug.Log("Start");
canShoot=false;
yield return new WaitForSeconds (shootingTimeDelay);
canShoot=true;
Debug.Log("End");
}
shootingTimeDelay is set to 1.1f. I am not destroying my gameObject anywhere and it works properly in other scripts in my project.
It never prints End. I don't get what is wrong
I would say don't use a coroutine for something like this.
Trying doing this and see if you get better restults
private float time = 0;
public float fireTime = 1.1f;
private void Update()
{
time += Time.deltaTime;
if(Input.GetKeyDown("space") && time >= fireTime)
{
Vector3 shootPosition = transform.position + new Vector3 (0, 0.5f, 0);
Instantiate (bullet, shootPosition, Quaternion.identity);
time = 0;
}
}
Ok i found the bug. I had a method in its superclass that called StopAllCoroutines but for some reason i never tought of it until now. Changed that to StopCoroutine("name of my coroutine") and now it works perfect :)
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.
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));
}