Bolean Problem

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Nave : MonoBehaviour
{
    [Header("Shooters")]
    public Transform Shooter1;
    public Transform Shooter2;
    public Transform Shooter3;
    public Transform Shooter4;
    public Transform Shooter5;
    public Transform Shooter6;
    public Transform Shooter7;
    public Transform Shooter8;
    public Transform Shooter9;
    public Transform Shooter10;

    [Header("Raycast Settings")]
    public float Raycast_size; // This is the size of the 
    public LayerMask Player; // This mask is for the player

    [Header("Movement Settings")]
    public float StartShipMovement;

    [Header("Music")]
    public AudioBehaviour Hooter;

    [Header("Bools")]
    public bool Movement_on;// This controls if the starship moves or not
    public bool Shoot_On; // This bool controls when the starhip can start to shoot
    public bool Move; //This bool controls if the player starship can move constantly
    public bool hasspawned;

    [Header("Shoot_Settings")]
    [SerializeField] private GameObject bullet; // The prefab of the bullet
    private GameObject bullet_copy;
    public float speed_bullets; // How fast the bullets wil go
    public int x;

    [Header("Delay_Settings")]
    public float Delay_Time;
   
  // Start is called before the first frame update
    void Start()
    {
        Movement_on = false; // At the begining the ship doesn't move
        Shoot_On = false; // At the begining the ship does't move
        hasspawned = false;
  }

    public void Update()
    {
        Movement_on = Physics.CheckSphere(transform.position, Raycast_size, Player); // This bool checks if the player is close

        if (Movement_on)
        {

            Move = true;
        }

        if(Move)
        {
            GetComponent<AudioSource>().Play();
            transform.position += new Vector3(-StartShipMovement * Time.deltaTime, 0, 0);
            StartCoroutine("Ship_Movement");
        }

      

    }

    // Update is called once per frame
    IEnumerator Ship_Movement() //
    {
        yield return new WaitForSeconds(Delay_Time);
        GetComponent<AudioSource>().Stop();

        if (hasspawned)
        {
           
            bullet_copy = Instantiate(bullet, Shooter1.transform.position, Quaternion.identity);
           
           
            Debug.Log("It should work");
            hasspawned = false;
         }
        
hasspawned = true;

   }

    public void OnDrawGizmos()
    {

        Gizmos.DrawWireSphere(transform.position, Raycast_size);
    }
}

