[自作PC] FURCRAEA_BUILT 総額102万程度の構成 

[Custom-built PC] FURCRAEA_BUILT – Configuration costing approximately 1.02 million yen.

【パーツ構成URL】
◆CPU➡ https://amzn.to/4dh953L
intel インテル CPU 第13世代 Core i9-13900K
◆マザボ➡ https://amzn.to/4rZYI8c
ASUS ROG MAXIMUS Z790 FORMULAにした
◆メモリ➡ https://amzn.to/4cd8uiw
CORSAIR DDR5-6000MHz デスクトップPC用メモリ VENGEANCE DDR5シリーズ (PC5-48000) Intel XMP メモリキット 32GB ホワイト [16GB×2枚] CMK32GX5M2E6000C36W
◆CPUクーラー➡ https://amzn.to/40X0BHR
CORSAIR iCUE LINK H150i LCD AIO 水冷式 CPU クーラー – 【QX120 RGB ファン/IPS LCDスクリーン付き】 – 360mm ラジエーター Intel LGA 1700、AMD AM5 に対応 – iCUE LINK システムハブ付属 ホワイト CW-9061010-WW
◆M.2 SSD(2TB)➡ https://amzn.to/4sFSrQk
CORSAIR MP600 PRO Low Profileシリーズ 2TBモデル 【LPX PCIe Gen4 x4 NVMe M.2】 SSD メモリ ホワイト CSSD-F2000GBMP600PLPW PS5拡張適用
◆HDD➡ https://amzn.to/4sE41ey
Western Digital ウエスタンデジタル WD Red Plus 内蔵 HDD ハードディスク 10TB CMR 3.5インチ SATA 7200rpm キャッシュ256MB NAS メーカー保証3年 WD101EFBX-EC 【国内正規取扱代理店】
◆電源ユニット➡ https://amzn.to/4s1jDYE
ASUS pc電源ユニット Lambda A++ 1200W ATX ROG-THOR-1200P2-GAMING Aura Sync 国内正規代理店品
◆グラボ➡ https://amzn.to/4118ITB
ASUS GeForce RTX 4080 搭載ビデオカード 16GB OC GDDR6X / ROG-STRIX-RTX4080-O16G-WHITE 日本正規流通品
◆PCケース➡ https://amzn.to/4uY1sWg
長尾製作所 オープンフレーム ver.ATX WHITE
※本記事にはアフィリエイトリンクが含まれます。

この構成なら、かなりちゃんとしてる。
白で統一したハイエンド寄りの見た目重視構成としてまとまってるし、互換性も基本問題なしです。CPUはCore i9-13900Kで24コア32スレッド、最大5.8GHz。マザボのROG MAXIMUS Z790 FORMULAはLGA1700対応で13/14/12世代をサポートしているので、組み合わせ自体は普通に合っています。メモリもDDR5-6000のIntel XMP対応で、Z790環境と噛み合っています。

かなり強いのは、見た目だけじゃなく冷却と電源もちゃんと盛れているところ。
13900Kは公称でProcessor Base Power 125W、Maximum Turbo Power 253Wなので発熱は重めですが、H150i LCDは360mmラジエーター採用でLGA1700対応です。ROG THOR 1200P2は80 PLUS Platinumの1200W電源なので、RTX 4080とi9の組み合わせでも電源容量はかなり余裕があります。

グラボもROG STRIX RTX 4080 WHITEなら、性能も見た目もこの路線にかなり合ってる。
ただしこのクラスは大型カードなので、ケース側の物理条件は確認したいところですが、今回のケースは長尾製作所のオープンフレーム ver.ATXで、そもそも“PCパーツが主役”の検証用・展示向けフレーム寄りなので、サイズ干渉の心配は一般的なケースよりかなり少ないです。

気をつけるなら、いちばん大事なのは13900KまわりのBIOSです。
Intelは13世代/14世代Coreデスクトップ向けの不安定化要因として、Intel推奨を超える電力設定やマイクロコードの問題を案内していて、ASUSも2024年8月以降のBIOSで新しいマイクロコードとIntel Default Settingsを反映したと案内しています。なので、この構成なら組んだ直後にZ790 FORMULAのBIOSを最新へ更新して、Intel Default Settings系で使うのがかなり重要です。すでにダメージを受けた個体は更新で治るわけではない、という注意も出ています。

あと、細かく見ると少しだけクセはあります。
SSDのMP600 PRO Low Profile 2TBはGen4 x4 NVMeで使えるので問題ないですが、Low ProfileはPS5向けっぽい背の低さ重視で、マザボ側にしっかりしたM.2ヒートシンクがあるZ790 FORMULAだと“このSSDでなければならない理由”は薄めです。逆にHDDのWD Red Plus 10TBはCMR・7200rpm・256MBキャッシュのモデルで、保存用としては真っ当です。

結論としては、
**この構成は「かなり豪華で、白統一の見た目も強い、ちゃんと実用になるハイエンド自作」**です。
そのうえで本音を言うと、

  • マザボはかなり高級寄り
  • 電源1200Wは余裕多め
  • オープンフレームだからホコリ・騒音・安全性は普通のケースより不利
  • 13900Kは最新BIOS前提で使いたい

この4点がポイントです。

かなり“見せる自作PC”としては強い構成。
必要なら次に、**この構成の「良い点 / 無駄に高い点 / 今買うなら置き換え候補」**を容赦なく仕分けます。

参考URL


z790 Hero 【総額75万】今一番アツいケース『NZXT H9 』で最強の自作PCを組み立てます。せろりんね
https://youtu.be/qP1vu1NQd7w?si=vFDLyee4NsAAqM75

【自作PC】最新の人気白パーツで最強なゲーミングPC組んでみた!【CORSAIR】せろりんね
https://www.youtube.com/watch?v=Qtii3saYP1s

ASUS ROG MAXIMUS Z790 FORMULA を最新 の bios に アップデートしたよ。

1,BIOSまたはMEファームウェアをアップデートする前に、BitLocker回復キーをバックアップし、オペレーティングシステムでBitLocker暗号化を一時停止してください。

BIOSをアップデートする前にBitLockerを一時停止する

[スタート]メニューをクリックします。
[コントロール パネル]、[システムとセキュリティ]、[BitLockerドライブ暗号化]の順に移動します。

無効なのでよし。

2,ASUS ASUS ROG MAXIMUS Z790 FORMULA 最新のUEFI BIOSは、サポートページからダウンロード
https://rog.asus.com/jp/motherboards/rog-maximus/rog-maximus-z790-formula/helpdesk_bios/

バージョン 2001
14.04 MB 2025/05/19
SHA-256 :5F301C30C43AF188BA0726D9DE5AE83860221197CC57CB92DE23BE20BAC2165D
「1. Intelマイクロコードをバージョン0x12Fにアップデートすることで、Intel第13世代および第14世代システムにおけるVminシフトの不安定性の原因となる可能性のあるシステム状態をさらに改善します。
このBIOSをアップデートすると、対応するIntel MEも同時にバージョン16.1.35.2557にアップデートされます。このBIOSをアップデートした後、後で古いBIOSに戻した場合でも、MEのバージョンは更新されたままになりますのでご注意ください。USB
BIOS Flashbackツールを実行する前に、BIOSRenamerを使用してBIOSファイル(A5471.CAP)の名前を変更してください。」

