我有法术冷却变量:
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);
}
}
}
答案 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 添加到包含预制件的变量中,以确保在运行时不会意外修改它们。