- Home /
Ienumerators not being called on client?
Hey so I made a Ienumerator to have a spell cooldown, which works great on the lan host client, but anyone who joins the game can only shoot once and it seems that the reset Ienumerators never get run. I will link my script down below any help is appreciated!
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine;
public class shootSpell : NetworkBehaviour {
public Camera cam;
public GameObject bulletPrefab;
public GameObject bulletPrefab2;
public GameObject bulletPrefab3;
public Transform bulletSpawn;
public Transform bulletWallSpawn;
public NetworkAnimator netAnim;
bool canShootMain = true;
bool canShootAlt = true;
bool canShootE = true;
public Image crossHair;
public Image altIcon;
public Image eIcon;
// Use this for initialization
void Start () {
netAnim = GetComponent<NetworkAnimator> ();
}
// Update is called once per frame
void Update () {
if (!isLocalPlayer) {
return;
}
if (Input.GetButton ("Fire1")) {
if (canShootMain == true) {
canShootMain = false;
StartCoroutine (spellMainDelay ());
crossHair.fillAmount = 0;
}
}
if (Input.GetButton ("Fire2")) {
if (canShootAlt == true) {
canShootAlt = false;
StartCoroutine (spellAltDelay ());
altIcon.fillAmount = 0;
}
}
if (Input.GetKey ("e")) {
if (canShootE == true) {
canShootE = false;
StartCoroutine (spellEDelay ());
eIcon.fillAmount = 0;
}
}
}
void FixedUpdate () {
if (canShootMain == false && crossHair.fillAmount < 1) {
crossHair.fillAmount += 0.0165f;
}
if (canShootAlt == false && altIcon.fillAmount < 1) {
altIcon.fillAmount += 0.0013f;
}
if (canShootE == false && eIcon.fillAmount < 1) {
eIcon.fillAmount += 0.002f;
}
}
[Command]
void CmdShoot1 () {
var bullet = (GameObject)Instantiate (bulletPrefab, bulletSpawn.position, bulletSpawn.rotation);
bullet.GetComponent<Rigidbody> ().velocity = bullet.transform.forward * 10;
NetworkServer.Spawn (bullet);
Destroy (bullet, 5f);
StartCoroutine (mainSpellCooldown ());
}
[Command]
void CmdShoot2 () {
var bullet = (GameObject)Instantiate (bulletPrefab2, bulletWallSpawn.position, bulletWallSpawn.rotation);
bullet.GetComponent<Rigidbody> ().velocity = bullet.transform.forward * 10;
NetworkServer.Spawn (bullet);
Destroy (bullet, 5f);
StartCoroutine (altSpellCooldown ());
}
[Command]
void CmdShoot3 () {
var bullet = (GameObject)Instantiate (bulletPrefab3, bulletSpawn.position, bulletSpawn.rotation);
bullet.GetComponent<Rigidbody> ().velocity = bullet.transform.forward * 10;
NetworkServer.Spawn (bullet);
Destroy (bullet, 5f);
StartCoroutine (ESpellCooldown ());
}
IEnumerator spellMainDelay () {
netAnim.SetTrigger ("rightSwing");
yield return new WaitForSeconds (.2f);
CmdShoot1 ();
}
IEnumerator mainSpellCooldown () {
yield return new WaitForSeconds (1f);
canShootMain = true;
}
IEnumerator spellAltDelay () {
netAnim.SetTrigger ("Earthquake");
yield return new WaitForSeconds (.1f);
CmdShoot2 ();
}
IEnumerator altSpellCooldown () {
yield return new WaitForSeconds (15f);
canShootAlt = true;
}
IEnumerator spellEDelay () {
netAnim.SetTrigger ("DownHit");
yield return new WaitForSeconds (.1f);
CmdShoot3 ();
}
IEnumerator ESpellCooldown () {
yield return new WaitForSeconds (10f);
canShootE = true;
}
}
There's an issue with Enumerators where sometimes they can't modify non-static fields so if you debug you might find the variables aren't changing back to true. I don't know a fix for this unfortunately but a workaround is to make them all static if there is only one "shootSpell" per game which seems unlikely.
Thanks for letting me know, I started to search around for other ways and came across the Time.time feature. In case anyone stumbles upon this in the future this link saved my game. https://docs.unity3d.com/ScriptReference/Time-time.html
Answer by DominikHeyn · Feb 22, 2017 at 10:14 AM
Hey there, I can't fix your problem without playing around with it but I'd like you to introduce to the way I handled cooldowns and stuff:
[ClientCallback] void Update () {
if (!isLocalPlayer)
return;
bool cooldownComplete = (Time.time > nextReadyTime);
if (cooldownComplete) {
if (Input.GetButton("Fire1")) {
AbilityCooldownMechanics ();
// Call here your method for casting the spell
}
}
else {
OnCooldown ();
}
}
private void OnCooldown() {
cooldownTimeLeft -= Time.deltaTime;
float roundedCD = Mathf.Round (cooldownTimeLeft);
}
private void AbilityCooldownMechanics() {
nextReadyTime = cooldownDuration + Time.time;
cooldownTimeLeft = cooldownDuration;
}
Maybe you can use this so you don't have to deal with your current problem. :-)
Dominik
Thanks for making a thoughtful input but I did manage to get around this issue using that Time.time feature you brought up. If you are knowledgeable about Unet and are willing to glance at a problem ive had for the past month, I would greatly appreciate it! If not that's totally ok thanks for your input on this question. http://answers.unity3d.com/questions/1316790/unet-igonore-collisions-between-layers.html
Your answer