3,アップデート手順


USBメモリの準備:
USBメモリをFAT32形式でフォーマットする。
ダウンロードした圧縮ファイルを解凍し、中身をUSBメモリのルート直下(フォルダに入れない)にコピーする。
BIOSアップデート (EZ Flash 3):
USBメモリをPCのBIOS USBポートに差し込み、PCを再起動する。
画面が表示されたら [Delete] キーを連打しBIOS (UEFI) 画面に入る。
[F7] キーを押して「Advanced Mode」に入り、

「Tool」メニューの「ASUS EZ Flash 3 Utility」を選択する。

USBメモリ内のBIOSファイルを選択し、

bitlockerのオフにしたかい?の警告が
でるのでYES

EZFLASH
このファイルを読み込みますか?


YES
BIOSを本当にアップデートしますか?YES



アップデート成功!自動的にリセットします
何回も自動で再起動される
1.bios updating.


2.ME Firmware is updating.


3.BIOS is updating Thunderbolt Num firmware.

4.BIOS is updating Thunderbolt Nvm firmware.
Do not shut down or reset the system to prevent system bootup failure.
ImageSize : 0x66000
Written so far : 0x64000 bytes
Image write finished.

いずれも
not shut down or reset the system to prevent system bootup failure.
なので触らない事

自動的に再起動する。絶対に電源を切らない

Before making any adjustments in the BIOS,
please press F5 to load the factory default settings to ensure smooth operation.
If setting up Intel RAID,
configure VD options according to the interface type for better compatibility.
Now, please press F1 to enter BIOS setup.

BIOSで設定を変更する前に、
F5キーを押して工場出荷時の設定を読み込み、スムーズな動作を確保してください。
Intel RAIDを設定する場合は、
互換性を高めるために、インターフェースの種類に応じてVDオプションを設定してください。
次に、F1キーを押してBIOSセットアップに入ります。

F5押したが、反応なしなのでF1押した

無事にBIOS アップデートが成功していた。Intel Default Settingもある。

設定を保存して再起動で

Windowsも起動した。

完了:


ASUS ROG Zephyrus G14 GA401IV バッテリー交換



ROG Zephyrus G14 GA401IVのバッテリー(型番: C41N1908)交換は、裏蓋のネジ11本を外し、内部コネクタを抜いて交換する比較的容易な作業です。バッテリーは約6,000円〜1万円で販売されており、PH1ドライバーや樹脂製のヘラがあれば約20〜30分で完了します。


バッテリー交換の手順
事前準備: パソコンの電源を切り、ACアダプタを抜きます。
裏蓋の取り外し: 底面の11本のネジを外します(ゴム足の下のネジも含む)。

下側(ヒンジと反対側)のネジは完全に外れない構造になっているため、そこからプラスチックのヘラでケースをこじ開けます。


バッテリーの取り外し:
バッテリーを固定しているネジ4本を外します。



バッテリーとマザーボードを繋ぐコネクタの金属ブラケットを右にずらします。


黒いサイドのポッチをドライバーでおしてから白いコネクタを上に引き抜いてバッテリーを切り離します。



新しいバッテリーの取り付け: 逆の手順で装着します。


動作確認・再組立て: 裏蓋を閉じる前に電源が入るか確認すると確実です。

[UE5.7.4][C++]遂に完成したC++プラグインUE用HLSL.EditorのMaterial作成機能

もうこれでノードスパゲッティから解放される

導入方法

0,以下のリンクをダウンロード (特に理由がなければ最新版使ってください)
furcraeaHLSLEditor_UE5.7.4V6_2.zip
https://drive.google.com/file/d/1BzMiQt4dXcu8p-dIfkyH3v1SRVSKjiCn/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V6.zip
https://drive.google.com/file/d/1APYn65u1yo3xkJlDFmqJ2yuCE5zHViqc/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V5.zip
https://drive.google.com/file/d/1YiUHmR1g6d9WwvAtd1rGADsiNZEXRMNX/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4.zip (V4)
https://drive.google.com/file/d/1gInP7W5hFB3pwlwbrbkekSzC8xOwusap/view?usp=sharing

furcraeaHLSLEditor_UE5.7.3V4.zip
https://drive.google.com/file/d/1XhVZgV6FRiyGOOquqO5nJVFXbmg_8DA-/view?usp=sharing

furcraeaHLSLEditor_UE5.7.3V3.zip
https://drive.google.com/file/d/1Qmz5Y_uT0VGKkrk1wskvw2DRbnND6or4/view?
usp=drive_link

furcraeaHLSLEditor_UE5.7.3V2.zip
https://drive.google.com/file/d/1CSXmSebk7hLM02qM5jKDv2ndNJ4jhUi7/view?usp=sharing

1,Pluginsフォルダにzipを解凍して入れてください。

  パスの例:UEプロジェクトフォルダ\Plugins\furcraeaHLSLEditor\Shaders

2,プラグインで「furcraeaHLSLEditor」を有効化

使用方法

コンテンツブラウザで右クリック>Miscellaneous>Code Material Assetを作成

できた New Code Material AssetをダブルクリックでHLSL編集画面が開く

Saveをクリックすると。。。GeneratedフォルダーにM_NewCodeMaterialAssetが作成されます。


まだまだ、1つしかCodeMatUser.ushがないので一つしかマテリアルが成立しないなどの不備があるので更新していく予定です。<-以下の画像のように修正済みです。

furcraeaHLSLEditorをGitHub で公開しました。
https://github.com/nobolu-ootsuka-unrealengine/furcraeaHLSLEditor/commits?author=nobolu-ootsuka-unrealengine

修正履歴



1つしかCodeMatUser.ushがないので一つしかマテリアルが成立しないなどの不備を修正

furcraeaHLSLEditor_UE5.7.3V2

Projects と RenderCore を bBuildEditorをガード外に移動(ランタイムでも必要なモジュールのため)


furcraeaHLSLEditor_UE5.7.3V3

CodeMaterialAsset が吐くMaterialのフォルダを (固定)Generated から (ユーザーが作った)CodeMaterialAssetと同じフォルダに変更した

CodeMaterialCompiler.cpp に2箇所変更しました。

① MakeMaterialPackagePath 関数(生成先パスを決定)

  • 変更前:/Game/Generated/M_xxx 固定
  • 変更後:Asset->GetOutermost()->GetName() でアセット自身のパッケージパスを取得し、FPackageName::GetLongPackagePath()
    でフォルダ部分を抜き出して {同じフォルダ}/M_xxx を返す ② CreateOrLoadMaterial の MakeDirectory 呼び出し
  • 変更前:MakeDirectory(“/Game/Generated”) 固定
  • 変更後:MakeDirectory(FPackageName::GetLongPackagePath(MakeMaterialPackagePath(Asset))) —
    生成先パスからフォルダを算出して作成 これにより、例えば Content/0_furcraeaTokyo/CodeMaterialAsset/NewCodeMaterialAsset に保存された CodeMaterialAsset
    に対しては、生成マテリアルも同じ Content/0_furcraeaTokyo/CodeMaterialAsset/M_NewCodeMaterialAsset に出力されます。

