#タスクシステムとは
ここで言うタスクシステムとは、かつてゲームプログラミングで使われていたとされる技法の事です
ざっくり言うと、タスクのリストをプライオリティー値で並べ、前から順番に実行していくような感じです
#何故ダメか
もともと手続き型プログラムは、実行してほしい処理を順番に書き並べたものです
言い換えればもとよりプログラムはタスクのリストであって、それをプログラムリストというわけです
それをタスクシステムは動的にタスクのリストを持って、さらにはプライオリティー値で並べ替えるので
"処理順がソースコードに表れません"
手続き型言語では処理の順番が最重要にもかかわらずです
それも動的に処理の順番が入れ替わるなら致し方ない部分もあるかもしれませんが大概は固定です
なら、実行順はソースコードで静的に可視化されたほうが良いわけです
どう頑張っても実行順がソースコードに表れないタスクシステムなんかが最適解になることはあり得ないのです
まっーーーたくナンセンス極まりないです
#何故タスクシステムなんかが流行ったのでしょう
思うに、こういう人たちは要は極端なんです
グラデーションというものを分かってません
#どうすればよいか
普通のアプリプログラムのように、ごく普通にプログラムを書けばよいだけです
とにかく、タスクシステムはタスクの並べ替えが極悪なので、それを取り除きます
そうすると普通のプログラムになります
具体的には型や種類ごとにコンテナを用意して突っ込み、foreach
などで処理すればよいだけです
このとき、コンテナに突っ込まれる各アイテムの並び順(実行順)は問いません
逆に、順番を問わないものだけを同一コンテナに入れます
プライオリティー値による並べ替えは有りません
もし処理の順番に依存関係があるなら、突っ込むコンテナを分けます
経験則ですが、型ごとにコンテナを分けるだけで十分なことが多いです
また、どの順で実行してもよいという事は並列に実行してもよいという事でもあるので
並列実行の余地があります
container_t< player_t * > players;
container_t< enemy_t * > enemies;
・
・
・
for( auto &player: players )
{
player->update();
}
for( auto &enemy: enemies )
{
enemy->update();
}
for( auto &player: players )
{
player->nanika();
}
・
・
・
このようにコンテナをforeach
なんかしながら
自由気ままに自分が処理したい順に好きなようにプログラムを書いていきます
プログラムのプログラムリストとしての機能を取り戻した瞬間です
きもちいい~~~
実行順はプログラムを見たまんまです
これぞ"プログラム"
#一見よく似てるけど
共通の処理をまとめるため、
1フレームに1回アップデートするインターフェースupdatable_t
を用意したとしましょう
これを実装したオブジェクトはコンテナupdatables
に入れられ、一フレームに一回update
が呼ばれます
container_t< updatable_t * > updatables;
・
・
・
for( auto &updatable: updatables )
{
updatable->update();
}
これは古典的なタスクシステムとよく似てますが、一つ決定的に違うのは
コンテナの中身の実行順は問わないということです
もし実行順に依存関係があるなら、updtablesには入れずに、別口で処理します
ここで依存関係があるからと並べ替えなんかをすると
プログラム上には表れない見えない依存関係ができて邪悪なわけです
タスクシステムのまずい点です
#何事も例外は有るよね
それでもコンテナに突っ込んだオブジェクトを並べ替えて処理したいことは有るでしょう
しかしそれは局所的にそうやれば良いだけであって、プログラム全体が犠牲になる必要は有りません
#結論
処理をプライオリティー値で並べ替えるタスクシステムは窓から投げ捨てましょう