I`m trying to make my best , sorry. This is my code for a starhip that should be shooting only once after some time . My problem comes when it starts shoot , it shoots until the delay ends and my desire is that shoots only once.
Every function works fine and the debug log shows me the message but the statment of hasspawned doesnt’ change after showing the message.

so your telling me more than one bullet spawns?
how man times are you calling the coroutine “Ship_Movement”?
first of all change the name of coroutine to “Ship_Shoot” or something, its not moveing the ship
you could add a bool to check if you want to call the coroutine:

if(Move)
        {
            GetComponent<AudioSource>().Play();
            transform.position += new Vector3(-StartShipMovement * Time.deltaTime, 0, 0);
            if(canShoot) { //add canShoot bool at the top starting as true
                   StartCoroutine("Ship_Shoot"); //changed name of "Ship_Movement"
                   canShoot = false; //add this so the courotine does not get called again
            }
        }

and finally add this at the end of the coroutine to make shooting possible again:

IEnumerator Ship_Movement() //
    {
        yield return new WaitForSeconds(Delay_Time);
        GetComponent<AudioSource>().Stop();
        if (hasspawned)
        {
          
            bullet_copy = Instantiate(bullet, Shooter1.transform.position, Quaternion.identity);
          
          
            Debug.Log("It should work");
            hasspawned = false;
         }
      
         hasspawned = true;
         canShoot = true;
   }

You have GOT to debug this stuff. It isn’t optional.

For instance, why are you setting hasspawned false on line 87 and then IMMEDIATELY setting it true on line 90?

Also, why are you checking the sphere in Update() and potentially calling StartCoroutine() every frame? That could start untold numbers of that coroutine.

I’ll post it again so you understand how to debug your code.

You must find a way to get the information you need in order to reason about what the problem is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: How To - Capturing Device Logs on iOS or this answer for Android: How To - Capturing Device Logs on Android

If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

When in doubt, print it out!™

Note: the print() function is an alias for Debug.Log() provided by the MonoBehaviour class.

Hello,

I’m not sure how much it may help but here are a few things to try.

Since the Coroutine Ship_Movement gets called whenever bool Move is true, it will be calling a separate Ship_Movement() each frame.

After each delay_Time and AudioSource.Stop, the if statement changing hasSpawned = false is being called, but the following hasSpawned = true; is also getting called and changing the value.

There is also nothing stopping the Ship_Movements if statement body where it Debug.Log(“It should work”) and changed hasSpawned to false, so the hasSpawned = true. will always be called afterwards, changing the value back to true.

Adding a “return;” statement to line 87-88 will break the function after changing hasSpawned to false and prevent it from the value from being set to true and prevent the boolean changing in inspector.

If this isn’t what you are looking for please lmk and I’ll try to give more clarification.

I know that there is nothing that stops the ship , i’m still working on the code. So if i understand to you the code is always making the hasspawned is true. My question is how could i make the hasspawned true to shot only one and can be called to shoot only one bullet when i want?

So to be clear, you want a re-usable function to be called and shoot a bullet whenever X condition is met?

I’d start off with trying to separate the goals you are trying to accomplish with the ShipMovement function. It currently seems to manage both movement and shooting. When it is done shooting, it changes a hasSpawn value which doesn’t give much indication of what it should do.

It seems movement should always be called whenever a gameObject is active/spawned, so a separate function to manage the position changes would be much easier to read and debug than a single ShipMovement coroutine. This would also help the Update calling ShipMovement constantly, and in turn messing with the hasSpawned/hasShot variables.

I’ve tried to split up the movement & shooting functions while trying to keep the same purpose, but I can’t guarantee anything working without seeing the entire project scene and what you want. I tried cleaning up the rest of the seemingly unnecessary fields adding complexity but you are asking for large blanket answer here.

I’d also recommend trying to isolate your code when asking for help, as it’s hard to understand with the occasional comment.

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Nave : MonoBehaviour
{
    [Header("Shooters")]
    public Transform Shooter1; //shooters 2-10 have been removed, as they arent referenced in the script at all.

    [Header("Raycast Settings")]
    public float Raycast_size; // This is the size of the
    public LayerMask Player; // This mask is for the player

    [Header("Movement Settings")]
    public float StartShipMovement; //movement speed?

    [Header("Music")]
    public AudioBehaviour Hooter;

    [Header("Bools")]
    //public bool Movement_on;// This controls if the starship moves or not           -  Unnecessary variable
    public bool Shoot_On; // This bool controls when the starhip can start to shoot
    //public bool Move; //This bool controls if the player starship can move constantly   -  Unnecessary variable
    public bool hasSpawnedBullet; //changed this field name to hasSpawnedBullet, for simplicity.

    [Header("Shoot_Settings")]
    [SerializeField] private GameObject bullet; // The prefab of the bullet

    public float speed_bullets; // How fast the bullets wil go    - Default value is never set, it will always be 0f;
    public int x; //- Default value is never set, it will always be 0f;

    [Header("Delay_Settings")]
    public float Delay_Time; //- Default value is never set, it will always be 0f;


// Default value comments have been added since it seems (i think?) you want variable info to be set on Start()


    // Start is called before the first frame update
    void Start()
    {
        Shoot_On = false; // At the begining the ship does't move
        hasSpawnedBullet = false;
        //Delay_Time = x;
        //speed_bullets = x;
    }

    public void Update()
    {
        transform.position += new Vector3(-StartShipMovement * Time.deltaTime, 0, 0);  //moves the ship



        if (ShouldShootBullet())
        {
           StartCoroutine("InstantiateBullet");
        }

    }


    private bool ShouldShootBullet()
    {
        if (Physics.CheckSphere(transform.position, Raycast_size, Player) && !hasSpawnedBullet) //checks if player is close & if the bullet has spawned already.
        {
            return true; //player is close, return bool = true;
        }
        else
        {
            return false; //player isn't close, return bool = false;
        }
    }


    private IEnumerator InstantiateBullet() //instantiates/spawns a new bullet & saves it as bullet_copy after X delay time
    {
        hasSpawnedBullet = true; //Changed hasSpawnedBullet value to true BEFORE the yield return new coroutine to prevent the function from being every frame up until the instantiation.

        yield return new WaitForSeconds(Delay_Time);

        GameObject bullet_copy = Instantiate(bullet, Shooter1.transform.position, Quaternion.identity); //saves bullet_copy as a local variable, since no other use was found in script

        Debug.Log("Spawning bullet");


    }


    public void OnDrawGizmos()
    {

        Gizmos.DrawWireSphere(transform.position, Raycast_size);
    }
}