furcraeaHLSLEditor_UE5.7.3V4

アウトライン表示用のVertexNormalを拡張のために

FragmentShader VertexShader(Optional)に分離しました!

安定性のためにincludeを辞めました。

furcraeaHLSLEditor_UE5.7.4V5.zip
ルール: FragmentShaderCode / VertexShaderCode には 関数定義を書かない。ヘルパーが必要なら全てインライン化する。
コンパイラの整理

  • ExtractHelperFunctions + エスケープトリック (将来の一般的ヘルパー対応) は保持
    // @param float3 ColorC = 0.90,0.20,1.20//でBPでパラメーター化

furcraeaHLSLEditor_UE5.7.4V6.zip
・日本語コメントがあるとVertex Shader側のコードカラーリングが効いてない不具合を修正
・こんどは両ペインで改行が入力できないを解決
・ユーザーが .ush のボディ内で Phase * Time のように Time を直接書いても View.GameTime として展開され、HLSL
コンパイルエラー → クラッシュが防がれます。

Audio Radial Slider のデフォルトvalueの表示が1にならない件

Audio Radial Slider のデフォルトvalueの表示が1にならない件が3日かけてやっと解決した

階層とメソッド一覧

   hierarchy: AudioVolumeRadialSlider
   hierarchy: AudioRadialSlider
   hierarchy: Widget
   hierarchy: Visual
   hierarchy: Object
   UFunction: SetWidgetLayout
   UFunction: SetValueTextReadOnly
   UFunction: SetUnitsTextReadOnly
   UFunction: SetUnitsText
   UFunction: SetTextLabelBackgroundColor
   UFunction: SetSliderThickness
   UFunction: SetSliderProgressColor
   UFunction: SetSliderBarColor
   UFunction: SetShowUnitsText
   UFunction: SetShowLabelOnlyOnHover
   UFunction: SetOutputRange
   UFunction: SetHandStartEndRatio
   UFunction: SetCenterBackgroundColor
   UFunction: GetSliderValue
   UFunction: GetOutputValue
   UFunction: SetVisibility
   UFunction: SetUserFocus
   UFunction: SetToolTipText
   UFunction: SetToolTip
   UFunction: SetRenderTranslation
   UFunction: SetRenderTransformPivot
   UFunction: SetRenderTransformAngle
   UFunction: SetRenderTransform
   UFunction: SetRenderShear
   UFunction: SetRenderScale
   UFunction: SetRenderOpacity
   UFunction: SetNavigationRuleExplicit
   UFunction: SetNavigationRuleCustomBoundary
   UFunction: SetNavigationRuleCustom
   UFunction: SetNavigationRuleBase
   UFunction: SetNavigationRule
   UFunction: SetKeyboardFocus
   UFunction: SetIsEnabled
   UFunction: SetFocus
   UFunction: SetCursor
   UFunction: SetClipping
   UFunction: SetAllNavigationRules
   UFunction: ResetCursor
   UFunction: RemoveFromParent
   UFunction: OnReply__DelegateSignature
   UFunction: OnPointerEvent__DelegateSignature
   UFunction: K2_RemoveFieldValueChangedDelegate
   UFunction: K2_BroadcastFieldValueChanged
   UFunction: K2_AddFieldValueChangedDelegate
   UFunction: IsVisible
   UFunction: IsRendered
   UFunction: IsInViewport
   UFunction: IsHovered
   UFunction: InvalidateLayoutAndVolatility
   UFunction: HasUserFocusedDescendants
   UFunction: HasUserFocus
   UFunction: HasMouseCaptureByUser
   UFunction: HasMouseCapture
   UFunction: HasKeyboardFocus
   UFunction: HasFocusedDescendants
   UFunction: HasAnyUserFocus
   UFunction: GetWidget__DelegateSignature
   UFunction: GetVisibility
   UFunction: GetTickSpaceGeometry
   UFunction: GetText__DelegateSignature
   UFunction: GetSlateVisibility__DelegateSignature
   UFunction: GetSlateColor__DelegateSignature
   UFunction: GetSlateBrush__DelegateSignature
   UFunction: GetRenderTransformAngle
   UFunction: GetRenderOpacity
   UFunction: GetParent
   UFunction: GetPaintSpaceGeometry
   UFunction: GetOwningPlayer
   UFunction: GetOwningLocalPlayer
   UFunction: GetMouseCursor__DelegateSignature
   UFunction: GetLinearColor__DelegateSignature
   UFunction: GetIsEnabled
   UFunction: GetInt32__DelegateSignature
   UFunction: GetGameInstance
   UFunction: GetFloat__DelegateSignature
   UFunction: GetDesiredSize
   UFunction: GetClipping
   UFunction: GetCheckBoxState__DelegateSignature
   UFunction: GetCachedGeometry
   UFunction: GetBool__DelegateSignature
   UFunction: GetAccessibleText
   UFunction: GetAccessibleSummaryText
   UFunction: GenerateWidgetForString__DelegateSignature
   UFunction: GenerateWidgetForObject__DelegateSignature
   UFunction: ForceVolatile
   UFunction: ForceLayoutPrepass
   UFunction: ExecuteUbergraph
   hierarchy: AudioVolumeRadialSlider
   hierarchy: AudioRadialSlider
   hierarchy: Widget
   hierarchy: Visual
   hierarchy: Object
   UFunction: SetWidgetLayout
   UFunction: SetValueTextReadOnly
   UFunction: SetUnitsTextReadOnly
   UFunction: SetUnitsText
   UFunction: SetTextLabelBackgroundColor
   UFunction: SetSliderThickness
   UFunction: SetSliderProgressColor
   UFunction: SetSliderBarColor
   UFunction: SetShowUnitsText
   UFunction: SetShowLabelOnlyOnHover
   UFunction: SetOutputRange
   UFunction: SetHandStartEndRatio
   UFunction: SetCenterBackgroundColor
   UFunction: GetSliderValue
   UFunction: GetOutputValue
   UFunction: SetVisibility
   UFunction: SetUserFocus
   UFunction: SetToolTipText
   UFunction: SetToolTip
   UFunction: SetRenderTranslation
   UFunction: SetRenderTransformPivot
   UFunction: SetRenderTransformAngle
   UFunction: SetRenderTransform
   UFunction: SetRenderShear
   UFunction: SetRenderScale
   UFunction: SetRenderOpacity
   UFunction: SetNavigationRuleExplicit
   UFunction: SetNavigationRuleCustomBoundary
   UFunction: SetNavigationRuleCustom
   UFunction: SetNavigationRuleBase
   UFunction: SetNavigationRule
   UFunction: SetKeyboardFocus
   UFunction: SetIsEnabled
   UFunction: SetFocus
   UFunction: SetCursor
   UFunction: SetClipping
   UFunction: SetAllNavigationRules
   UFunction: ResetCursor
   UFunction: RemoveFromParent
   UFunction: OnReply__DelegateSignature
   UFunction: OnPointerEvent__DelegateSignature
   UFunction: K2_RemoveFieldValueChangedDelegate
   UFunction: K2_BroadcastFieldValueChanged
   UFunction: K2_AddFieldValueChangedDelegate
   UFunction: IsVisible
   UFunction: IsRendered
   UFunction: IsInViewport
   UFunction: IsHovered
   UFunction: InvalidateLayoutAndVolatility
   UFunction: HasUserFocusedDescendants
   UFunction: HasUserFocus
   UFunction: HasMouseCaptureByUser
   UFunction: HasMouseCapture
   UFunction: HasKeyboardFocus
   UFunction: HasFocusedDescendants
   UFunction: HasAnyUserFocus
   UFunction: GetWidget__DelegateSignature
   UFunction: GetVisibility
   UFunction: GetTickSpaceGeometry
   UFunction: GetText__DelegateSignature
   UFunction: GetSlateVisibility__DelegateSignature
   UFunction: GetSlateColor__DelegateSignature
   UFunction: GetSlateBrush__DelegateSignature
   UFunction: GetRenderTransformAngle
   UFunction: GetRenderOpacity
   UFunction: GetParent
   UFunction: GetPaintSpaceGeometry
   UFunction: GetOwningPlayer
   UFunction: GetOwningLocalPlayer
   UFunction: GetMouseCursor__DelegateSignature
   UFunction: GetLinearColor__DelegateSignature
   UFunction: GetIsEnabled
   UFunction: GetInt32__DelegateSignature
   UFunction: GetGameInstance
   UFunction: GetFloat__DelegateSignature
   UFunction: GetDesiredSize
   UFunction: GetClipping
   UFunction: GetCheckBoxState__DelegateSignature
   UFunction: GetCachedGeometry
   UFunction: GetBool__DelegateSignature
   UFunction: GetAccessibleText
   UFunction: GetAccessibleSummaryText
   UFunction: GenerateWidgetForString__DelegateSignature
   UFunction: GenerateWidgetForObject__DelegateSignature
   UFunction: ForceVolatile
   UFunction: ForceLayoutPrepass
   UFunction: ExecuteUbergraph

