Siv3D(C++)で初めてゲームを作る方に向けたTips


今年の5月頃にSiv3Dでゲーム開発を始めました。
以下はこの半年ほどで集めた知見や質問に対する回答です。
DiscordのSiv3Dコミュニティの皆様、ありがとうございます。

# Q.共有データに登録したフォントにaddFallbackするには？
A.共有データなどに存在する寿命が尽きないフォントを指定する

# Q.アラビア語はサポートされている？
A.RTL(右から左へ書く言語)はサポートされておらず。ただし、addFallbackで指定する等以外ではエラーが発生することはあまり無い

# Q.OpenAIのAPIを叩けるか？
A.OpenAI::Chat::Completeメソッドがある

# Q.OpenAI::Chat::Completeメソッドにおいて、応答を続けることは出来るか？
※翻訳を頼む時に時々拒否されが、特定のキーワードを含む返事を返すことでこれを突破出来る為、応答を続けたい
A.以下の59.8 の方法を参照
https://siv3d.github.io/ja-jp/tutorial3/openai/

# Q.Windowsで作成したexeはそのままmac環境に持って行っても動くか？
A.動かない

# Q.マップ表示などで、最終的に複数のテクスチャを一枚のテクスチャとして扱いたい。可能か？
A.以下を参照
https://siv3d.github.io/ja-jp/tutorial3/render-texture/

# Q.ボーンアニメーション対応の予定はあるか？
A.対応に対して前向きとのこと

# Q.パーティクルシステムは存在するか？
A.以下を参照
https://siv3d.github.io/ja-jp/samples/2d/#13-%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%AF%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0

# Q.フェードインが遅いとき、どうする？
A.処理を軽くする以外方法は無し。以下がその代表例。
・アセットの読み込みであれば非同期でのアセット作成
・Audio であればストリーミング再生
・フォントのプリロードを行う

# Q.フォントのプリロードは、シーンをまたいでも有効か？
A.同一の Font オブジェクトであれば、一度でも描画または preload した文字はいつまでもキャッシュされ、即座に使える
※ゲーム中に突然新しい文字を数百文字登場させると、それらの初回描画にコストがかかり、1 フレームに数百ミリ秒以上かかることがある

# Q.GPUを消費させないテクニックはあるか？
A.描画負荷を下げる方法としては
・シーンやウィンドウの解像度を下げる
・画面外のものを描画しないようにして .draw() の回数を減らす
・Siv3D 内部処理における Draw call（Profiler::GetStat().drawCalls）の少ないプログラムにする（1,000 以下が望ましい）
（テクスチャやステートを切り替えると Draw call が増える。例えばマップチップが 1 チップごとに独立した Texture だと、違うチップを描くごとに Draw call が増えてしまうので、
1 枚のテクスチャにパックする。）
・画面の更新が無いときは System::Sleep() で FPS を抑制する

# Q.LineStringにテクスチャを張り付ける方法はあるか？
※汚れのような質感を付与したい
A.以下の77.21を参照
https://siv3d.github.io/ja-jp/tutorial4/physics2d/

# Q.KlattTTSによる文章読み上げに関するドキュメントはどちらにあるか？
A.Siv3D/KlatTTS.hpp にあるのがすべて
なお、大昔のアルゴリズムなので「どうぶつの森の住人 / 昔のロボットみたいな感じの音声」になる

# Q.SayとTextToSpeechの音色を変えられるか？
A.変更できるのは言語のみ。指定した言語が同じでも、環境によっては性別が異なる場合も

# Q.漫才形式のチュートリアルを実装したい
A.チュートリアルでキャラクターにしゃべらせたい場合は、VOICEVOX を含む無料または市販の音声合成ソフトを使って読み上げメッセージを .mp3 ファイルなどに出力するのが良い
ゲーム内で再生しなくても、チュートリアル動画を YouTube で公開し、ゲーム内で System::LaunchBrowser() で YouTube ページへ誘導することも
Siv3D でランタイムに VOICEVOX を使うサンプルは以下
https://discord.com/channels/443310697397354506/998781438264623155/1151169406802604104

# Q.シューティングゲームでクリック時に弾を発射、その時同時に画面を揺らしたい時、UIだけは揺らしたくないが？
A.座標変換の適用外にすれば UI は揺れない（新チュートリアル 39.9）

# Q.貫通弾を実装している。毎秒衝突判定してしまうので、多段ヒットしてしまう。対策は？
A.もし弾に ID を持たせられるなら、敵は受けた弾の ID を Array に記録し、同じ弾からダメージを受けないというのが最も良い

# Q.フランス語環境でもparse関数は「.」を使った小数点を変換出来るか？
A.Parse<double>, Parse<float> は確実に 1.23 を正しくパースする。
Parse<Vec2> や Parse<ColorF> はロケールの影響を受ける stringstream 経由でパースするのですが、これもプログラムで明示的にロケールを変更していない限り大丈夫

# Q.OpenSiv3D製のゲーム&ソフトウェアのみを集めたor投稿出来るサイトはあるか？
A.Discordに専用のチャンネルがある

# Q.以下にある「C++/Siv3D と文法が近いスクリプト言語」とは？
https://zenn.dev/reputeless/books/siv3d-documentation/viewer/quick-example
A. AngelScript
Siv3D での使い方は検索でいくつか見つかる。
スクリプトから使える Siv3D 機能は多くないので、C++ でホットリロードが可能な現在は、開発への導入は非推奨

