- Home /
What am I doing wrong. "Calling Script to start coroutine"
void Update () {
if (ptrScriptVariable.pistolammo = 0)
{
ptrScriptReload = (ReloadScript) objPlayer.GetComponent( typeof(ReloadScript) );
yield return StartCoroutine("Reload");
}
I get the error Assets/Scripts/PistolScript.cs(18,14): error CS1624: The body of PistolScript.Update()' cannot be an iterator block because
void' is not an iterator interface type
Working with a C Sharp scipt when I am used to Java. Every other time I called a script this way to deduct ammo after shot in the Variable script worked.
Thanks..
Please place your script in the code format -- it really puts people off, and just annoying really :) (highlight your code and press the 0101 icon)
Answer by Peter G · Dec 11, 2010 at 01:44 AM
You cannot yield in the Update()
. Since Update is called everyframe, if you made one yield, then 2 would be called on top of each other, and so forth.
You can remove the yield return, and still start the coroutine, but then Unity will not wait until the execution finishes to move on. You could add a bool to ensure that the operation is finished; make sure that you don't start multiple coroutines at the same time as well.
bool reloading = false; bool finished = false;
void Update () { if (ptrScriptVariable.pistolammo = 0) { if(!reloading) { ptrScriptReload = (ReloadScript) objPlayer.GetComponent(typeof(ReloadScript)); StartCoroutine(Reload()); //This version is faster to call than a string.
reloading = true;
}
}
if(finished) {
//Execute some code
}
}
IEnumerator Reload () {
while(stillReloading) {
//Reload code;
//I don't know what you are returning.
yield return null;
}
reloading = false;
finished = true;
}
Answer by Eric5h5 · Dec 11, 2010 at 02:12 AM
It would be better if you removed Update; it's not serving any purpose. Just check that ptrScriptVariable.pistolammo is 0 when you decrement the variable, and call the coroutine from there. Checking ptrScriptVariable.pistolammo every frame is a waste, and you can't yield on coroutines in Update.
Edit: I'm not quite following what you're doing, but it seems like the game logic isn't really separated the way it should be ideally. Here's a quick example of a script, which would be attached to the player, that handles firing a bullet (I'm using JS here, sorry...I'm writing this quickly and C# is a pain in the ass for stuff like this). This won't directly apply to your project, but hopefully you get the general idea:
var bullet : Rigidbody; var bulletForce = 500.0; var maxAmmo = 6; private var ammoCount : int;
function Start () { ammoCount = maxAmmo;
while (true) {
if (Input.GetButtonDown("Fire")) {
FireBullet();
if (--ammoCount == 0) {
yield Reload();
}
}
yield;
}
}
function FireBullet () { var bulletClone = Instantiate (bullet, transform.position, transform.rotation); bulletClone.AddForce (Vector3.forward * bulletForce); }
The input is in a coroutine in an infinite loop, so when it's yielding on Reload, it's not checking for input at all. Since the bullet is a rigidbody, you'd add a force once to make it move when it's instantiated, rather than using Translate in Update (which also won't work properly for collisions). Then the bullet prefab could have this script on it:
var maxFlightTime = 1.0; var bulletHit : GameObject;
function Start () { yield WaitForSeconds (maxFlightTime); DestroySelf(); }
function DestroySelf () { Instantiate (bulletHit, transform.position, Quaternion.identity); Destroy (gameObject);
}
function Update () { transform.position.y = 0.0; }
function OnCollisionEnter () { DestroySelf(); }
This way the bullet only cares about stuff that directly relates to it...the bullet is just going to fly until it runs out of steam or hits something; why should it care if the player is reloading his gun or anything?
Problem Solved, thanks for helping me understand (Peter and Eric), I did not end up rewriting my code I just was doing it in the wrong script and had to change a few things. SOLVED*
Answer by doomprodigy · Dec 11, 2010 at 02:24 AM
Alirght here is my code without any modifications from my last post.
using UnityEngine; using System.Collections;
public class PistolScript : MonoBehaviour { private float moveSpeed = 30f; // how fast the bullet moves private float timeSpentAlive; // how long the bullet has stayed alive for private GameObject objPlayer; public float pistolammo = 10f; private VariableScript ptrScriptVariable; private VariableScript ptrScriptReload;
// Use this for initialization
void Start () {
objPlayer = (GameObject) GameObject.FindWithTag ("Player");
ptrScriptVariable = (VariableScript) objPlayer.GetComponent( typeof(VariableScript) );
}
// Update is called once per frame
void Update () {
ptrScriptVariable = (VariableScript) objPlayer.GetComponent( typeof(VariableScript) );
if (ptrScriptVariable.pistolammo = 0)
{
ptrScriptReload = (ReloadScript) objPlayer.GetComponent( typeof(ReloadScript) );
yield return StartCoroutine("Reload");
}
timeSpentAlive += Time.deltaTime;
if (timeSpentAlive > 1) // if we have been travelling for more than one second remove the bullet
{
removeMe();
}
// move the bullet
transform.Translate(0, 0, moveSpeed * Time.deltaTime);
transform.position = new Vector3(transform.position.x,0,transform.position.z); // because the bullet has a rigid body we don't want it moving off it's Y axis
}
void removeMe ()
{
Instantiate(ptrScriptVariable.parBulletHit, transform.position, Quaternion.identity );
Destroy(gameObject);
}
void OnCollisionEnter(Collision Other)
{
if ( Other.gameObject.GetComponent( typeof(AIscript) ) != null && Other.gameObject != objPlayer ) // if we have hit a character and it is not the player
{
AIscript ptrScriptAI = (AIscript) Other.gameObject.GetComponent( typeof(AIscript) );
ptrScriptAI.health -= 10;
ptrScriptVariable = (VariableScript) objPlayer.GetComponent( typeof(VariableScript) );
ptrScriptVariable.pistolammo -= 1;
Instantiate(ptrScriptVariable.parAlienHit, transform.position, Quaternion.identity );
removeMe();
}
removeMe(); // remove the bullet if it has hit something else apart from an enemy character
}
}
I understand about the Yield not going in the update that way because of the frames constantly updating. I need it to update to check what the ammount of ammo is so it knows if it needs to reload or not (That is why it is in update). I tried to work with the code posted by Peter.G but I could not get it to work right. All I want it to do is deduct ammo found in my variables (Which it does in a collision currently (Which I need to move to when it calls the time scale (I wish to do it her and not in the script which shoots as this is a base for other weapons) and after it has deducted all the ammo it instantly reloads which is just a waiting for a few secconds (In which I can incorporate Gui and animations later) after the time is over add the ammo back (so just a pistolammo += 10)
Heres the other scripts: Reload Script (So the wait time and where I will incorporate gui effects and animations later)
using System.Collections; using UnityEngine;
public class ReloadScript : MonoBehaviour { // C# Reload Coroutine IEnumerator Reload () { // Wait for one frame yield return 0;
// Wait for two seconds yield return new WaitForSeconds (5.0);
} }
And the variable script
using UnityEngine; using System.Collections;
public class VariableScript : MonoBehaviour { public float pistolammo = 10; public float shotgunammo = 6; public float assualtrifleammo = 30; }
Unsure if to make a new topic or not so I just gave another answer, Was also unsure if I typed it here or not so I did it as an awnser for the formating.