● AudioRadialSlider という独自クラスです。ソースを探します:

● わかりました。ではビルド・実行後のOutput Logで Cast OK が出ているか確認してください。それだけ教えてください。

LogTemp: Warning: AudioUI: Cast OK [AudioVolume_Master] before=1.000000
LogTemp: Warning: AudioUI: after=1.000000
LogTemp: Warning: AudioUI: Cast OK [AudioVolume_se] before=1.000000
LogTemp: Warning: AudioUI: after=1.000000
LogViewport: Display: Player bShowMouseCursor Changed, False -> True
PIE: Server logged in
PIE: Play in editor total start time 0.113 seconds.
LogTemp: Warning: AudioUI: Cast OK [AudioVolume_Master] before=1.000000
LogTemp: Warning: AudioUI: after=1.000000
LogTemp: Warning: AudioUI: Cast OK [AudioVolume_se] before=1.000000
LogTemp: Warning: AudioUI: after=1.000000

● before=1.0 — 値はすでに1.0になっています。 でも表示が違う?

これは表示テキスト(ラベル)の問題です。UAudioRadialSlider は Value(0〜1 正規化)を OutputRange
に変換して表示します。OutputRange の設定次第で表示が変わります。

● Searched for 1 pattern, read 1 file (ctrl+o to expand)

● SynchronizeProperties は Value を Slate に送っていません。RebuildWidget を確認します:

● Searched for 1 pattern (ctrl+o to expand)

● 原因判明。SynchronizeProperties が Value を Slate に送っていません。GetCachedWidget() で Slate
ウィジェットを取得して直接 SetValue します:

● Searched for 4 patterns, read 1 file (ctrl+o to expand)

● SAudioRadialSlider::SetSliderValue() を使います。Slate ウィジェットに直接セットします:

● Write(D:\Sandbox\UE573petit25Cl\UE573petit25Cl\Source\UE573petit25Cl\AudioUI.h)

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "AudioUI.generated.h"

/**
 *  Base class for Audio settings UI.
 *  Initializes AudioVolumeRadialSlider defaults and routes value changes to AudioManager.
 */
UCLASS(abstract)
class UE573PETIT25CL_API UAudioUI : public UUserWidget
{
	GENERATED_BODY()

protected:

	virtual void NativePreConstruct() override;
	virtual void NativeConstruct() override;

public:

	UFUNCTION()
	void InitSliderDefaults();

private:

	UFUNCTION()
	void OnMasterVolumeChanged(float Value);

	UFUNCTION()
	void OnSEVolumeChanged(float Value);
};

● Write(D:\Sandbox\UE573petit25Cl\UE573petit25Cl\Source\UE573petit25Cl\AudioUI.cpp)

// Copyright Epic Games, Inc. All Rights Reserved.

#include "AudioUI.h"
#include "AudioManager.h"
#include "AudioRadialSlider.h"
#include "SAudioRadialSlider.h"
#include "Blueprint/WidgetTree.h"
#include "TimerManager.h"
#include "Engine/World.h"

void UAudioUI::NativePreConstruct()
{
	Super::NativePreConstruct();
	InitSliderDefaults();
}

void UAudioUI::NativeConstruct()
{
	Super::NativeConstruct();

	// Bind slider delegates
	if (UAudioRadialSlider* Master = Cast<UAudioRadialSlider>(GetWidgetFromName(TEXT("AudioVolume_Master"))))
	{
		Master->OnValueChanged.AddDynamic(this, &UAudioUI::OnMasterVolumeChanged);
	}

	if (UAudioRadialSlider* SE = Cast<UAudioRadialSlider>(GetWidgetFromName(TEXT("AudioVolume_se"))))
	{
		SE->OnValueChanged.AddDynamic(this, &UAudioUI::OnSEVolumeChanged);
	}

	if (UWorld* World = GetWorld())
	{
		FTimerHandle Handle;
		World->GetTimerManager().SetTimerForNextTick(this, &UAudioUI::InitSliderDefaults);
	}
}

void UAudioUI::InitSliderDefaults()
{
	if (!WidgetTree) return;

	WidgetTree->ForEachWidget([](UWidget* Widget)
	{
		if (UAudioRadialSlider* Slider = Cast<UAudioRadialSlider>(Widget))
		{
			Slider->Value = 1.0f;

			TSharedPtr<SWidget> CachedWidget = Slider->GetCachedWidget();
			if (CachedWidget.IsValid())
			{
				StaticCastSharedPtr<SAudioRadialSlider>(CachedWidget)->SetSliderValue(1.0f);
			}
		}
	});
}

void UAudioUI::OnMasterVolumeChanged(float Value)
{
	if (UAudioManager* AM = GetGameInstance()->GetSubsystem<UAudioManager>())
	{
		AM->SetMasterVolume(Value);
	}
}

void UAudioUI::OnSEVolumeChanged(float Value)
{
	if (UAudioManager* AM = GetGameInstance()->GetSubsystem<UAudioManager>())
	{
		AM->SetSEVolume(Value);
	}
}

● ビルドして確認してください。

● よかったです!長い道のりでしたね。

