ソースの表示以前のリビジョンバックリンク全て展開する/折り畳む文書の先頭へ Share via Share via... Twitter LinkedIn Facebook Pinterest Telegram WhatsApp Yammer Reddit Teams最近の変更Send via e-Mail印刷パーマリンク × « FreeBSD 11-STABLEでVirtualBox復活(`・ω・´) portsnapにautoなるコマンドが実装されてた » FName::GetPlainANSIString()で正しい文字列が取れない事がある お急ぎのあなたのために、まずは結論。FNameが保持する文字列が必要な時はToString()で生成したFStringを使うべし。GetPlainANSIString()とGetPlainWIDEString()を使うとハマるから止めといた方がいい。 Unreal Engine 4の軽量文字列クラスFName(公式リファレンス)のGetPlainANSIString関数/GetPlainWIDEString関数で取得できる文字列ポインタには、そのFNameインスタンスが本来持っている文字列の一部しか入っていない事がある。恐らく仕様。以下が実証コード。 TArray<FName> Names; Names.Add(FName(TEXT("Hoge_"))); Names.Add(FName(TEXT("Hoge_0000"))); Names.Add(FName(TEXT("Hoge_0001"))); Names.Add(FName(TEXT("Hoge_10"))); Names.Add(FName(TEXT("Hoge_1200"))); Names.Add(FName(TEXT("Hoge_1300"))); Names.Add(FName(TEXT("Hoge_9999"))); Names.Add(FName(TEXT("Hoge9999"))); for (const auto& Name : Names) { UE_LOG(LogWindows, Log, TEXT("◆%s"), *Name.ToString()); UE_LOG(LogWindows, Log, TEXT(" PlainAnsiString=%s (%p)"), *FString(Name.GetPlainANSIString()), Name.GetPlainANSIString()); UE_LOG(LogWindows, Log, TEXT(" [FNameEntry]")); UE_LOG(LogWindows, Log, TEXT(" ComparisonIndex=%d"), Name.GetComparisonIndex()); UE_LOG(LogWindows, Log, TEXT(" [ComparisonEntry]")); UE_LOG(LogWindows, Log, TEXT(" Address=%p"), Name.GetComparisonNameEntry()); UE_LOG(LogWindows, Log, TEXT(" isWide=%d"), Name.GetComparisonNameEntry()->IsWide()); UE_LOG(LogWindows, Log, TEXT(" DisplayIndex=%d"), Name.GetDisplayIndex()); UE_LOG(LogWindows, Log, TEXT(" [DisplayEntry]")); UE_LOG(LogWindows, Log, TEXT(" Address=%p"), Name.GetDisplayNameEntry()); UE_LOG(LogWindows, Log, TEXT(" isWide=%d"), Name.GetDisplayNameEntry()->IsWide()); UE_LOG(LogWindows, Log, TEXT(" Number=%d"), Name.GetNumber()); } 実行結果を見ると、Hoge_10, Hoge_1200, Hoge_1300, Hoge_999で見事に同一のPlainAnsiStringが返ってきているのが分かる(★の部分) LogWindows: ◆Hoge_ LogWindows: PlainAnsiString=Hoge_ (000000021299B988) LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029720 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B978 LogWindows: isWide=0 LogWindows: DisplayIndex=1029720 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B978 LogWindows: isWide=0 LogWindows: Number=0 LogWindows: ◆Hoge_0000 LogWindows: PlainAnsiString=Hoge_0000 (000000021299B9A0) LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029721 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B990 LogWindows: isWide=0 LogWindows: DisplayIndex=1029721 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B990 LogWindows: isWide=0 LogWindows: Number=0 LogWindows: ◆Hoge_0001 LogWindows: PlainAnsiString=Hoge_0001 (000000021299B9C0) LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029722 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B9B0 LogWindows: isWide=0 LogWindows: DisplayIndex=1029722 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B9B0 LogWindows: isWide=0 LogWindows: Number=0 LogWindows: ◆Hoge_10 LogWindows: PlainAnsiString=Hoge (000000021299B9E0)…★ LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029723 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: DisplayIndex=1029723 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: Number=11 LogWindows: ◆Hoge_1200 LogWindows: PlainAnsiString=Hoge (000000021299B9E0)…★ LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029723 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: DisplayIndex=1029723 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: Number=1201 LogWindows: ◆Hoge_1300 LogWindows: PlainAnsiString=Hoge (000000021299B9E0)…★ LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029723 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: DisplayIndex=1029723 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: Number=1301 LogWindows: ◆Hoge_9999 LogWindows: PlainAnsiString=Hoge (000000021299B9E0)…★ LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029723 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: DisplayIndex=1029723 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B9D0 LogWindows: isWide=0 LogWindows: Number=10000 LogWindows: ◆Hoge9999 LogWindows: PlainAnsiString=Hoge9999 (000000021299B9F8) LogWindows: [FNameEntry] LogWindows: ComparisonIndex=1029724 LogWindows: [ComparisonEntry] LogWindows: Address=000000021299B9E8 LogWindows: isWide=0 LogWindows: DisplayIndex=1029724 LogWindows: [DisplayEntry] LogWindows: Address=000000021299B9E8 LogWindows: isWide=0 LogWindows: Number=0 FNameはハッシュ付き文字列として実装されている。文字列はFNameの共用領域に格納され、各FNameインスタンスはその文字列格納領域へのインデックス=ハッシュを保持してる。FNameの同士の比較は互いのハッシュの比較、つまり整数の比較に還元されるため、通常の文字列比較より速いって仕掛けなんですな。 ただ、このハッシュ生成方法がちょっと曲者で、文字列がアンダースコア+ゼロ詰めされていない数値で終わっていたら、その部分を除いた文字列を共用領域に格納し、数値は各FNameインスタンスで保持するという方法なのだ。割と最近のバージョンアンプで変わったらしい(知人曰く4.12あたりで変わった気がすると)。なかなか破壊的な変更をしてくださりやがるな!言葉だと分かりにくいので図を作ってみた。 図を踏まえつつ改めて実行結果を見てみると、条件に合致するHoge_10, Hoge_1200, Hoge_1300, Hoge_999の中身が、その通りになっている事がお分かりいただけよう。Numberが実際の数値+1されているのは、これまた仕様で、数値分割条件を満たさないFNameインスタンス(Number == 0)との区別の為っぽい。 UE4では生成されたオブジェクトのインスタンスに対し、オブジェクト名+連番の名前を自動付与するため、大規模な開発になるとFName文字列ストアの肥大化が無視できなくなり、保持方法を変更したのだと思われる。 こんな格納の仕方で大丈夫なの!?と思うが、ふつーにFNameを使う分には何の問題もない。や、正確には大丈夫じゃなかったからこの記事書いてる訳だけど、文字列の生ポインタ取ってこねくり回すような事をしなければ大丈夫。FName文字列に対して低レベルな操作を行いたい時は、ToString()関数で生成したFStringに対して行う事をオススメする。エンジンのコードを見てもらうと分かるが、ComparisonIndexの文字列にアンダースコアと数値をくっつけて元の文字列を復元してやがるので(笑) ちなみに、実行結果内のDisplayIndexというのは、名前の通り表示用の文字列へのインデックス。簡単に言えば、FName生成時に与えられた文字列のインデックスである。FNameは基本的にcase-preserving(内部的には大文字小文字を区別するが対外的には区別せずに扱う)なので、比較用と表示用で別々の文字列を持つ必要がある訳だ。知らずに使ってると、これも地味にハマりポイントかも。 FName abc(TEXT("abc")); FName ABC(TEXT("ABC")); UE_LOG(LogWindows, Log, TEXT("%s %s %s"), *abc.ToString(), (abc == ABC ? TEXT("==") : TEXT("!=")), *ABC.ToString()); 念のため上記コードで確認したら、LogWindows: abc == ABCとなった。 掘ってみるとFNameには結構罠があるので注意が必要だ。 Comments the original source <a href=https://ugelsatipo.gob.pe>Ledger Live Download</a> 1 | Mariomuh | 2026-04-22 13:43 | reply Hello admirers of premium climate control ! The aesthetic design of the best-air-conditioners is also an important factor for many homeowners. Sleek and modern designs can seamlessly blend with home decor. <a href=http://best-air-conditioners.vercel.app/#></a>. A visually appealing model can be just as important as its cooling capabilities. For consumers who prioritize style as much as functionality, best-air-conditioners.vercel.app reviews aesthetically pleasing units that blend seamlessly into any decor. These stylish air conditioners not only cool efficiently but also enhance your home's aesthetics. Elevate your interior design while enjoying a comfortable climate by choosing an attractive AC model. Essential Features in Air Conditioners at https://best-air-conditioners.vercel.app/ - http://best-air-conditioners.vercel.app/# May you enjoy incredible cooling experiences with the best air conditioners ! 2 | Williamcus | 2026-04-23 23:18 | reply usa online casino real money <a href=“https://onlinecasinosreviewhub.com/”>play live roulette</a> texas online gambling <a href=https://onlinecasinosreviewhub.com/>virtual city casino eu</a> crown bingo 3 | Charlesunjug | 2026-04-25 20:41 | reply Name E-Mail Website 人間の証明として、ボックス内の全ての文字を入力してください。 この項目は空のままにして下さい:Preview Comment blog/2017/2017-01-20.txt 最終更新: 2017-01-24 11:13by Decomo