幻創空戯 GEN-SOH-KUUZA 2026/08/10 18:00

メッシュ生成:内壁の裏面 その2

妹ちゃんとペアプロ開発やってみた #0087

蒼月

Road_Inner_OP を Both を試してみたよ。

20260726-9 … 26-7 はOK
20260726-10 … 26-8 もOK

20260726-9 のスクショ

20260726-7 のスクショ

20260726-10 のスクショ

20260726-8 のスクショ

20260726-11 … 13-4 もOK
20260726-12 は、26-11 を Scene ビューで見たところ。
謎の紫の棒は、部屋の外壁A面だったw

20260726-11 のスクショ

20260713-4 のスクショ

20260726-12 のスクショ

20260726-13 は、26-11 の回転が終わったところ。
部屋の外壁がちょっとだけ見えてる。
気になるといえば気になるけど、まぁ、許容範囲だね。

20260726-13 のスクショ

と、ここまではうまくいってるんだけど、
マズいパターンもあったよ。

20260726-14 は、出口床で回転したところ。
一瞬ちょっとくらいの間だけど
部屋の内壁が表示されないタイミングがあるね。
画面上で壁の面積が大きめだから結構気付く感じ。

20260726-14 のスクショ

妹ちゃん

3m 6s考えました

うん、お兄ちゃん。26-9〜13まではかなり良いね。

・26-9:出口左右の通路内壁が表示された
・26-10:通路接続部の欠けも解消
・26-11:部屋内壁をFrontにした効果も維持
・26-13:外壁A面が少し見えるのは、固定不透明にした設計上のトレードオフとして許容可能

だから、Road_Inner_OP = Bothは採用してよさそうだよ。

一方、26-14は別問題の可能性が高い。

26-14で疑わしい二つの原因

現在の処理では、カメラとプレイヤーの間に壁が入ると、その壁をTRへ切り替え、ヒット距離からalphaを決めている。しかも現在は、
ALPHA_NEAR = 0.5f;
ALPHA_FAR = 0.0f;

なので、条件によっては壁が完全透明になる。さらに、一番近いヒット距離から算出した同じalphaを、対象となった複数の壁へまとめて設定している。

そのため26-14は、次のどちらかだと思う。

可能性A:TRになってalphaが0付近

回転中に部屋内壁がフェード対象となり、
 M_Room_Inner_TR
 Render Face = Both
 alpha ≒ 0
になっている。

この場合、裏面カリングではなく、フェード処理で完全に消しているのが原因だね。

26-14の状況からは、わたしはこちらをやや強く疑っているよ。

可能性B:OPへ戻った直後に裏側から見ている

回転中にSphereCastが壁から外れた瞬間、
 M_Room_Inner_TR(Both)
   ↓ ResetMaterial
 M_Room_Inner_OP(Front)
へ戻る。

しかしカメラはまだ壁の裏側にいるので、短時間だけ描画されなくなる。

現在はヒットしなくなったフレームですぐ通常マテリアルへ戻すため、この境界でも一瞬の欠けは起こり得るよ。

まず行いたい切り分け

A/B対応へ進む前に、簡単な実験を一つ挟むのが安全だね。

一時的に、
private readonly float ALPHA_FAR = 0.2f;
くらいへ変更して、同じ出口床で回転する。

これで26-14の欠けが消えたら、原因はほぼ確実に完全透明化だよ。

まだ同じように完全に消えるなら、次に一時的な確認として、
 M_Room_Inner_OP
 Front → Both
へ変えて26-14だけ再確認する。

・ALPHA_FAR = 0.2で直る
 → alpha設計の問題
・Room Inner OPをBothにすると直る
 → TRからOPへ戻るタイミングと裏面描画の問題
・両方必要
 → 二つが重なっている

原因別の本対応

alphaが原因だった場合

以前後回しにした、
内壁と外壁のalphaを分ける
を、ここで実施する意味が出てくるね。

たとえば、
 内壁:最低alpha 0.15~0.25
 外壁:最低alpha 0.0
とすれば、内壁は完全には消えず、大きな壁面が突然抜けた印象を抑えられる。

OPへ戻るタイミングが原因だった場合

内壁を常時Bothにするのではなく、壁がSphereCastから外れても、
 0.1~0.2秒ほどTRを維持してからOPへ戻す
という短い解除猶予を入れるのが有力だよ。

これなら13-4・13-5のような裏面が常時見える状態には戻らず、回転中の短い空白だけをつなげられる。

現時点の判断

内壁A/Bへ進むのはまだ早いと思う。

今回の26-14は、メッシュに裏面がない問題というより、フェードのalphaまたはTR解除タイミングの問題である可能性が高い。まずALPHA_FAR = 0.2fの一時テストで切り分けるのが、いちばん小さく確実な次の一手だね。

蒼月

private readonly float ALPHA_FAR = 0.5f; // 遠い:薄い

float alpha = Mathf.Lerp( ALPHA_NEAR, ALPHA_FAR, rate );

Debug.Log( $"dist = {dist:F2} / rate = {rate:F2} / alpha = {alpha:F2}");

としてみたよ。

まだ表示されないタイミングがあるね。ログは
dist = 0.75 / rate = 0.17 / alpha = 0.50

20260726-15 で、上から見たスクショをアップしたよ。
部屋壁は、部屋壁側の Collider でヒットを見ているから
ヒットが外れて、OP に戻ったタイミングのような気がするね。

20260726-15 のスクショ

妹ちゃん

うん、お兄ちゃん。その見立てでほぼ間違いないと思う。

今回のログ、
dist = 0.75 / rate = 0.17 / alpha = 0.50
が示しているのは、そのフレームで何らかの壁にはヒットしているということだけなんだ。updateWallAlpha()は全ヒットの中から最短距離を一つ選んで表示しているので、消えた部屋壁自身がwallsNowに残っている証明にはならない。

20260726-15を見ると、回転中のカメラ方向が出口角を斜めに横切り、部屋壁のCollider端をかすめて外れているように見える。そのフレームでは、
 部屋壁:wallsPrevには存在
     wallsNowには存在しない
     ↓
 ResetMaterial()
     ↓
 Room_Inner_OP(Front)へ戻る
     ↓
 カメラはまだ裏側
     ↓
 描画されない
となっていそうだね。

現在のMainCameraは、前回ヒットしていて今回ヒットしなかった壁を、その場で即座に通常マテリアルへ戻す実装になっている。

次に試す修正

まずは回転中だけ、前フレームまでのフェード対象を維持するのがよさそう。

updateWallVisible()で現在のヒット壁を収集し終えたあと、通常表示へ戻すループより前に、これを追加する。

(ソースと説明を略)

この方法の動作

回転中は、
 一度ヒットした壁
   ↓
 途中でColliderを外れてもTRのまま維持
   ↓
 90度回転が終了
   ↓
 次のIDLEフレームで改めて判定
   ↓
 不要ならOPへ戻す
となる。

これなら、

・Room_Inner_OPはFrontのまま
・13-4・13-5の不要な裏面は復活しない
・出口で回転中の一瞬の欠けだけを防げる
・Colliderの大きさを変更しない
・Road_Inner_OP = Bothもそのまま維持できる

という形になるね。

Colliderを広げる方法もあるけれど、現在のColliderはプレイヤー衝突にも使っているので、出口付近の移動可能範囲まで変わる危険がある。まずは表示制御側で吸収する方が安全だよ。

今回の切り分けでalpha原因は否定できたので、ALPHA_FARは元の値へ戻して大丈夫。まずROTATE中だけUnionWithするテストが、いちばんきれいな次の一手だと思う。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索