原因のまとめ:

  • AudioVolumeRadialSlider は URadialSlider ではなく AudioWidgets プラグインの UAudioVolumeRadialSlider
  • SynchronizeProperties() が Value を Slate に送らない(プラグインの仕様)
  • Slate ウィジェット (SAudioRadialSlider) に直接 SetSliderValue() を呼ぶ必要があった

● お疲れ様でした!

今回の実装まとめ:

  • AudioVolume_Master → AudioManager::SetMasterVolume()
  • AudioVolume_se → AudioManager::SetSEVolume()
  • 初期値は両方 1.0(SAudioRadialSlider::SetSliderValue で Slate に直接セット)

おまけ

AudioManager.h

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "AudioManager.generated.h"

class USoundBase;
class UAudioComponent;

/**
 *  Game-wide audio manager — BGM playlist + volume control.
 *
 *  Access from anywhere:
 *    UGameInstance* GI = GetGameInstance();          // or GetWorld()->GetGameInstance()
 *    UAudioManager* AM = GI->GetSubsystem<UAudioManager>();
 *
 *  BGM asset note:
 *    USoundBase assets used as BGM tracks must have looping DISABLED so that
 *    OnAudioFinished fires when the track ends and the playlist advances.
 */
UCLASS()
class UE573PETIT25CL_API UAudioManager : public UGameInstanceSubsystem
{
	GENERATED_BODY()

public:

	// -------------------------------------------------------
	// Playlist
	// -------------------------------------------------------

	/** BGM tracks to play in order (or randomly when bRandomPlayback is true) */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BGM")
	TArray<TObjectPtr<USoundBase>> BGMPlaylist;

	/**
	 *  If true, tracks are played in a random order.
	 *  A full cycle (every track plays once) is guaranteed before any track repeats.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BGM")
	bool bRandomPlayback = false;

	// -------------------------------------------------------
	// Volume  (0.0 – 1.0)
	// -------------------------------------------------------

	/** Overall volume multiplier applied to all audio */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Volume", meta=(ClampMin=0, ClampMax=1))
	float MasterVolume = 1.0f;

	/** Volume multiplier applied to BGM on top of MasterVolume */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Volume", meta=(ClampMin=0, ClampMax=1))
	float BGMVolume = 1.0f;

	/** Volume multiplier applied to SE on top of MasterVolume */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Volume", meta=(ClampMin=0, ClampMax=1))
	float SEVolume = 1.0f;

public:

	// -------------------------------------------------------
	// BGM API
	// -------------------------------------------------------

	/**
	 *  Starts BGM playlist playback.
	 *  @param TrackIndex  0-based index of the first track to play.
	 *                     Ignored in random mode — a fresh shuffle is always started.
	 */
	UFUNCTION(BlueprintCallable, Category="Audio|BGM")
	void PlayBGM(int32 TrackIndex = 0);

	/** Stops BGM playback and destroys the internal audio component */
	UFUNCTION(BlueprintCallable, Category="Audio|BGM")
	void StopBGM();

	/** Pauses BGM playback */
	UFUNCTION(BlueprintCallable, Category="Audio|BGM")
	void PauseBGM();

	/** Resumes a paused BGM */
	UFUNCTION(BlueprintCallable, Category="Audio|BGM")
	void ResumeBGM();

	/** Skips to the next track immediately */
	UFUNCTION(BlueprintCallable, Category="Audio|BGM")
	void SkipTrack();

	// -------------------------------------------------------
	// Volume API
	// -------------------------------------------------------

	/** Sets the master volume and immediately applies it to the playing BGM */
	UFUNCTION(BlueprintCallable, Category="Audio|Volume")
	void SetMasterVolume(float Volume);

	/** Sets the BGM volume and immediately applies it to the playing BGM */
	UFUNCTION(BlueprintCallable, Category="Audio|Volume")
	void SetBGMVolume(float Volume);

	/** Sets the SE volume (applied to subsequent PlaySE calls) */
	UFUNCTION(BlueprintCallable, Category="Audio|Volume")
	void SetSEVolume(float Volume);

	// -------------------------------------------------------
	// SE API
	// -------------------------------------------------------

	/** Plays a non-spatialized sound effect at MasterVolume * SEVolume */
	UFUNCTION(BlueprintCallable, Category="Audio|SE")
	void PlaySE2D(USoundBase* Sound);

	/** Plays a spatialized sound effect at the given world location at MasterVolume * SEVolume */
	UFUNCTION(BlueprintCallable, Category="Audio|SE", meta=(WorldContext="WorldContextObject"))
	void PlaySE3D(USoundBase* Sound, const FVector& Location, UObject* WorldContextObject);

private:

	/** Currently active BGM audio component */
	UPROPERTY()
	TObjectPtr<UAudioComponent> BGMComponent;

	/** Index of the track that is currently playing */
	int32 CurrentTrackIndex = 0;

	/** Remaining track indices for random mode; rebuilt when the list is exhausted */
	TArray<int32> ShuffledIndices;

	/** Plays the track at the given playlist index */
	void PlayTrackAtIndex(int32 Index);

	/** Called when the current BGM track finishes — advances to the next track */
	UFUNCTION()
	void OnBGMFinished();

	/** Returns the index of the next track to play */
	int32 PickNextTrackIndex();

	/** Applies the current MasterVolume * BGMVolume to the active audio component */
	void RefreshBGMVolume();

	/** Fills ShuffledIndices with a fresh Fisher-Yates permutation of all track indices */
	void RebuildShuffledIndices();
};

AudioManager.cpp

// Copyright Epic Games, Inc. All Rights Reserved.

#include "AudioManager.h"
#include "Components/AudioComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Sound/SoundBase.h"

// -------------------------------------------------------
// BGM API
// -------------------------------------------------------

void UAudioManager::PlayBGM(int32 TrackIndex)
{
	if (BGMPlaylist.IsEmpty())
	{
		return;
	}

	// Stop any currently playing track before starting the playlist
	StopBGM();

	if (bRandomPlayback)
	{
		// Start a fresh shuffle so every track plays before any repeats
		RebuildShuffledIndices();
		PlayTrackAtIndex(ShuffledIndices.Pop(EAllowShrinking::No));
	}
	else
	{
		PlayTrackAtIndex(FMath::Clamp(TrackIndex, 0, BGMPlaylist.Num() - 1));
	}
}

void UAudioManager::StopBGM()
{
	if (BGMComponent)
	{
		// Remove delegate first so Stop() does not accidentally trigger OnBGMFinished
		BGMComponent->OnAudioFinished.RemoveDynamic(this, &UAudioManager::OnBGMFinished);
		BGMComponent->Stop();
		BGMComponent->DestroyComponent();
		BGMComponent = nullptr;
	}
}

void UAudioManager::PauseBGM()
{
	if (BGMComponent)
	{
		BGMComponent->SetPaused(true);
	}
}

void UAudioManager::ResumeBGM()
{
	if (BGMComponent)
	{
		BGMComponent->SetPaused(false);
	}
}

void UAudioManager::SkipTrack()
{
	if (BGMPlaylist.IsEmpty())
	{
		return;
	}

	PlayTrackAtIndex(PickNextTrackIndex());
}

