Search Unity

Inline Code Block placeholder in C#?

Discussion in 'Scripting' started by Marrt, Jul 29, 2015.

  1. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    I cannot find how to do this or if it is even possible,

    Can i specify a kind of code snippet that will be inserted into every occurrence of a placeholder at compile time? I cannot use a function because i need those snippets to contain yield statements for use within Coroutines.


    Use case: a break for a Coroutine-Statemachine

    I have a bool to break a state from anywhere. This is needed because yielded coroutines ( "yield returnStartCoroutine(Coroutine());" ) only return if finished or broken from within (see this post and this post). I need this block multiple times within states and without this every state would be riddled with thos blocks

    Code (CSharp):
    1.  
    2. private    IEnumerator StateCombat(){
    3.    
    4.     float meleeFocus = 1F;    //1s chargetime for melee attacks    
    5.     while(true){
    6.         if(distance < meleeDist){                    
    7.            
    8.             //Charge up Melee Attack
    9.             float timer = meleeFocus;
    10.             while(timer > 0F){
    11.                 timer -= Time.deltaTime;
    12.                 <<<WatchForStateBreak>>>
    13.             }
    14.             StartCoroutine(    Main.GenericMeleeAttack());
    15.         }else{
    16.             Approach();
    17.         }                        
    18.         <<<WatchForStateBreak>>>
    19.     }
    20. }
    21.  
    22.  
    23. CODE-BLOCK-PLACEHOLDER <<<WatchForStateBreak>>>{
    24.     yield return new WaitForEndOfFrame();
    25.     if(stateBreak){    stateBreak = false; yield break; }
    26.     yield return null;
    27.     if(stateBreak){    stateBreak = false; yield break; }
    28. }
    29.  

    Code block does the following:

    yield return new WaitForEndOfFrame();
    //end of current frame, all Coroutines and Update()/LateUpdate() calls that may set stateBreak have finished by now

    if(stateBreak){ stateBreak = false; yield break; }
    //break State, the new "state" is already set by the function that has set "stateBreak to true"

    yield return null;
    //continue after next Update()

    if(stateBreak){ stateBreak = false; yield break; }
    //check again on resume, it may have been that a break has already occurred this frame
     
    Last edited: Jul 29, 2015
  2. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Why can't you just use a regular function or delegate?

    To wait for that function to finish you can always yield a coroutine.
     
  3. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Thanks for the quick reply!
    A lack of sophisticated coding background on my side i guess :D. I used delegates for the first time two days ago for some selective removes on lists, i think i didn't fully grasp the concept yet and i have no idea how to apply them to this.

    like that?
    Code (CSharp):
    1. IEnumerator WatchForStateBreak{
    2.     yield return new WaitForEndOfFrame();
    3.     if(stateBreak){    stateBreak = false; yield break; }
    4.     yield return null;
    5.     if(stateBreak){    stateBreak = false; yield break; }
    6. }

    And then call that Coroutine wherever i used <<<WatchForStateBreak>>>. But then my stateBreak will only break this nested-routine, never the state itself.


    Maybe some more background: The sole reason for me doing this is because this code
    Code (CSharp):
    1. yield return StartCoroutine(myRoutine);
    2. print("never gets here");
    never gets to print if myRoutine is stopped by StopCoroutine(). So i use that stateBreak flag that will only get tested after all Coroutines of this frame have finished at EndOfFrame and on resume in the next frame since the flag could have already been set by another earlier routine this frame.
    Breaking State Transitions (e.g. a hit interrupted a charging enemy) will set the current state=State.Staggered and statebreak=true but never use StopCoroutine() to break the ChargingState - it must break itself

    - maybe my whole concept is flawed and i should use a third party Coroutine Manager or use a non-Coroutine Statemachine...