Search Unity

Rigidbody.AddForce doesn't always work

Discussion in 'Physics' started by Seppi, Jun 20, 2017.

  1. Seppi

    Seppi

    Joined:
    Nov 10, 2012
    Posts:
    162
    I'm trying to add force to an object when a key is pressed. it works most of the time, but one in every few key presses just doesn't work. I don't think it's a code issue but here it is anyway:

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class Bird : MonoBehaviour {
    7.  
    8. Rigidbody bird;
    9. public int force = 10;
    10. bool canFlap = true;
    11. public float timer = 0.25f;
    12.  
    13.     // Use this for initialization
    14.     void Start () {
    15.        
    16.         bird = GetComponent<Rigidbody>();
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void FixedUpdate () {
    21.        
    22.         if(Input.GetButtonDown("Jump") && canFlap == true){
    23.            
    24.             Wait();
    25.             bird.velocity = new Vector3(0,0,0);
    26.             bird.AddForce(Vector3.up * force);
    27.         }
    28.     }
    29.  
    30.     IEnumerator Wait () {
    31.        
    32.         canFlap = false;
    33.         yield return new WaitForSeconds(timer);
    34.         canFlap = true;
    35.     }
    36. }
    37.  
    Any ideas? Thanks!
     
  2. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    I don't know if this is your issue, but from what I understand, you can call coroutines in JavaScript the way you have here
    Code (csharp):
    1. Wait()
    In C#, though, you need to do it this way:
    Code (csharp):
    1. StartCoroutine("Wait");
    It might be messing with the results you expect by not calling it the right way, perhaps.


    Actually, found it in the docs..
    https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html

    Kind of crummy that this doesn't cause a compiler error since it doesn't really seem to have any purpose to allow that as far as I know..?? (maybe it does, I don't know)
     
    DasJonny likes this.
  3. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    It does have a purpose. You can use a coroutine as a default method and execute any code within it without creating an instance of coroutine itself, basically negating yields.

    Also @Seppi, make sure you're not creating multiple coroutines with StartCoroutines (unless you want to do it ofc).

    Use null checks for either coroutine itself, or the enumerator:
    Code (CSharp):
    1.  
    2. // E.g. pseudocode
    3. ...
    4. private Coroutine _coroutine;
    5.  
    6. private void FixedUpdate(){
    7. ...
    8.    if (_coroutine != null){
    9.        StopCoroutine(_coroutine);
    10.        _coroutine = null;
    11.    }
    12.    _coroutine = StartCoroutine(YourCoroutine());
    13. ...
    14. }
    15.  
    16. // Or enumerator
    17. private IEnumerator _coroutineEnumerator;
    18.  
    19. ...
    20.     if (_coroutineEnumerator != null){
    21.          StopCoroutine(_coroutineEnumerator);
    22.          _coroutineEnumerator = null;
    23.     }
    24.     _coroutineEnumerator = Coroutine;
    25.    StartCoroutine(_coroutineEnumerator);
    26. ...
     
    Last edited: Jun 20, 2017
  4. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    Oh really... Yesterday I had quickly tried that before posting to make sure, and it didn't seem to call the function at all. I must have something wrong though. Anyways, not sure the issue outside of that.

    Edit:, I don't think it's true that just calling it as Wait() calls it like a regular function, unless I misunderstood:
    Code (csharp):
    1.  
    2. public class test : MonoBehaviour
    3. {
    4.     void Start ()
    5.     {
    6.         Debug.Log("Before wait");
    7.         Wait();
    8.         Debug.Log("After wait");
    9.     }
    10.  
    11.     IEnumerator Wait()
    12.     {
    13.  
    14.         Debug.Log("Start");
    15.         yield return new WaitForSeconds(2.0f);
    16.         Debug.Log("End");
    17.     }
    18. }
    Console output:
    Code (csharp):
    1.  
    2. Before wait
    3. UnityEngine.Debug:Log(Object)
    4. test:Start() (at Assets/test.cs:14)
    5.  
    6. After wait
    7. UnityEngine.Debug:Log(Object)
    8. test:Start() (at Assets/test.cs:16)
    9.  
    Note that the "Start" and "End" doesn't show in the log at all, telling me that Wait isn't even called here.
     
    Last edited: Jun 21, 2017