// -------------------------------------------------------
// Volume API
// -------------------------------------------------------

void UAudioManager::SetMasterVolume(float Volume)
{
	MasterVolume = FMath::Clamp(Volume, 0.0f, 1.0f);
	RefreshBGMVolume();
}

void UAudioManager::SetBGMVolume(float Volume)
{
	BGMVolume = FMath::Clamp(Volume, 0.0f, 1.0f);
	RefreshBGMVolume();
}

void UAudioManager::SetSEVolume(float Volume)
{
	SEVolume = FMath::Clamp(Volume, 0.0f, 1.0f);
}

// -------------------------------------------------------
// SE API
// -------------------------------------------------------

void UAudioManager::PlaySE2D(USoundBase* Sound)
{
	if (!Sound)
	{
		return;
	}

	UGameplayStatics::SpawnSound2D(GetGameInstance(), Sound, MasterVolume * SEVolume);
}

void UAudioManager::PlaySE3D(USoundBase* Sound, const FVector& Location, UObject* WorldContextObject)
{
	if (!Sound || !WorldContextObject)
	{
		return;
	}

	UGameplayStatics::SpawnSoundAtLocation(WorldContextObject, Sound, Location,
		FRotator::ZeroRotator, MasterVolume * SEVolume);
}

// -------------------------------------------------------
// Private helpers
// -------------------------------------------------------

void UAudioManager::PlayTrackAtIndex(int32 Index)
{
	if (!BGMPlaylist.IsValidIndex(Index) || !BGMPlaylist[Index])
	{
		return;
	}

	CurrentTrackIndex = Index;

	// Tear down previous component and unsubscribe before spawning a new one
	if (BGMComponent)
	{
		BGMComponent->OnAudioFinished.RemoveDynamic(this, &UAudioManager::OnBGMFinished);
		BGMComponent->Stop();
		BGMComponent->DestroyComponent();
		BGMComponent = nullptr;
	}

	// Spawn a 2D audio component:
	//   bPersistAcrossLevelTransition = true  — BGM survives level loads
	//   bAutoDestroy                  = false — we control the lifetime manually
	BGMComponent = UGameplayStatics::SpawnSound2D(
		GetGameInstance(),
		BGMPlaylist[Index],
		MasterVolume * BGMVolume,
		1.0f,   // PitchMultiplier
		0.0f,   // StartTime
		nullptr,// ConcurrencySettings
		true,   // bPersistAcrossLevelTransition
		false   // bAutoDestroy
	);

	if (BGMComponent)
	{
		BGMComponent->OnAudioFinished.AddDynamic(this, &UAudioManager::OnBGMFinished);
	}
}

void UAudioManager::OnBGMFinished()
{
	if (BGMPlaylist.IsEmpty())
	{
		return;
	}

	PlayTrackAtIndex(PickNextTrackIndex());
}

int32 UAudioManager::PickNextTrackIndex()
{
	if (bRandomPlayback)
	{
		// Rebuild the shuffle pool when every track has been played once
		if (ShuffledIndices.IsEmpty())
		{
			RebuildShuffledIndices();
		}
		return ShuffledIndices.Pop(EAllowShrinking::No);
	}

	// Sequential: wrap around to the beginning after the last track
	return (CurrentTrackIndex + 1) % BGMPlaylist.Num();
}

void UAudioManager::RefreshBGMVolume()
{
	if (BGMComponent)
	{
		BGMComponent->SetVolumeMultiplier(MasterVolume * BGMVolume);
	}
}

void UAudioManager::RebuildShuffledIndices()
{
	const int32 Count = BGMPlaylist.Num();
	ShuffledIndices.Reset(Count);

	for (int32 i = 0; i < Count; ++i)
	{
		ShuffledIndices.Add(i);
	}

	// Fisher-Yates shuffle
	for (int32 i = Count - 1; i > 0; --i)
	{
		const int32 j = FMath::RandRange(0, i);
		ShuffledIndices.Swap(i, j);
	}
}

[maya][skinweight]キャラクターの背丈やスケール、回転等を変更する方法

0.前提として同階層にrootとmeshがスキンバインドされて並んでいる状態
root
mesh

1.rootを複製してとっておく
もとのrootとmeshの名前をroot_oldとmesh_oldにする

2.root_oldのジョイントを使ってメッシュの背丈を変更する。
3.変更されたmesh_oldを複製しmeshとする

4.meshをフリーズする

5.上記で変更されたmeshにあわせてrootの背丈を変更してフリーズする

5.rootとmeshスキンバインドする
6.mesh_oldからmeshへスキンウェイトをコピーする。
7.rootとmesh選択してFBX出力
おしまい。

このキャラクターのディティールはこっち

[UE5][C++] The following modules are missing or built with a different engine version: プラグイン名 Would you like to rebuild them now?

出る時の必殺リセット(確実)

UE を閉じてからプロジェクト直下で削除:

Binaries/

Intermediate/

(あれば)Plugins/furcraeaHLSLEditor/Binaries/

(あれば)Plugins/furcraeaHLSLEditor/Intermediate/

その後

.uproject 右クリック → Generate Visual Studio project files

VS で Development Editor / Win64 で Rebuild

起動

[UE5][C++]正しい作業場所まとめ

正しい作業場所まとめ(重要)

作業内容やる場所
フォルダ作成 / リネームエクスプローラー
.uplugin / Build.cs 編集VS(テキスト)
.h / .cpp 追加エクスプローラーで追加後、フォルダ削除※
Generate Project Files
Generate Project Filesエクスプローラー(.uproject右クリック)
ビルドVS
アセット作成 / 動作確認UEエディタ

Runtime に追加とかはUEがわでやるの?VSでやるの?

結論:エクスプローラーでやる。VSではやらない。
これは断言できる。


[UE5.7][C++]unrealengine5 C++プロジェクト VisualStudio いらないファイル消す Zipしたい時

これだけにする

プロジェクトフォルダ直下にある以下のフォルダを削除してください。

  • .vs: Visual Studio のキャッシュやユーザー設定が保存されている隠しフォルダ。
  • Binaries: コンパイルされた実行ファイルやライブラリが保存されるフォルダ。
  • Intermediate: ビルドプロセス中の中間ファイルが保存されるフォルダ。
  • Saved: セーブデータ、スクリーンショット、ログ、クラッシュレポートなどが保存されるフォルダ。
  • DerivedDataCache (DDC): エディタがアセットを処理したキャッシュデータが保存されるフォルダ。容量が非常に大きくなることがあります。 

注意点:

  • Content フォルダと .uproject ファイル、Source フォルダ (C++プロジェクトの場合) は絶対に削除しないでください。これらがプロジェクトの本体です。
  • これらのフォルダを削除した後、プロジェクトを開く前にVisual Studioのソリューションをクリーンアップし、必要に応じてソリューションを再生成.uproject ファイルを右クリックし Generate Visual Studio project files を選択)すると、より確実です。
  • その後、残った必要なファイル(ContentSource.uproject.slnConfig など)をZIP圧縮します。

[UE5.7][C++]自宅AI(Ollama)サーバーをUE5のC++プラグインで連携したよ


