Unityでゲームを制作しています。
例えば、ゲーム上でスコアが一定値に達するたびにステージの難易度が上がり、画面に「ステージ〇〇」というテキストのカットインを入れたりするように、
「判定はUpdate上だがメソッドを呼び出すのは一度だけ」という場面がよくあると思うのですが、
これを実装するのに効率的な方法は何がありますか?
bool変数を用意して、これがtrueならメソッドを実行。実行後にfalseに戻す。
スコアが一定値に達するたびにtrueにする。
という方法で今まで実装してきたのですが、あまり効率的には思えません。
回答よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答2件
0
ベストアンサー
イベントを利用するのはどうでしょうか?
Update内の処理はコストが高くなりがちなので僕はあまり使いません。
イベントを利用することでUpdate内で処理する必要がなくなります。
###レベルを管理するマネージャー
とりあえず静的クラスとしました。コードは未検証です。
[このクラスの注意点]
・ addScore内で全てのレベルをコンプリートした時の処理を入れていません。
・ レベルがあがった時にscoreCounterの値を0にしています。本来であれば次のレベルに持ち越すスコアがあるはずです。
・ ScriptableObject化の話を書いていますが、導入した場合静的クラスから参照できないかもしれません。
C#
1public static class levelManager 2{ 3 //レベルアップのイベント 4 public static event System.Action<int> OnLevelUp = delegate {}; 5 //スコア追加のイベント 6 public static event System.Action<int> OnAddScore = delegate {}; 7 8 /// <summary> 9 /// レベルアップまでに必要なカウント 10 /// わかりやすいようにとりあえずここに書いてますが 11 /// 本来ならこういうデータは管理しやすいように切り出した方がわかりやすいです。 12 /// 僕はよくエクセルで管理してScriptableObject化してそれを参照するようにします。 13 /// </summary> 14 static readonly int[] LEVEL_COUNTS = new int[] 15 { 16 //LEVEL1 17 10, 18 //LEVEL2 19 11, 20 //LEVEL3 21 12 22 }; 23 24 //こうしとけば外からでも levelManager.nowLevel でアクセスできるのでとりあえずはやしておく 25 public static int nowLevel { get{ return nowIdx + 1; } } 26 27 static int nowIdx = 0; 28 static int scoreCounter = 0; 29 30 /// <summary> 31 /// スコアのチェック用 levelManager.addScore(数値); でアクセス 32 /// </summary> 33 public static bool addScore(int addCount) 34 { 35 scoreCounter += addCount; 36 //スコアがaddされた 37 if (OnAddScore != null) OnAddScore(scoreCounter); 38 //レベルアップ判定 39 if(scoreCounter > LEVEL_COUNTS[nowIdx]) 40 { 41 nowIdx++; 42 scoreCounter = 0; 43 //レベルがあがった 44 if(OnLevelUp != null) OnLevelUp(nowLevel); 45 46 return true; 47 } 48 49 return false; 50 } 51}
###スコアを表示する箇所
C#
1public class showScore : MonoBehaviour 2{ 3 Text levelTxt; 4 Text scoreTxt; 5 6 /// <summary> 7 /// オブジェクトが表示された時にイベントをバインド 8 /// </summary> 9 void OnEnable() 10 { 11 levelManager.OnLevelUp += levelUpEvent; 12 levelManager.OnAddScore += addScoreEvent; 13 } 14 15 /// <summary> 16 /// オブジェクトが非表示になった時にイベントをアンバインド 17 /// </summary> 18 void OnDisable() 19 { 20 levelManager.OnLevelUp -= levelUpEvent; 21 levelManager.OnAddScore -= addScoreEvent; 22 } 23 24 //レベルアップしたらテキストに反映 25 void levelUpEvent(int lv) 26 { 27 levelTxt.text = lv.ToString(); 28 } 29 30 //スコアが上がったらテキストに反映 31 void addScoreEvent(int score) 32 { 33 scoreTxt.text = score.ToString(); 34 } 35}
###スコアを追加するキャラクターなど
C#
1public class charaCtor : MonoBehaviour 2{ 3 void addScore() 4 { 5 //スコアを追加 6 var isLevelUp = levelManager.addScore(10); 7 8 Debug.Log(isLevelUp ? "レベルアップ" : "レベルアップしませんでした"); 9 } 10}
###今の実装 アップデート内でテキストを変更することについて
Update内でテキストを常に変更するのは意外に高コストです。
前表示したレベルをキャッシュして判定した方がいいです。
C#
1 2 int currentLevel = 0; 3 int nowLevel = 1; 4 void Update() 5 { 6 if(currentLevel != nowLevel) 7 { 8 currentLevel = nowLevel; 9 levelTxt.text = currentLevel.ToString(); 10 } 11 }
投稿2017/08/21 05:39
編集2017/08/22 06:15総合スコア1729
0
実際にUpdate内に実装するなら、bool変数を使う形になると思います。
ですが今回の例で言う「スコアが一定値に達する度に」という内容であれば、
「スコアが加算された時」に判定と処理を行えばよいのでUpdate内に実装する必要はありません。
1フレーム毎にスコアが加算されるゲームでない限り「Updateの頻度>スコアが加算される頻度」だと思いますので、後者で実行した方が負荷としては軽減されると考えられます。
投稿2017/08/21 00:31
総合スコア11427
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/08/22 04:00
2017/08/22 06:13
退会済みユーザー
2017/08/22 14:52