C# / Unity

遭遇した問題と対策:その他のメモ

以下はC#やUnity関連でこれまでに遭遇した問題の中で、「個別にページを割くほどには掘り下げてはいないが残しておきたい事柄」に関して、自分の備忘録を兼ねて書き残していくメモのようなものです。


多くの人が遭遇する共通的の問題というのは誰かがページを割いて説明してくれていたりするものですが、遭遇率の低い、或いは遭遇者の少ないニッチな問題に対してはそうした「特集」が組まれることは少ないので、実にフォーラムスレッド等においても「そのスレッドの本題ではないが投稿者が添えたサイドノート」といった小粒の情報が繋がって線となり面となって技術的な山脈の一部をおぼろげながら露わしめる知識の糧と成るといったことが往々にしてありましたものですから、では一つそれに倣って見よう、こうして残したメモが誰かの糧になるか知らんと思った果ての試みでありますので須らく一つ一つに割いている労力は少なくして居ります。

VisualStudio:C#コードのカラーを保ったまま他のテキストソフトへのコピーができない

←こういう色がついたままコピーしたい。

←現実はこうなってしまう

なぜか一部だけ色がついたり(つかなかったり)する

Visual Studioで、コードのカラーを保ったままリッチテキスト(HTMLテキスト)としてコピーするには、これまでは以下の2つのいずれかが機能していたよう。

しかし、この両方とも現状では機能しない・・・。

OneNoteに貼り付けると、上の「現実」の画像のように一部だけ色がつくものの、他は全部色情報が消えてしまう。

調べてみると、以下のフォーラムスレッドでこれと思しき問題について議論されていて、Roslynの動作の何かが原因でこうなっているらしく、CopyAsHtmlを修正予定だがリリースの見込みはすぐには立っていないっぽい的な感じ(※フォーラムを覗いてこの文章を書いてる日付は2024/5/10)

https://github.com/microsoft/VS-PPT/issues/271

Unsupported Type 〇〇〇

インスペクターやOdin Inspector等で、[Serializable]なclass/structを表示しようとするとこのメッセージが出た。

プレハブを編集しているときに発生する。

(Report構造体にエラーが出た例)

れは構造体が

[Serializable]

public struct Report

{

public int p;

}

こんな単純なものでもエラーが消えない。

 

このバグは、「プレハブに関連して、ゲームオブジェクトにアタッチされている間に仮想シリアライズされている[Serializable]クラスを変更した際に発生する」とのこと。

コンポーネントを一旦削除して再度アタッチすれば治るはず、とのこと。実際再度アタッチしたらエラーが出なくなった。

 

参考

https://discussions.unity.com/t/unsupported-type-generic-mono-when-using-serializable/52750

エラー:CS1666 固定サイズバッファーは使用できません

固定長配列を使った構造体を作ったのだが、固定長バッファで変なエラーがVisualStudio側で出る(Unity側では出ない)

「エラー  CS1666:fixed でない式に含まれる固定サイズ バッファーは使用できません。fixed ステートメントを使用してください。」

 

[Serializable]
public unsafe struct OctreeCell
{
    [SerializeField, HideInInspector]
    fixed uint oct[8];

    public OctreeCell(uint defaultValue)
    {
        for (int i = 0; i < 8; i++)
        {
            fixed (uint* p = &oct)
            {
                oct[i] = uint.MaxValue;
            }
        }
    }
}

 

MSDNにはこのエラーの説明ページがあるが、その通りにやってもダメ。

https://docs.microsoft.com/ja-jp/dotnet/csharp/misc/cs1666

 

このように、言われた通りfixedステートメントを使用しようとしても、そもそもoctにアクセスした段階でエラーになっているのでどうしようもない。属性を外してみたりstructをグローバルに出してみたりしたがダメ。

ポインターは詳しくないので何でこうなるのかは分からないが、Unity側は問題なくコンパイルを終えるので無視するしかない。


localToWorldMatrixとTransformPointが違う結果を返す(点座標変換で)

試したコードが以下。

 

[CustomEditor(typeof(Wheel), true)]
public class WheelEditor : Editor//VehiclePartsEditor
{
    Wheel t;
    private void OnEnable()
    {
        t = target as Wheel;
 
        var localPosition = new Vector3(1, 2, 3);
        var worldPosition1 = t.transform.localToWorldMatrix * localPosition;
        var worldPosition2 = t.transform.TransformPoint(localPosition);
        Debug.Log(worldPosition1 + " / " + worldPosition2);
    }
}

※t.transform.positionは(0,0,0)でないことを確認済み


その結果がこれであった。

これはおかしい。localToWorldMatrixとの積を関数化したのがTransformPoint()なので結果は同じになるはずだ(※Matrixについてよく知らなかったのでそう思っていた)。

だがTransformPoint()は正しい結果になっているのに対し、localToWorldMatrixとの直接の積ではlocalPositionの初期値と同じ値が返ってくるのはどういうわけなのか?

(結果がVector4になる違いはあれど)

 

その答えがフォーラムスレッドにあった。


以下引用(DeepL機械翻訳・一部改変あり)

-------------------------------------------

ここでの問題は、Vector3の位置を渡している可能性が高いことです。しかし、4x4の行列は同次座標空間1を表します。同次座標における位置/点/方向は4つの要素を持ち、3つではありません。UnityはVector2 / 3 / 4構造体に対して暗黙の変換演算子を持っています。しかし、この場合 "w "座標は0に初期化されます。これはベクトルを "方向 "ベクトルに変えてしまうことになる。方向は、行列が適用するかもしれない平行移動の影響を受けません。つまり、ベクトルの拡大縮小と回転だけが行われます。

 

これを修正するには、wを "1 "に設定したVector4を渡す必要がある。

Vector4 v = pos;
v.w = 1;
Vector4 wPos = localToWorld * v;

MultiplyPoint3x4を使う方法もある。これはおそらくより良い解決策だろう。

これは行列との直接乗算を行い、行列が3×4の行列であると仮定します。

 -------------------------------------------

https://discussions.unity.com/t/math-behind-transform-transformpoint/199343


Vector4にしてw=1を入れて渡すと、正しい結果が返ってきた。