2017-11-18 10 views
0

解決しよう:バージョン2017.2が予期しない動作を取得ユニティ

UI button On Click manager

に更新ユニティ()マネージャ]をクリックオンUIボタンの実行リストへの1つの以上のタスクを追加し、それらのタスクの実行は予測できない動作をします。私のカウントダウンスクリプトは、そのリストに複数のタスクが追加されている場合(つまり、添付されたイメージの場合)、2倍の速さでカウントされます。 1つのタスクを削除すると、コードが実行されます(カウントダウンは毎秒5..4..3..2..1などのように画面に表示されます)。ユニティバグ?

public IEnumerator Countdown() 
{ 
    while (timeLeft > 0) 
    { 
     yield return new WaitForSeconds(1.0f); 
     countText.text = timeLeft.ToString("f0"); 
     timeLeft--;   
    } 
} 

public void StartCountDown() 
{ 
    StartCoroutine("Countdown"); 
} 
+2

このように、コルーチンは同時に2回実行されますか? – lockstock

+0

はい、そうです。したがって、On Click()リストに1つ以上のタスク(合計3つのタスク)を追加すると、3回実行されます。なぜそれはこのように振る舞うのですか? – Gusto

答えて

2

コルーチン関数が呼び出されるたびに、timeLeft変数が変更されています。最初に実行中のコルーチン関数を再度呼び出すと、複数のコルーチン関数がtimeLeft変数を同時に変更して、現在の問題になります。

ブール変数を使用してコルーチンが既に実行されていることを検出し、開始が再び行われる場合がありますが、同時に複数のタイマーを作成することに言及しました。各関数呼び出しは、それのためtimeLeft変数を持つようにCountdown関数内timeLeft変数.Move

:2つのオプションがあります。また、異なるTextコンポーネントを使用して各関数呼び出しのTextを変更するように、countText変数にも同じ操作を行います。全体コルーチン機能.Move

public IEnumerator Countdown() 
{ 
    float timeLeft = 5f; 
    Text countText = GameObject.Find("TextForThisCounter").GetComponent<Text>(); 

    while (timeLeft > 0) 
    { 
     yield return new WaitForSeconds(1.0f); 
     countText.text = timeLeft.ToString("f0"); 
     timeLeft--; 
    } 
} 

別のクラスにタイマーとするとき、タイマーが行われている中にダニがあるあなたに、各第二に通知するコールバックActionを使用しています。より移植性と再利用性が高いので、この方法をお勧めします。 IDを実装して、実行が終了したタイマーを特定することもできます。

タイマーは、別のスクリプトに移動:

public struct CountDownTimer 
{ 
    private static int sTimerID = 0; 
    private MonoBehaviour monoBehaviour; 

    public int timer { get { return localTimer; } } 
    private int localTimer; 

    public int timerID { get { return localID; } } 
    private int localID; 

    public CountDownTimer(MonoBehaviour monoBehaviour) 
    { 
     this.monoBehaviour = monoBehaviour; 
     localTimer = 0; 

     //Assign timer ID 
     sTimerID++; 
     localID = sTimerID; 
    } 

    public void Start(int interval, Action<int> tickCallBack, Action<int> finshedCallBack) 
    { 
     localTimer = interval; 
     monoBehaviour.StartCoroutine(beginCountDown(tickCallBack, finshedCallBack)); 
    } 

    private IEnumerator beginCountDown(Action<int> tickCallBack, Action<int> finshedCallBack) 
    { 
     while (localTimer > 0) 
     { 
      yield return new WaitForSeconds(1.0f); 
      localTimer--; 
      //Notify tickCallBack in each clock tick 
      tickCallBack(localTimer); 
     } 

     //Notify finshedCallBack after timer is done 
     finshedCallBack(localID); 
    } 
} 

用途:

スタートタイマー4倍異なるIDを持つ各。

void Start() 
{ 
    createAndStartNewTimer(); 

    createAndStartNewTimer(); 

    createAndStartNewTimer(); 

    createAndStartNewTimer(); 
} 


public void createAndStartNewTimer() 
{ 
    //Create new Timer 
    CountDownTimer timer = new CountDownTimer(this); 

    //What to do each second time tick in the timer 
    Action<int> tickCallBack = (timeLeft) => 
    { 
     Debug.Log(timeLeft.ToString("f0")); 
    }; 


    //What to do each second time tick in the timer 
    Action<int> finshedCallBack = (timeriD) => 
     { 
      Debug.Log("Count Down Timer Done! ID: " + timeriD); 
     }; 

    //Start Countdown Timer from 5 
    timer.Start(5, tickCallBack, finshedCallBack); 
} 
+0

"coroutine関数が呼び出されるたびに、timeLeft変数が変更されています。" - これは明らかですが、ここで問題となるのは、コルーチンがリスト上の唯一のタスクであるときに1回呼び出されることです。 On Clickイベントにタスクを追加すると、なぜ2回実行されますか?それはこのように振舞うべきではありません。 "しかし、同時に複数のタイマーを作成したいと述べています。 - いいえ、私はそれを言いませんでした。私はそれが一度だけ実行する必要があります。 – Gusto

+0

あなたの質問から "UIボタンの実行リストに2つ以上のタスクを追加すると、Click()マネージャー上でこれらのタスクの実行が予期しない動作をする" *その 'onClick'スロットに' StartCountDown() 'を追加すると、 1回以上、「StartCountDown()」関数が追加された時間と呼ばれます。それはバグではなく、そのように動作するはずです。 – Programmer

+0

あなたが添付画像を注意深く見ると、私は同じタスクを2回追加していません。自分のカウントダウンスクリプトとは関係のない別のタスクを追加しています。その後、統合は狂ってしまい、コルーチンを2回実行します。 – Gusto