-1

I have spell cooldown variable :

     private float nextFire = 0;
 public bool IsOffCooldown()
 {
     return Time.time > nextFire;
 }

 public void Cast(Transform spellSpawnerTransform)
 {
     nextFire = Time.time + FireRate;
     Instantiate(this, spellSpawnerTransform.position, Quaternion.identity);
 }

Once I close the app the variable nextFire keeps it's previous value i.e if the last time the game went on for let's say 30 secs the nextFire variable will have 30f as starting value. Why ? How to fix this ?

UPDATE Full code

public class Spell : MonoBehaviour
{

public float FireRate;
public float Damage;
public float Speed;
public GameObject SpellExplosion;
public float nextFire = 0;

public bool IsOffCooldown()
{
    return Time.time > nextFire;
}

private void Update()
{

}

public void Cast(Transform spellSpawnerTransform)
{
    nextFire = Time.time + FireRate;
    Instantiate(this, spellSpawnerTransform.position, Quaternion.identity);
}
}

SpellMover Class :

public class SpellMover : MonoBehaviour
{
private Rigidbody2D spellRigidBody;
private Vector3 sp;
private Vector2 dir;
private Spell spell;

private void Start()
{
    spell = GetComponent<Spell>();
    spellRigidBody = GetComponent<Rigidbody2D>();
    sp = Camera.main.WorldToScreenPoint(transform.position);
    dir = (Input.mousePosition - sp).normalized;
    RotateTowardsMouse();
}

private void Update()
{    
    spellRigidBody.AddForce(dir * spell.Speed);
}

private void RotateTowardsMouse()
{
    Transform target = spellRigidBody.transform;
    Vector3 mouse_pos = Input.mousePosition;
    Vector3 object_pos = Camera.main.WorldToScreenPoint(target.position);
    mouse_pos.x = mouse_pos.x - object_pos.x;
    mouse_pos.y = mouse_pos.y - object_pos.y;
    float angle = Mathf.Atan2(mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg;
    spellRigidBody.transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
}

private void OnTriggerEnter2D(Collider2D other)
{
    if (other.name == "Player" || other.name == "SpellSpawner" || other.name == "Boundary")
    {
        return;
    }
    Instantiate(spell.SpellExplosion, transform.position + transform.right, transform.rotation);
}
}

Player Movement Class :

public class PlayerMovement : MonoBehaviour
{
public float Speed;
public GameObject SpellToUse;

private Spell CurrentSpell;
private bool IsAttacking = false;
private Rigidbody2D playerRigidBody;
private Animator playerAnimator;
private SpriteRenderer playerRenderer;
private GameObject skillSpawner;

private void Start()
{
    CurrentSpell = SpellToUse.GetComponent<Spell>();
    playerRigidBody = GetComponent<Rigidbody2D>();
    playerAnimator = GetComponent<Animator>();
    playerRenderer = GetComponent<SpriteRenderer>();
    skillSpawner = transform.FindChild("SpellSpawner").gameObject;
}

private void Update()
{
    float horizontal = Input.GetAxis("Horizontal");
    float vertical = Input.GetAxis("Vertical");
    playerRigidBody.velocity = new Vector2(horizontal * Speed, vertical * Speed);
    playerAnimator.SetFloat("Speed", horizontal);
    if (Input.GetKey(KeyCode.Space) && CurrentSpell.IsOffCooldown())
    {
        CurrentSpell.Cast(skillSpawner.transform);
        IsAttacking = true;
    }
    if (Input.GetKeyUp(KeyCode.Space))
    {
        IsAttacking = false;
    }
    playerAnimator.SetBool("IsAttacking", IsAttacking);
    UpdateSpellSpawnerLocation(horizontal, vertical);
}

//separate script maybe ?
private void UpdateSpellSpawnerLocation(float inputHorizontal, float inputVertical)
{
    if (inputHorizontal < 0)
    {
        //left
        skillSpawner.transform.position = new Vector2(playerRigidBody.transform.position.x - playerRenderer.bounds.size.x / 3, playerRigidBody.transform.position.y);
    }
    else if (inputHorizontal > 0)
    {
        //right
        skillSpawner.transform.position = new Vector2(playerRigidBody.transform.position.x + playerRenderer.bounds.size.x / 3, playerRigidBody.transform.position.y);
    }
    else if (inputVertical > 0)
    {
        //up
        skillSpawner.transform.position = new Vector2(playerRigidBody.transform.position.x, playerRigidBody.transform.position.y + playerRenderer.bounds.size.y / 3);
    }
    else if (inputVertical < 0)
    {
        //down
        skillSpawner.transform.position = new Vector2(playerRigidBody.transform.position.x, playerRigidBody.transform.position.y - playerRenderer.bounds.size.y / 2);
    }
}
}

1 Answers1

1

The nextFire variable is on a MonoBehaviour and is public. This means, that Unity will serialize the value and make it accessible through the inspector. From there on it will always load the value which is set in the inspector at game start. It might be that you set some value there while not in play mode, so it was persisted. You can think of this inspector value as the "default value", changes at runtime won't be saved, but in edit mode they are.

To not save the value, but keep the variable public add the NonSerialized attribute like this:

[System.NonSerialized]
public float nextFire = 0f;

But I don't see any reason for this to be a public variable. Make it private and it should work. Or make it a property with a public get and private set, so it won't be serialized in the inspector.

After reading that you made the variable public because you wanted to see it in the inspector: If it is public it will also be saved and loaded by Unity. If you only want to check the value for debugging, right-click on the little icon at the top right of the inspector and select debug mode. It will also show private variables that way. Then just make nextFire private. Alternatively, you can leave it public and also have it be serialized, but then in Awake() set it to zero.

public float nextFire;

void Awake()
{
    nextFire = 0f;
}

Next, it looks like you might be changing values of the prefab instead of a GameObject in the scene. Be aware that you need to save a copy of the instantiated prefab and then change values on the copy, not the original, or else the changes also persist through play mode. Prefabs are always saved.

public GameObject spellPrefab;
private GameObject runtimeSpell;
private float nextFire;

void Awake()
{
    runtimeSpell = Instantiate(spellPrefab);
}

You can add the postfix Prefab to variables holding prefabs, to make sure you don't accidentally modify them at runtime.

Xarbrough
  • 1,393
  • 13
  • 23
  • using the `[System.NonSerialized]` did the job making the variable private doesn't solves the problem. One question i'm aware that im changing the prefab instead of the clone, declaring gameobject runtimeSpell doesn't change anything tho. – PreqlSusSpermaOhranitel May 29 '16 at 20:15