- Home /
(c#) Problems with yield
Hello. I am trying to write a script where hitting the Fire1 button sets a boolean value called _isAttacking to true, then sets it to false five seconds later. The relevant part of the code is at the bottom in the void Attack() block of code, but here's the whole thing just incase something needs to be changed elsewhere:
using UnityEngine;
using System.Collections;
public class movement : MonoBehaviour {
public float speed = 6.0F;
public float jumpHeight = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
CharacterController controller;
public bool isAttacking { get { return _isAttacking; } set { _isAttacking = value; } }
bool _isAttacking = false;
void Start(){
controller = GetComponent<CharacterController>();
}
void Update() {
if (controller.isGrounded) {
moveDirection = Vector3.forward;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButtonDown("Jump"))
{
moveDirection.y = jumpHeight;
}
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
void Attack(){
if (Input.GetButtonDown("Fire1"))
{
_isAttacking = true;
yield return new WaitForSeconds(5);
_isAttacking = false;
}
}
}
My problem is that the debugger is giving me an error that says "The body of `movement.Attack()' cannot be an iterator block because `void' is not an iterator interface type" and I'm not sure what that means, as I'm kind of a beginner with Unity Scripting. What should I do to get this working?
Answer by Flynn · Nov 28, 2012 at 06:41 AM
C# is a bit more strict with how you are supposed to do things than JS -- It wants your functions to be clearly defined as iterator blocks, and it wants you to strictly call them using StartCoroutine.
To see how this should be done, replace your Attack() method with this:
public void Attack()
{
StartCoroutine(Attack_Coroutine());
}
private IEnumerator Attack_Coroutine()
{
if (Input.GetButtonDown("Fire1"))
{
_isAttacking = true;
yield return new WaitForSeconds(5);
_isAttacking = false;
}
}
From a code clarity standpoint, I recommend checking Input.GetButtonDown("Fire1"), and THEN calling Attack() if that returns true -- but that's purely methodology, and not required :)
Good luck!
I second that advice about calling attack after detecting the fire button has been pressed. +1 for Flynn.
Awesome! I took your advice of calling attack after the input is checked and it's working perfectly now! Thanks so much for your help!
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Waiting between pingpong loops 2 Answers
What is wrong with this use of WaitForSeconds? 1 Answer
C# yield waitforseconds 3 Answers