お世話になっております。
【前提の認識】
Massで動作する群衆用の横断歩道待ちのスロットについて、
こちらを生成する処理はMassCrowdSubsystem::CreateWaitSlot()にてゲーム開始時に実行される認識です。
【確認した問題点】
スロット群はレーンを中心として左右対称に生成されることを意図しているのかと思ったのですが、
現状はそのようになっておらず、レーンの片側に偏って生成されており、対抗レーンに被るような形になっているようです。
試しに以下のように変更してみたところ、スロットたちがレーンを中央として左右に生成されることを確認しました。
```
WaitArea.Slots.Reserve(NumSlots);
const float UsableSpace = TotalSpace * 0.75f; // 追加
for (int32 SlotIndex = 0; SlotIndex < NumSlots; SlotIndex++)
{
const float U = (SlotIndex + 0.5f) / (float)NumSlots;
FCrowdWaitSlot& Slot = WaitArea.Slots.AddDefaulted_GetRef();
Slot.Forward = Forward;
Slot.Position = Base + Left * (UsableSpace * 0.5f - UsableSpace * U) - Forward * ((SlotIndex & 1) * SlotSize * 0.5f); // 変更
Slot.Radius = SlotSize * 0.5f;
}
```
【質問】
・現在MassCrowdSubsystem::CreateWaitSlot()のスロット生成アルゴリズムは意図通り機能していますでしょうか?
・もし不具合であれば推奨の修正方法はありますでしょうか?
ご確認よろしくお願いいたします。
[Attachment Removed]
お世話になっております。
横断歩道待ちのスロットについて、正確には MassCrowdSubsystem::CreateWaitSlots()(複数形)ですが、呼び出し経路は BuildLaneData() 経由で、サブシステム初期化時(UMassCrowdSubsystem::Initialize() が登録済み ZoneGraphData を走査)に加えて、後から ZoneGraphData が登録されたタイミング(PostZoneGraphDataAdded、ワールドパーティションのストリーミング等)でも走ります。エディタでは RebuildLaneData()(設定変更時、ゾーングラフビルド完了時、コンソールコマンド ai.mass.CrowdRebuildLaneData)から再構築されます。ゲーム開始時という認識自体は概ね合っていますが、一度きりではない点だけご注意ください。
質問1:現状のアルゴリズムは意図通りか
「レーンを中心に左右対称」という前提とは異なり、片側に寄せるのは現在の意図的な設計となっています。
SlotSize = s、TotalSpace = T、Left 方向の座標を ℓ(Base 基準)として整理すると、スロット中心は
ℓ_i = -SpaceRight - s/2 + 0.75 * T * U_iとなり、NumSlots ≈ T/s を代入すると
- 右端スロット中心:ℓ = -SpaceRight - 0.125s(横断歩道の右端をわずかにはみ出す)
- 左端スロット中心:ℓ = -SpaceRight + 0.75T - 0.875s
- 左端に残る空き:0.25T + 0.375s(=全幅の25%が連続した通路として残る)
つまり”使用幅を75%に絞って、余った25%を Left 側にひとまとめの通路として空ける"という構造です(直近のコメント"[Content removed] so that there’s enough space for incoming pedestrians to pass through.
"「対向から来る歩行者が通り抜けられるように」という部分)。左右対称にすると、この通路が左右12.5%ずつに分割され、通り抜け用としては機能しなくなります。右側通行を前提に、待機者を右に寄せて左を対向通路として空ける、という意図と考えられます。ただし、これはコメントで述べてあるように、式には厳密ではない雑な部分が2つあります。
- 端のはみ出し:SlotSize/2 の項が 0.75 のスケーリングを受けないため、右端スロットの中心が横断歩道の端から 0.125s 外に出ます。半径を含めると 0.625s はみ出します。
- スロット数と使用幅の不整合:NumSlots は全幅 T から round(T / s) で求めているのに、配置は 0.75T の範囲に詰め込んでいます。結果として横方向のピッチが 0.75s になり、ジグザグの前後オフセット s/2 を加味しても隣接スロット間距離は約 0.90s で、直径 s に足りず円が重なります。
質問2:推奨の修正
・現行の設計を維持したまま、式の雑さだけ直す場合
使用幅からスロット数を求め、右端から素直に詰める形にすると、はみ出しもピッチの不整合も同時に解消します。ただし NumSlots が現行比で25%減るため、同時に待機できる人数が減ります。収容数を維持したい場合は NumSlots は現行のままにして、位置計算だけ差し替えてください
const float UsableSpace = TotalSpace * 0.75f;
const int32 NumSlots = FMath::Max((SlotSize > 0 ? FMath::FloorToInt(UsableSpace / SlotSize) : 1), 1);
...
WaitArea.Slots.Reserve(NumSlots);
for (int32 SlotIndex = 0; SlotIndex < NumSlots; SlotIndex++)
{
const float U = (SlotIndex + 0.5f) / (float)NumSlots;
FCrowdWaitSlot& Slot = WaitArea.Slots.AddDefaulted_GetRef();
Slot.Forward = Forward;
Slot.Position = Base + Left * (-SpaceRight + UsableSpace * U) - Forward * ((SlotIndex & 1) * SlotSize * 0.5f);
Slot.Radius = SlotSize * 0.5f;
}
**・ 左右対称にしたい場合**
ご提案頂いた変更で意図どおりになりますが、採用する場合は以下2点だけご認識ください。
- 上記のとおり通路が左右12.5%ずつに分割されるため、対向歩行者の通り抜け余地という元の設計意図は失われます。日本の左側通行に合わせたいだけであれば、対称化ではなく A案のバイアスの符号を反転する(-SpaceRight 起点を +SpaceLeft - UsableSpace 起点に変える)方が意図に沿います。
- 隣接レーンが片側だけに存在する非対称ケースでは、Base(自レーン中心)と全幅の中心が一致しないため、スロットが横断歩道の外側にはみ出します。
[Attachment Removed]