まず全体全体(おすすめ)

A.別途REST(非ストリーミング)で完了させる

  • UE → AIサーバへHTTP POST
  • AI → 問題JSON
  • UE → UIに反映(UMG)

メリット:実装が簡単/デバッグしやすいプレイ
:とにかくが長いと立つが出る


自宅AI側:エンドポイントの考え方

あなたが今 OpenWebUI を使っているなら、内部のモデル実体はおそらくOllama

  • Ollamaの代表的なAPI(例)
    • 生成:POST /api/generate
    • チャット:POST /api/chat

UEからは「どのURLに投げるか」だけ差し替えできるようにしておくのが正解。


UE5プラグイン設計(ほぼこれを入れる)

1) 設定(プロジェクトの設定を出す)

  • ベースURL(例:http://192.168.1.23:11434
  • モデル名(例:llama3.1
  • タイムアウト秒
  • オプション: API Key(OpenAI互換を使う場合)

UDeveloperSettingsを使うと綺麗。


実装:UE5 C++(RESTで会話させる最小セット)

(1) ビルド.cs

  • "HTTP"、、"Json""JsonUtilities"追加

(2) 送信受信用の構造体(JSON)

  • リクエスト: モデル / プロンプト(またはメッセージ)
  • 応答: 応答(または選択肢)

(3) ブループリント非同期ノード化(UIに優しい)

  • UBlueprintAsyncActionBase
    • OnSuccess
    • OnError
      を吐く

作った全コード

furcraHomeAIServerChat2.Build.cs

// Some copyright should be here...

using UnrealBuildTool;

public class furcraHomeAIServerChat2 : ModuleRules
{
	public furcraHomeAIServerChat2(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
		
		PublicIncludePaths.AddRange(
			new string[] {
				// ... add public include paths required here ...
			}
			);
			
		
		PrivateIncludePaths.AddRange(
			new string[] {
				// ... add other private include paths required here ...
			}
			);
			
		
		PublicDependencyModuleNames.AddRange(
			new string[]
			{
                "Core", "CoreUObject", "Engine", "UMG","HTTP", "Json", "JsonUtilities"
				// ... add other public dependencies that you statically link with here ...
			}
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"CoreUObject",
				"Engine",
				"Slate",
				"SlateCore",
				"DeveloperSettings",
				// ... add private dependencies that you statically link with here ...	
			}
			);
		
		
		DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);
	}
}

AiChatTypes.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

/**
 * 
 */
class FURCRAHOMEAISERVERCHAT2_API AiChatTypes
{
public:
	AiChatTypes();
	~AiChatTypes();
};





#include "AiChatTypes.generated.h"

USTRUCT(BlueprintType)
struct FAiChatMessage
{
	GENERATED_BODY()

	// "system" | "user" | "assistant"
	UPROPERTY(BlueprintReadWrite, EditAnywhere) FString role;
	UPROPERTY(BlueprintReadWrite, EditAnywhere) FString content;
};

USTRUCT()
struct FOllamaChatRequest
{
	GENERATED_BODY()

	UPROPERTY() FString model;
	UPROPERTY() TArray<FAiChatMessage> messages;
	UPROPERTY() bool stream = false;
};

USTRUCT()
struct FOllamaChatMessage
{
	GENERATED_BODY()

	UPROPERTY() FString role;
	UPROPERTY() FString content;
};

USTRUCT()
struct FOllamaChatResponse
{
	GENERATED_BODY()

	UPROPERTY() FOllamaChatMessage message;
	UPROPERTY() bool done = false;
};

AiChatTypes.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "AiChatTypes.h"

AiChatTypes::AiChatTypes()
{
}

AiChatTypes::~AiChatTypes()
{
}



AiLinkAsyncChat.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "AiChatTypes.h"
#include "AiLinkAsyncChat.generated.h"

// Forward declarations for HTTP interfaces to avoid including HTTP headers in this public header
class IHttpRequest;
class IHttpResponse;

using FHttpRequestPtr = TSharedPtr<IHttpRequest, ESPMode::ThreadSafe>;
using FHttpResponsePtr = TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAiChatSuccess, const FString&, AssistantText);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAiChatError, const FString&, Error);

UCLASS()
class FURCRAHOMEAISERVERCHAT2_API UAiLinkAsyncChat : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	UPROPERTY(BlueprintAssignable) FAiChatSuccess OnSuccess;
	UPROPERTY(BlueprintAssignable) FAiChatError OnError;

	// Messagesは「system + 履歴 + 今回のuser」を含めて渡す
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
	static UAiLinkAsyncChat* SendChat(const TArray<FAiChatMessage>& Messages);

	virtual void Activate() override;

private:
	TArray<FAiChatMessage> MessagesInternal;
	void HandleResponse(FHttpRequestPtr Req, FHttpResponsePtr Resp, bool bOk);
};

AiLinkAsyncChat.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "AiLinkAsyncChat.h"

#include "UAiLinkSettings.h"
#include "HttpModule.h"
#include "Interfaces/IHttpRequest.h"
#include "Interfaces/IHttpResponse.h"
#include "JsonObjectConverter.h"

UAiLinkAsyncChat* UAiLinkAsyncChat::SendChat(const TArray<FAiChatMessage>& Messages)
{
	auto* Node = NewObject<UAiLinkAsyncChat>();
	Node->MessagesInternal = Messages;
	return Node;
}

void UAiLinkAsyncChat::Activate()
{
	const UAiLinkSettings* S = GetDefault<UAiLinkSettings>();
	if (!S)
	{
		OnError.Broadcast(TEXT("Settings not found"));
		return;
	}

	const FString Url = S->BaseUrl / TEXT("api/chat");

	FOllamaChatRequest Body;
	Body.model = S->Model;
	Body.messages = MessagesInternal;
	Body.stream = false;

	FString JsonStr;
	if (!FJsonObjectConverter::UStructToJsonObjectString(Body, JsonStr))
	{
		OnError.Broadcast(TEXT("Failed to serialize request JSON"));
		return;
	}

	TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Req = FHttpModule::Get().CreateRequest();
	Req->SetURL(Url);
	Req->SetVerb(TEXT("POST"));
	Req->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
	Req->SetTimeout(S->TimeoutSeconds);
	Req->SetContentAsString(JsonStr);

	Req->OnProcessRequestComplete().BindUObject(this, &UAiLinkAsyncChat::HandleResponse);
	Req->ProcessRequest();

	UE_LOG(LogTemp, Warning, TEXT("[AI] Activate() called"));
	UE_LOG(LogTemp, Warning, TEXT("[AI] URL: %s"), *Req->GetURL());
	UE_LOG(LogTemp, Warning, TEXT("[AI] Payload: %s"), *JsonStr);
}

