1. このサイトではcookie (クッキー) を使用しています。サイトの利用を継続した場合、cookieの使用に同意したものとみなさせていただきます。 詳しくはこちらをご覧ください。

ゲームの『重さ』対策を研究して改善に励むスレ

たかッシュ2018-03-18に開始した「ゲーム制作」の中の討論

  1. munokura

    munokura ユーザー

    確かに!
    2000ではその印象が大きかったのですが、MVで確認してみましたが同じなんですね!
    裏を返すと、その辺りに変数の処理を入れる(片方に絞らない)と重くなるというコア開発の判断なのでしょうかね?
     
    #21
    神無月サスケ がいいね!しました
  2. ネコタ

    ネコタ ユーザー

    こんばんは。
    私も詳しくはないですが、どっかの記事で読んだことを参考に考えてみました。

    1-1ですが、イベントに設定できるページ条件も違いますね。スイッチは2個に対して、変数は1つしか設けられません。
    1-2、1-3は、差が無いように思います。

    2-1と2-3では、同じ処理をする場合でも行数の多い方が処理が重くなるでしょう。確か、空白(◆のみ)も含めたはずなので、場合によっては2-3の方が重くなりそうです。ただし、後述の理由により普通は処理速度が同じだと思います。

    2-2は、圧倒的に重くなります。というのも、ラベルジャンプの処理で1フレーム使われるためです。ツクール2000では1フレーム内で10000行の処理ができたと記憶しています(言い換えると、1行あたり1/10000の処理となる計算だけれど、実際は10000行までは1フレームが使われて、それを超えたら20000行までは2フレームかかる、という感じだと思います)。たぶん、これを踏襲しているんじゃないでしょうか。そう考えると、ラベルジャンプを使うよりは分岐で並べた方が使用フレームが少なく済む場合の方が多いです。


    比較すれば3-2の方が変数の処理をしない分軽くなると思います。が、結局1万行以内に収まる処理ならどちらも1フレームなので、コードの見やすさや書き込みの労力を考えれば3-1で作った方が良い場合が多いと思います(1万行も同じコマンドは書かないでしょう、普通)。


    ちなみに、1つのイベントを処理するためには、1フレーム使います(1万行単位で1フレーム使用されるルール)。並列処理のイベントに変数+1する処理のみを書き込んだ(終了させる処理を書かない)場合は、2行のイベントを毎フレーム繰り返し処理するため60フレームで60増えます。

    では、同イベント(並列処理で終了条件のないイベント)でループを作り、その中に変数+1する処理のみ(ループ中断処理を入れない)にしてみたらどうなるでしょう?

    すると、1フレームに最大1万行の処理が行われるというルールにより、60フレームでは60万増えることになります。試してみてください(会話コマンドで変数表示\v[1]など入力すれば、変数の値を確認できます)。もしかしたら、何かに使えるテクニックになるかもしれません。
     
    最後に編集: 2019-01-30
    #22
    神無月サスケmunokura がいいね!しています
  3. WTR

    WTR ユーザー

    1.2 変数の操作はどう操作するかで変わりそうな気がします
    同じ代入でも固定値より乱数のほうが他の関数を呼び出すオーバーヘッドがあるはず

    1.3 は最適化すればセルフスイッチのほうが軽くできそうなものですが
    結局リフレッシュが呼ばれるみたいなんで変わらなそうですね
    実装都合ってことでしょうか
     
    #23
    神無月サスケ, munokuraネコタ がいいね!しています
  4. 神無月サスケ

    神無月サスケ ユーザー

    負荷の違いについてお答えします。
    ただし、コアスクリプトは、JavaScriptで書かれており、
    JavaScriptは、環境ごとに実装が異なるので、あくまで一般論にとどまります。
    特定の環境では当てはまらないことがあることにご注意ください。

    >1-2.変数とスイッチの処理の負荷に差はありますか?
    これは「ほぼない」です。変数が数字を扱うのに対して、スイッチがtrue、falseを扱うのですが、
    これらの値はどの環境でも最適化されているので、どちらでも変わりません。
    ごく一部の環境では、スイッチがごくわずかに早くなる可能性はあります。

    >1-3.スイッチとセルフスイッチの負荷の差はありますか?
    これは「ほんの少しある」です。スイッチはキーになるのがスイッチIDという数字ですが、
    セルフスイッチは、[マップID、イベントID、A~Dの数値]という配列で、
    実際にはそれを文字列化したものを使っています。
    このため、このキーの文字列化で、若干時間がかかります。
    とはいえ、多用しなければ、問題ないレベルです。

    1-2、1-3共通で言えることですが、変数やスイッチを操作すると、
    「リフレッシュ」が呼ばれ、イベント関連が全てスイッチに合うようにする
    処理が行われるため、この処理に一番時間がかかります。
    これは変数などを扱って、リフレッシュ可能なタイミングになった時に行われるため、
    スイッチや変数は一度にまとめて行った方が、
    行をまたいで行うより「結構速くなる」というのはあります。

    >2.条件分岐とラベルジャンプ
    速い方から順番に並べます。
    >2-1.条件分岐で「条件を満たさない時の分岐を作成」にそれぞれの条件分岐を内包する。
    >2-3.「条件を満たさない時の分岐を作成」もラベルジャンプもなく、すべての条件分岐を直列に並べる。
    >2-2.条件分岐で条件を満たした時に、以下の条件分岐を終了した時点のラベルへジャンプさせる。

    これは単純に、「実行される行数の期待値」を考えれば分かると思います。
    2-3は、全ての条件判定を行うので一番行数が多くなります。
    2-1は、条件がヒットした後は、全て無視できるので、2-3より軽くなります。
     ただ、処理は速くなりますが、エディタでの見た目が深くなり見づらくなるので推奨できません。
    2-2はイベントコマンド「ラベルジャンプ」に1フレーム使うため、わずかなタイムラグが生じますが、実は一番おすすめです。見た目が一番分かりやすいからです。
    以上ですが、いずれも、わずかの速度の差なので、並列処理を行う場合以外は、ほとんど影響ありません。

    >3.ループ処理と同じコマンドを並べた時の差
    これはおっしゃる通り、同じコマンドを回数分並べたほうが早いです。
    イベントを実行するインタプリタの行数があくまで処理速度に影響するからです。
    とはいえ、その差はごくわずかであり、コマンドを回数分並べるよりも、
    ループを使った方が、「何回繰り返すか」が分かりやすく、デバッグしやすい、というのはあります。

    結論から言うと、イベントコマンドレベルでの処理では、
    わざわざ軽量化のことを考える必要がある場面はあまりなく、
    あくまで自分の組みやすいように組めばいい、ということになると思います。
     
    最後に編集: 2019-01-31
    #24
    munokura, ネコタくろうど がいいね!しています
  5. munokura

    munokura ユーザー

    皆さん
    ご回答いただき、ありがとうございます。
    予想通り「考えるほどの負荷ではない」ということのようですが、少しすっきりしました。
    考える必要性が低い疑問にお答えくださった皆様に感謝いたします。
    大変、興味深かったです。

    1ラベル・1イベントに1フレーム使われるという具体的な例は、自分にとっては(マジか!的な)驚きでした。

    しかし、回答を読みながら、新たな疑問点が浮かんできました。

    コモンイベントの負荷です。
    マップイベントに直書きする方がコモンイベントを呼び出すより負荷が低いと思います。
    しかし、何度も同じ処理を書く手間と、修正時の手間とを減らすためにコモンイベントがあると解釈しています。

    上述の分岐の処理でラベルジャンプの代わりにコモンイベント内で「イベント処理の中断」を使用すると、ラベルジャンプより軽いのでしょうか?
    それともトラブルを生みやすい処理でしょうか?

    どこかで、マップイベントで何もしない状態と判断され固定するならば「イベントの一時消去」をした方が軽くなると読んだ記憶があります。
    その印象から、「イベント処理の中断」も軽い処理なのかな?と思いついた次第です。

    もっとも、マップイベントを「イベントの一時消去」するのは、毎回読みに行くイベントが減るからという理屈だろうと思いますので、まったくの別物だとは思っています。

    理論的な話なのに、「思う」ばかりで情けない話なのですが(笑)
     
    #25
  6. 神無月サスケ

    神無月サスケ ユーザー

    コモンイベントは、マップイベントと負荷は変わりません。
    なぜなら、コモンイベント実行中は、マップイベントは、コモンイベントが終わるのを待っている状態だからです。
    プログラムで言うと、コモンイベントは、「サブルーチンを実行している」のと同じです。
    よって、コモンイベントは、どんどん使ってください。

    コモンイベント内での「イベント処理の中断」は、ツクールによって、「コモンイベントを中断する」のと、
    「イベントそのものを中断する」のがありますね。ややこしいので、僕は使わないようにしています。
    それにあまり軽量化とは関係ありません。

    「イベントの一時消去」は軽量化に効果がありますが、「イベント処理の中断」は効果がありません。
    「イベントの一時消去」を行うと、本来イベントが毎フレーム行っている、updateという処理の大半を
    省略するため、処理がかなり減るので軽くなります。
    しかし、「イベント処理の中断」を行っても、update自体は変わらないため、軽くはなりません。

    というわけで、「もう使わないイベントは一時消去する」というのは、
    イベントの多いマップでは、地味に効果のある方法だといえます。
     
    #26
    くろうどmunokura がいいね!しています

このページを共有