关闭应用

时间:2016-05-29 17:49:41

标签: c# variables unity3d

我有法术冷却变量:

     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);
 }

一旦我关闭应用程序,变量nextFire保持它的先前值,即如果上次游戏继续进行,那么说30秒,nextFire变量将具有30f作为起始值。为什么?如何解决这个问题?

更新完整代码

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类:

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);
}
}

球员运动等级:

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 个答案:

答案 0 :(得分:1)

nextFire 变量位于MonoBehaviour上并且是公开的。这意味着,Unity将序列化该值并使其可通过检查器访问。从那里开始,它将始终加载在游戏开始时在检查器中设置的值。可能是你在那里设置了一些值,而不是在播放模式,所以它是持久的。您可以将此检查器值视为“默认值”,运行时更改将不会保存,但在编辑模式下它们是。

要保存该值,但保持变量public,请添加 NonSerialized 属性,如下所示:

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

但我认为没有任何理由将其作为公共变量。把它变成私有的它应该有效。或者使它成为具有公共get和私有集的属性,因此它不会在检查器中序列化。

在阅读之后,您将变量设为public是因为您希望在检查器中看到它:如果它是公共的,它也将由Unity保存和加载。如果您只想检查调试值,请右键单击检查器右上角的小图标,然后选择 debug 模式。它也会以这种方式显示私有变量。然后只需将 nextFire 设为私有。或者,您可以将其公开并将其序列化,但在 Awake()中将其设置为零。

public float nextFire;

void Awake()
{
    nextFire = 0f;
}

接下来,看起来您可能正在更改预制件的值而不是场景中的GameObject。请注意,您需要保存实例化预制件的副本,然后更改副本上的值,而不是原始值,否则更改也会在播放模式下保留。预制件始终保存。

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

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

您可以将postfix Prefab 添加到包含预制件的变量中,以确保在运行时不会意外修改它们。