質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

8427閲覧

Unity-Update上の判定で一度だけメソッドを呼び出す

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

2グッド

3クリップ

投稿2017/08/19 18:17

Unityでゲームを制作しています。

例えば、ゲーム上でスコアが一定値に達するたびにステージの難易度が上がり、画面に「ステージ〇〇」というテキストのカットインを入れたりするように、
「判定はUpdate上だがメソッドを呼び出すのは一度だけ」という場面がよくあると思うのですが、
これを実装するのに効率的な方法は何がありますか?

bool変数を用意して、これがtrueならメソッドを実行。実行後にfalseに戻す。
スコアが一定値に達するたびにtrueにする。
という方法で今まで実装してきたのですが、あまり効率的には思えません。

回答よろしくお願いします。

sell, TomoeEbihara👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
IShix

総合スコア1724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/08/22 04:00

丁寧な回答ありがとうございます。 デリゲートとイベントですね、やってみます。
IShix

2017/08/22 06:13

解決できてよかったです。 それから、見てわかるとは思いますが今回のコードの注意点を数点お伝えしておきます。 ・ addScore内で全てのレベルをコンプリートした時の処理を入れていません。 ・ レベルがあがった時にscoreCounterの値を0にしています。本来であれば次のレベルに持ち越すスコアがあるはずです。 ・ ScriptableObject化の話を書いていますが、導入した場合静的クラスから参照できないかもしれません。
退会済みユーザー

退会済みユーザー

2017/08/22 14:52

重ねてありがとうございますm(__)m
guest

0

実際にUpdate内に実装するなら、bool変数を使う形になると思います。

ですが今回の例で言う「スコアが一定値に達する度に」という内容であれば、
「スコアが加算された時」に判定と処理を行えばよいのでUpdate内に実装する必要はありません。

1フレーム毎にスコアが加算されるゲームでない限り「Updateの頻度>スコアが加算される頻度」だと思いますので、後者で実行した方が負荷としては軽減されると考えられます。

投稿2017/08/21 00:31

sakura_hana

総合スコア11427

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問