# Q.midiやmp4にはループタグがあると思うが、RPGツクール等のように、このループタグを用いて曲の一部のみをループさせることは出来るか？
A.それらはツクールの独自拡張。ループタグというものはもともと無い
なので Siv3D では非対応。MIDI の場合は
https://wl-amigo.github.io/LoopMID2LoopOGG/
のようなアプリで波形ファイルに変換するとよい。
ロードも早く、ストリーミング再生もできるようになる

# Q.TextureAssetのrotatedメソッドはどこを原点に回転する？
A.チュートリアル 8.3 のように、軸は選べる
https://zenn.dev/reputeless/books/siv3d-documentation/viewer/tutorial-texture

# Q.Scene::Time()を初期化する方法はあるか？
サウンドノベルを作成する時、以下の方法で実装すると
Nが引き継がれてしまう。
https://zenn.dev/reputeless/books/siv3d-documentation/viewer/tutorial-font#14.14-テキストを-1-文字ずつ表示する
A.代わりにStopwatchを使うことをおすすめする

# Q.色を指定する時、カラーコード（#FFFFFFFFのような形式）でも指定出来るか？
A.ColorF(U"#FFeeDD")のように出来る

# Q.Gmailを起動したいが？
A.s3d::System::LaunchBrowserがある

# Q.ArrayにC#のTryGetValueにあたるメソッドはあるか？
A.Array::fetch(indnx, defaultValue) が近い

# Q.モニターのスケールを変更する方法はあるか？
A.OS の設定を変える方法は用意していない

# Q.バイナリ化について、Classの中にClassがあるような構造でもシリアライズ可能か？
A.シリアライズ可能な型はシリアライズ可能です

# Q.JSONライブラリでも日本語の読み取りエラーが発生する時がある
A.JSONファイルの文字コードを確認すると良いかもしれない

# Q.画面外のオブジェクト（テクスチャなど）は画面内と同等のメモリを食うか？
A.テクスチャは作成した時点でメモリを消費し、それ以降は何もない。
画面外に描画したものにも GPU の draw() 命令は発行されるので、画面外に無駄に大量に描画すると実行時性能が低下する
不要な描画はしないように

# Q.textureのuvメソッドとは？
A.texture.uv(u, v, w, h) は、テクスチャ上の矩形を UV 座標で指定して TextureRegion を作る関数
UV 座標は画像の左上を (0, 0), 右下を (1, 1) とするテクスチャ上の座標

# Q.四角形のフチが端から端へ光っていく演出をしたい
A.Rect に example/particle.png の一部を貼り付ける方法が、3 行程度で出来る
https://gist.github.com/Reputeless/c7bdec7b462118581b56e35fb39236a0

# Q.レイアウトを組むとき、どう実装するのが良い？
A.基準となるゲームの画面解像度(例えば800x600)を決めておいて、実際の解像度と基準解像度の高さ同士の比を使って座標をスケーリングするとやりやすい

# Q.Siv3D が使用している TOML ライブラリが、日本語コメントを正しく処理していない
A.v0.8 でライブラリを変えるので直る

# Q.exeへ引数を渡す&渡した引数を取得する方法はあるか？
A.Visual Studio の場合、デバッグ実行時にコマンドライン引数を追加して呼び出すプロパティがあるので、
それを使うとデバッグ実行時に設定したコマンドライン引数が自動的に使われて呼び出される

# Q.文字列のスペース埋めを簡単に行える方法はあるか？
A.U"{:[フィル文字][配置]文字幅}"_fmt(文字列) で文字列を文字幅までフィル文字で埋められる
フィル文字には任意の1文字（省略すると半角スペース）、配置には <（左揃え）、^（中央揃え）、>（右揃え）のいずれか（省略すると左揃え）、文字幅には正整数を指定
例：
U"{:10}"_fmt(U"XXX") → XXX       
U"{:0>6}"_fmt(42) → 000042

String::lpadded(size_t length, char32 fillChar = U' '); という String のメンバ関数もある

# Q.Effectクラスを宣言すると、Assetエラーが出る
A.Effectにテンプレートパラメータとして指定したクラスの方にTexture等の生成コードが含まれていて、それを毎フレーム呼び出してしまっているのではないか？
なおEffectクラスは毎フレーム生成するのではなく、メンバ変数で持つべき

# Q.FFT::Analyzeなるものを発見したが、これを使えばドラムのリズムだけ抽出するといったことが出来るか？
A.高速フーリエ変換は波形を周波数ごとに分解するので、特定の周波数や音程に反応するものは作れる
ただ、周波数だけでドラムのリズムを取るのは難易度高い

# Q.指定したenumの要素をarrayに全格納する方法は？
A.連番であれば Range(from, to) .map(ToEnum<E>)
連番でなければ magic_enum を使うと実現できる
magic_enum の場合、扱える数値の上限があるので enum 側に工夫が必要

# Q.シーン、もしくは2Dcameraを暗くする方法はあるか？
A.ScopedColorMul2D で例えば ColorF{ 0.8 } の「カラー乗算」を適用すると、適用中に .draw するものがすべて 80% の明るさになる。
色のバランスを変えて夕暮れの赤っぽい表現もできる