メッシュ生成:内壁の裏面 その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するテストが、いちばんきれいな次の一手だと思う。