void UAiLinkAsyncChat::HandleResponse(FHttpRequestPtr Req, FHttpResponsePtr Resp, bool bOk)
{
	if (!bOk || !Resp.IsValid())
	{
		OnError.Broadcast(TEXT("HTTP request failed (no response)"));
		return;
	}

	const int32 Code = Resp->GetResponseCode();
	const FString Content = Resp->GetContentAsString();
	UE_LOG(LogTemp, Warning, TEXT("[AI] HTTP %d"), Code);
	UE_LOG(LogTemp, Warning, TEXT("[AI] Body: %s"), *Content);

	UE_LOG(LogTemp, Warning, TEXT("[AI] HandleResponse() called. bOk=%d RespValid=%d"),
		bOk ? 1 : 0, Resp.IsValid() ? 1 : 0);

	if (Resp.IsValid())
	{
		UE_LOG(LogTemp, Warning, TEXT("[AI] HTTP %d"), Resp->GetResponseCode());
		UE_LOG(LogTemp, Warning, TEXT("[AI] Body: %s"), *Resp->GetContentAsString());
	}



	if (Code < 200 || Code >= 300)
	{
		OnError.Broadcast(FString::Printf(TEXT("HTTP %d: %s"), Code, *Content));
		return;
	}

	FOllamaChatResponse Parsed;
	if (!FJsonObjectConverter::JsonObjectStringToUStruct(Content, &Parsed, 0, 0))
	{
		OnError.Broadcast(FString::Printf(TEXT("Failed to parse JSON: %s"), *Content));
		return;
	}

	UE_LOG(LogTemp, Warning, TEXT("[AI] Broadcasting Success: %s"), *Parsed.message.content);
	OnSuccess.Broadcast(Parsed.message.content);

}

AiLinkAsyncGenerate.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "AiLinkRequestTypes.h"
#include "AiLinkAsyncGenerate.generated.h"

// Forward declarations for HTTP interfaces to avoid including HTTP headers in this public header
class IHttpRequest;
class IHttpResponse;

using FHttpRequestPtr = TSharedPtr<IHttpRequest, ESPMode::ThreadSafe>;
using FHttpResponsePtr = TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAiGenerateSuccess, const FString&, Text);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAiGenerateError, const FString&, Error);

UCLASS()
class FURCRAHOMEAISERVERCHAT2_API UAiLinkAsyncGenerate : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	UPROPERTY(BlueprintAssignable) FAiGenerateSuccess OnSuccess;
	UPROPERTY(BlueprintAssignable) FAiGenerateError OnError;

	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
	static UAiLinkAsyncGenerate* GenerateText(const FString& Prompt);

	virtual void Activate() override;

private:
	FString PromptInternal;
	void HandleResponse(FHttpRequestPtr Req, FHttpResponsePtr Resp, bool bOk);
};

AiLinkAsyncGenerate.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "AiLinkAsyncGenerate.h"

#include "UAiLinkSettings.h"	
#include "HttpModule.h"
#include "Interfaces/IHttpRequest.h"
#include "Interfaces/IHttpResponse.h"
#include "JsonObjectConverter.h"

UAiLinkAsyncGenerate* UAiLinkAsyncGenerate::GenerateText(const FString& Prompt)
{
	auto* Node = NewObject<UAiLinkAsyncGenerate>();
	Node->PromptInternal = Prompt;
	return Node;
}

void UAiLinkAsyncGenerate::Activate()
{
	const UAiLinkSettings* S = GetDefault<UAiLinkSettings>();
	if (!S)
	{
		OnError.Broadcast(TEXT("Settings not found"));
		return;
	}

	const FString Url = S->BaseUrl / TEXT("api/generate");

	FOllamaGenerateRequest Body;
	Body.model = S->Model;
	Body.prompt = PromptInternal;
	Body.stream = false;

	FString JsonStr;
	if (!FJsonObjectConverter::UStructToJsonObjectString(Body, JsonStr))
	{
		OnError.Broadcast(TEXT("Failed to serialize request JSON"));
		return;
	}

	TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Req = FHttpModule::Get().CreateRequest();
	Req->SetURL(Url);
	Req->SetVerb(TEXT("POST"));
	Req->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
	Req->SetTimeout(S->TimeoutSeconds);
	Req->SetContentAsString(JsonStr);

	Req->OnProcessRequestComplete().BindUObject(this, &UAiLinkAsyncGenerate::HandleResponse);
	Req->ProcessRequest();
}

void UAiLinkAsyncGenerate::HandleResponse(FHttpRequestPtr Req, FHttpResponsePtr Resp, bool bOk)
{
	if (!bOk || !Resp.IsValid())
	{
		OnError.Broadcast(TEXT("HTTP request failed (no response)"));
		return;
	}

	const int32 Code = Resp->GetResponseCode();
	const FString Content = Resp->GetContentAsString();

	if (Code < 200 || Code >= 300)
	{
		OnError.Broadcast(FString::Printf(TEXT("HTTP %d: %s"), Code, *Content));
		return;
	}

	FOllamaGenerateResponse Parsed;
	if (!FJsonObjectConverter::JsonObjectStringToUStruct(Content, &Parsed, 0, 0))
	{
		OnError.Broadcast(FString::Printf(TEXT("Failed to parse JSON: %s"), *Content));
		return;
	}

	OnSuccess.Broadcast(Parsed.response);
}

AiLinkRequestTypes.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

/**
 * 
 */
class FURCRAHOMEAISERVERCHAT2_API AiLinkRequestTypes
{
public:
	AiLinkRequestTypes();
	~AiLinkRequestTypes();
};


//#pragma once
//#include "CoreMinimal.h"
#include "AiLinkRequestTypes.generated.h"

USTRUCT()
struct FOllamaGenerateRequest
{
	GENERATED_BODY()

	UPROPERTY() FString model;
	UPROPERTY() FString prompt;
	UPROPERTY() bool stream = false;
};

USTRUCT()
struct FOllamaGenerateResponse
{
	GENERATED_BODY()

	UPROPERTY() FString response;
	UPROPERTY() bool done = false;
};

AiLinkRequestTypes.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "AiLinkRequestTypes.h"

AiLinkRequestTypes::AiLinkRequestTypes()
{
}

AiLinkRequestTypes::~AiLinkRequestTypes()
{
}

UAiLinkSettings.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Engine/DeveloperSettings.h"
#include "UAiLinkSettings.generated.h"

UCLASS(Config = Game, DefaultConfig, meta = (DisplayName = "Home AI Chat"))
class FURCRAHOMEAISERVERCHAT2_API UAiLinkSettings : public UDeveloperSettings
{
	GENERATED_BODY()

public:
	UPROPERTY(Config, EditAnywhere, Category = "AI")
	FString BaseUrl = TEXT("http://192.168.1.23:11434");

	UPROPERTY(Config, EditAnywhere, Category = "AI")
	//FString Model = TEXT("llama3.1"); 
	//FString Model = TEXT("deepseek-r1:32b");llama3.1:8b
	//FString Model = TEXT("llama3.1:70b");//llama3.1:8b
	FString Model = TEXT("llama3.1:8b");//
	UPROPERTY(Config, EditAnywhere, Category = "AI")
	float TimeoutSeconds = 120.0f;

	// 例: "You are NPC assistant in my game..."
	UPROPERTY(Config, EditAnywhere, Category = "AI")
	FString SystemPrompt = TEXT("You are a helpful in-game NPC. Keep replies concise.");
};

UAiLinkSettings.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "UAiLinkSettings.h"

BluePrintはこんなかんじ

以上。