diff --git a/src/Game.Client/Assets/Localization/Tables/String/Common Shared Data.asset b/src/Game.Client/Assets/Localization/Tables/String/Common Shared Data.asset index a2d2ecc2..2e667dd2 100644 --- a/src/Game.Client/Assets/Localization/Tables/String/Common Shared Data.asset +++ b/src/Game.Client/Assets/Localization/Tables/String/Common Shared Data.asset @@ -74,7 +74,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 483635457687552 - m_Key: Input_Controls_Hold + m_Key: Camera_Control_Reverse m_Metadata: m_Items: [] - m_Id: 485408155107328 @@ -213,6 +213,10 @@ MonoBehaviour: m_Key: Sprint_Controls m_Metadata: m_Items: [] + - m_Id: 6465602920128512 + m_Key: Input_Controls_Hold + m_Metadata: + m_Items: [] m_Metadata: m_Items: [] m_KeyGenerator: diff --git a/src/Game.Client/Assets/Localization/Tables/String/Common_en.asset b/src/Game.Client/Assets/Localization/Tables/String/Common_en.asset index 4b13502c..3f4eb4f6 100644 --- a/src/Game.Client/Assets/Localization/Tables/String/Common_en.asset +++ b/src/Game.Client/Assets/Localization/Tables/String/Common_en.asset @@ -75,7 +75,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 483635457687552 - m_Localized: Hold + m_Localized: Reverse m_Metadata: m_Items: [] - m_Id: 485408155107328 @@ -214,6 +214,10 @@ MonoBehaviour: m_Localized: Sprint Controls m_Metadata: m_Items: [] + - m_Id: 6465602920128512 + m_Localized: Hold + m_Metadata: + m_Items: [] references: version: 2 RefIds: [] diff --git a/src/Game.Client/Assets/Localization/Tables/String/Common_ja.asset b/src/Game.Client/Assets/Localization/Tables/String/Common_ja.asset index cbe4eb49..92737658 100644 --- a/src/Game.Client/Assets/Localization/Tables/String/Common_ja.asset +++ b/src/Game.Client/Assets/Localization/Tables/String/Common_ja.asset @@ -75,7 +75,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 483635457687552 - m_Localized: "\u30DB\u30FC\u30EB\u30C9" + m_Localized: "\u30EA\u30D0\u30FC\u30B9" m_Metadata: m_Items: [] - m_Id: 485408155107328 @@ -214,6 +214,10 @@ MonoBehaviour: m_Localized: "\u30B9\u30D7\u30EA\u30F3\u30C8\u64CD\u4F5C" m_Metadata: m_Items: [] + - m_Id: 6465602920128512 + m_Localized: "\u30DB\u30FC\u30EB\u30C9" + m_Metadata: + m_Items: [] references: version: 2 RefIds: [] diff --git a/src/Game.Client/Assets/Localization/Tables/String/InputControls_en.asset b/src/Game.Client/Assets/Localization/Tables/String/InputControls_en.asset index 4c8bc513..5733835b 100644 --- a/src/Game.Client/Assets/Localization/Tables/String/InputControls_en.asset +++ b/src/Game.Client/Assets/Localization/Tables/String/InputControls_en.asset @@ -475,19 +475,19 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 76672933973 - m_Localized: Left Shoulder + m_Localized: LB m_Metadata: m_Items: [] - m_Id: 76672933974 - m_Localized: Right Shoulder + m_Localized: RB m_Metadata: m_Items: [] - m_Id: 76672933975 - m_Localized: Left Trigger + m_Localized: LT m_Metadata: m_Items: [] - m_Id: 76672933976 - m_Localized: Right Trigger + m_Localized: RT m_Metadata: m_Items: [] - m_Id: 76672933977 diff --git a/src/Game.Client/Assets/Localization/Tables/String/InputControls_ja.asset b/src/Game.Client/Assets/Localization/Tables/String/InputControls_ja.asset index 78ca2e11..0b4fc653 100644 --- a/src/Game.Client/Assets/Localization/Tables/String/InputControls_ja.asset +++ b/src/Game.Client/Assets/Localization/Tables/String/InputControls_ja.asset @@ -475,11 +475,11 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 76672933973 - m_Localized: "L\u30DC\u30BF\u30F3" + m_Localized: LB m_Metadata: m_Items: [] - m_Id: 76672933974 - m_Localized: "R\u30DC\u30BF\u30F3" + m_Localized: RB m_Metadata: m_Items: [] - m_Id: 76672933975 diff --git a/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Dialogs/HorrorOptionDialogComponent.cs b/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Dialogs/HorrorOptionDialogComponent.cs index e2be09e2..7e8357c5 100644 --- a/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Dialogs/HorrorOptionDialogComponent.cs +++ b/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Dialogs/HorrorOptionDialogComponent.cs @@ -9,6 +9,8 @@ using Game.Shared.Constants; using Game.Shared.Enums; using Game.Shared.Extensions; +using Game.Shared.Input; +using Game.Shared.Localization; using R3; using UnityEngine; using UnityEngine.InputSystem; @@ -207,26 +209,18 @@ public override UniTask Startup() }) .AddTo(Disposables); - LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged; - Disposables.Add(Disposable.Create(() => LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged)); + LocalizationEvents.OnLocaleChanged + .Subscribe(_ => RefreshBindingDisplays()) + .AddTo(Disposables); // コントローラー接続/切替に追従して family 別表示を更新する - InputSystem.onDeviceChange += OnDeviceChanged; - Disposables.Add(Disposable.Create(() => InputSystem.onDeviceChange -= OnDeviceChanged)); + InputSystemEvents.OnDeviceChanged + .Subscribe(_ => RefreshBindingDisplays()) + .AddTo(Disposables); return base.Startup(); } - private void OnLocaleChanged(Locale locale) - { - RefreshBindingDisplays(); - } - - private void OnDeviceChanged(InputDevice device, InputDeviceChange change) - { - RefreshBindingDisplays(); - } - private void RefreshBindingDisplays() { // ロケール変更でバインド表示名を再ローカライズ diff --git a/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Player/HorrorPlayerController.cs b/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Player/HorrorPlayerController.cs index 9b4afaa5..70dfb5b0 100644 --- a/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Player/HorrorPlayerController.cs +++ b/src/Game.Client/Assets/Programs/Runtime/MVC/Horror/Player/HorrorPlayerController.cs @@ -5,6 +5,7 @@ using Game.Shared.Bootstrap; using Game.Shared.Extensions; using Game.Shared.Input; +using Game.Shared.Interaction; using R3; using UnityEngine; @@ -36,6 +37,10 @@ public class HorrorPlayerController : MonoBehaviour [Header("回転速度(度/秒)")] [SerializeField] private float _lookRotationSpeed = 0.1f; + [Header("インタラクション")] + [Tooltip("インタラクト対象を検出する検出器(同一 Prefab 上にアタッチ)")] + [SerializeField] private InteractionDetector _interactionDetector; + private InputSystemService _inputService; private InputSystemService InputService => _inputService ??= GameServiceManager.Get(); @@ -131,6 +136,17 @@ public void Initialize(HorrorOptionSaveData data) ) .Subscribe(_ => ApplicationEvents.HideCursor()) .AddTo(this); + + // インタラクト実行:現在のターゲットがあればその効果を発火する + Player.Interact.OnPerformedAsObservable() + .Subscribe(_ => + { + if (_interactionDetector != null && _interactionDetector.TryGetActionable(out var interactable)) + { + interactable.Interact(); + } + }) + .AddTo(this); } public void ApplyOptions(HorrorOptionSaveData data) @@ -143,7 +159,7 @@ public void ApplyOptions(HorrorOptionSaveData data) _lookAcceleration = data.CameraAcceleration; _cameraShake = data.CameraShake; - _mainCamera.fieldOfView = data.CameraFov; + if (_mainCamera != null) _mainCamera.fieldOfView = data.CameraFov; // OnSaved でランタイム再適用される。カメラ基準位置は触らない(しゃがみ中のリセット防止) _sprintToggle = data.SprintToggle; diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Input/InputSystemEvents.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Input/InputSystemEvents.cs new file mode 100644 index 00000000..239f1ea6 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Input/InputSystemEvents.cs @@ -0,0 +1,15 @@ +using System; +using R3; +using UnityEngine.InputSystem; + +namespace Game.Shared.Input +{ + public static class InputSystemEvents + { + public static Observable<(InputDevice device, InputDeviceChange deviceChange)> OnDeviceChanged + => Observable.FromEvent, (InputDevice, InputDeviceChange)>( + h => (a, b) => h((a, b)), + h => InputSystem.onDeviceChange += h, + h => InputSystem.onDeviceChange -= h); + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Input/InputSystemEvents.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Input/InputSystemEvents.cs.meta new file mode 100644 index 00000000..96c8583a --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Input/InputSystemEvents.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aead81d541094d80926354a7e745658c +timeCreated: 1781751786 \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction.meta new file mode 100644 index 00000000..e6efa31b --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 436f82b9ac90e6f4f839a834e889b5a0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/DebugInteractable.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/DebugInteractable.cs new file mode 100644 index 00000000..e2b7ce12 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/DebugInteractable.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace Game.Shared.Interaction +{ + /// + /// インタラクト時に Debug.Log を出すだけの最小 実装(検証・サンプル用)。 + /// の OverlapSphere に検出されるため Collider が必要。 + /// 視覚表現はアウトライン()と + /// 対象側プロンプト()へ委譲する。 + /// + public class DebugInteractable : MonoBehaviour, IInteractable + { + [Tooltip("ログに出す識別ラベル")] + [SerializeField] private string _label = "Object"; + + [Tooltip("中心位置の上書き。未指定なら自身の transform.position を使う")] + [SerializeField] private Transform _centerOverride; + + [Tooltip("アウトライン表現を担うコンポーネント")] + [SerializeField] private InteractionOutlineHighlighter _highlighter; + + [Tooltip("対象位置に出すプロンプト表示")] + [SerializeField] private InteractionPromptView _promptView; + + public Vector3 CenterPosition => + _centerOverride != null ? _centerOverride.position : transform.position; + + public void Interact() + { + Debug.Log($"[Interact] {_label}"); + } + + public void SetInteractionState(InteractionState state, Camera viewCamera) + { + // アウトラインは実行可能時のみ点灯(「可能」を強調。発見可能はプロンプトのみで差別化する) + if (_highlighter != null) + _highlighter.SetHighlighted(state == InteractionState.Actionable); + + if (_promptView != null) + _promptView.SetState(state, viewCamera); + } + + // 無効化・破棄時に提示を確実に消す(検出器の Hidden 通知が届かないケースの保険) + private void OnDisable() + { + if (_promptView != null) + _promptView.SetState(InteractionState.Hidden, null); + } + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/DebugInteractable.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/DebugInteractable.cs.meta new file mode 100644 index 00000000..2b349fab --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/DebugInteractable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b200b3ffde9a6684b9fb58ab9ca1d347 \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/IInteractable.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/IInteractable.cs new file mode 100644 index 00000000..a9289c7f --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/IInteractable.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +namespace Game.Shared.Interaction +{ + /// + /// インタラクト可能なオブジェクトのインターフェース。 + /// 検出基準点()・実行()・ + /// 提示状態の反映()を提供する。 + /// + public interface IInteractable + { + /// + /// 検出の基準となる中心位置。プレイヤーからの距離計算と可視判定(視線の的)に使用する。 + /// + Vector3 CenterPosition { get; } + + /// + /// インタラクトアクション実行時の効果。 + /// + void Interact(); + + /// + /// 提示状態を反映する。対象側がアウトラインやプロンプト表示を切り替える。 + /// は対象側プロンプトがビルボードで正対するための視点カメラ + /// (検出器が保持する唯一の視点。 時は未使用で null 可)。 + /// + void SetInteractionState(InteractionState state, Camera viewCamera); + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/IInteractable.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/IInteractable.cs.meta new file mode 100644 index 00000000..e42a7a62 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/IInteractable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 91542f3b94872d34e8735b46267115a8 \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionDetector.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionDetector.cs new file mode 100644 index 00000000..c6c76bcf --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionDetector.cs @@ -0,0 +1,409 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Game.Shared.Interaction +{ + /// + /// プレイヤー周囲のインタラクト対象を検出し、各対象の提示状態を駆動する検出器。 + /// 検出範囲()内・カメラ視界内・非遮蔽の対象を「発見可能(Discoverable)」とし、 + /// そのうちインタラクト距離()内で画面中心に最も近い 1 つだけを「実行可能(Actionable)」とする。 + /// 距離判定はプレイヤー位置、視界・遮蔽判定はカメラを基準にする(一人称で視点が頭前方にあるため)。 + /// + public class InteractionDetector : MonoBehaviour + { + [Tooltip("視界・遮蔽判定とビルボード視点の基準カメラ")] + [SerializeField] private Camera _camera; + + [Tooltip("発見可能とみなす最大距離(m, プレイヤー基準)")] + [SerializeField] private float _discoverRadius = 6f; + + [Tooltip("インタラクト可能とみなす最大距離(m, プレイヤー基準)。_discoverRadius 以下にする")] + [SerializeField] private float _interactRadius = 3f; + + [Tooltip("検出スキャンの間隔(秒)。毎フレームではなく間引く")] + [SerializeField] private float _scanInterval = 0.1f; + + [Tooltip("候補収集の対象レイヤー(Interactable)")] + [SerializeField] private LayerMask _interactableMask = ~0; + + [Tooltip("遮蔽判定の対象レイヤー(壁・床・構造物)。対象自身のレイヤー(Interactable)は含めないこと")] + [SerializeField] private LayerMask _occluderMask = ~0; + + [Tooltip("レティクルからのエイムアシスト用 SphereCast 半径(m)。小さいほど厳密、大きいほど掴みやすい")] + [SerializeField] private float _aimAssistRadius = 0.15f; + + // 遮蔽レイを対象表面の手前で止め、対象自身の collider への自己ヒットを避けるための余白 + private const float OcclusionMargin = 0.05f; + + // レティクル SphereCast の原点をカメラ手前へ後退させる量(対象へのめり込みによる検出漏れ対策) + private const float AimCastBackstep = 0.2f; + + // 物理クエリ・候補集計用の再利用バッファ(毎スキャンで Clear し GC を避ける) + private readonly Collider[] _hitBuffer = new Collider[16]; + private readonly HashSet _seen = new(); + private readonly List _visible = new(); + + // 提示状態の差分追跡(前回 / 今回)。Scan 末尾で swap して再利用する + private Dictionary _previousStates = new(); + private Dictionary _currentStates = new(); + + private IInteractable _actionable; + private float _nextScanTime; + +#if UNITY_EDITOR + // ---- デバッグ Gizmo トグル ---- + [Header("Debug Gizmos")] + [SerializeField] private bool _drawGizmos = false; + [SerializeField] private bool _drawDiscoverRadius = true; + [SerializeField] private bool _drawInteractRadius = true; + [SerializeField] private bool _drawAimCast = true; + [SerializeField] private bool _drawOcclusionRays = true; + [SerializeField] private bool _drawCameraFrustum = true; + [SerializeField] private bool _drawCandidates = true; + + // ---- Gizmo 色定数 ---- + private static readonly Color GizmoColorDiscoverRadius = Color.cyan; + private static readonly Color GizmoColorInteractRadius = Color.yellow; + private static readonly Color GizmoColorAimCastMiss = Color.white; + private static readonly Color GizmoColorAimCastHit = Color.green; + private static readonly Color GizmoColorOcclusionRayClear = Color.green; + private static readonly Color GizmoColorOcclusionRayBlocked = Color.red; + private static readonly Color GizmoColorFrustum = Color.gray; + private static readonly Color GizmoColorCandidateDiscoverable = Color.cyan; + private static readonly Color GizmoColorCandidateActionable = Color.green; + private static readonly Color GizmoColorCandidateOutOfView = new Color(0.3f, 0.3f, 0.3f); + private static readonly Color GizmoColorCandidateOccluded = Color.red; + + // ---- 候補分類 ---- + private enum GizmoCandidateKind { OutOfView, Occluded, Discoverable, Actionable } + + private readonly struct GizmoCandidate + { + public readonly Vector3 Center; + public readonly GizmoCandidateKind Kind; + + public GizmoCandidate(Vector3 center, GizmoCandidateKind kind) + { + Center = center; + Kind = kind; + } + } + + // ---- スナップショット(最後のスキャン結果を OnDrawGizmos から参照する) ---- + private Vector3 _gizmoCamPos; + private Vector3 _gizmoAimOrigin; + private Vector3 _gizmoAimDir; + private float _gizmoAimMaxDist; + private bool _gizmoAimHasHit; + private Vector3 _gizmoAimHitPoint; + private readonly List _gizmoCandidates = new(); + + // 遮蔽レイのスナップショット(origin → center、ヒット有無) + private readonly struct GizmoOcclusionRay + { + public readonly Vector3 From; + public readonly Vector3 To; + public readonly bool Blocked; + + public GizmoOcclusionRay(Vector3 from, Vector3 to, bool blocked) + { + From = from; + To = to; + Blocked = blocked; + } + } + + private readonly List _gizmoOcclusionRays = new(); +#endif + + /// + /// 現在の実行可能(Actionable)対象を取得する。存在しなければ false。Interact 入力の実行先。 + /// + public bool TryGetActionable(out IInteractable target) + { + target = IsAlive(_actionable) ? _actionable : null; + return target != null; + } + + private void Update() + { + if (Time.time < _nextScanTime) return; + _nextScanTime = Time.time + _scanInterval; + Scan(); + } + + private void Scan() + { +#if UNITY_EDITOR + _gizmoCandidates.Clear(); + _gizmoOcclusionRays.Clear(); + if (_camera != null) + { + _gizmoCamPos = _camera.transform.position; + } +#endif + + _visible.Clear(); + _seen.Clear(); + _currentStates.Clear(); + _actionable = null; + + if (_camera != null) + { + CollectVisible(); + _actionable = SelectActionableByAimCast(); + + for (int i = 0; i < _visible.Count; i++) + { + var target = _visible[i]; + _currentStates[target] = ReferenceEquals(target, _actionable) + ? InteractionState.Actionable + : InteractionState.Discoverable; + +#if UNITY_EDITOR + // 最終分類を候補リストへ反映する(CollectVisible で Discoverable として仮記録済みの要素を上書き) + var finalKind = ReferenceEquals(target, _actionable) + ? GizmoCandidateKind.Actionable + : GizmoCandidateKind.Discoverable; + var center = target.CenterPosition; + // 仮記録(Discoverable)を最終 kind に差し替える + bool replaced = false; + for (int j = 0; j < _gizmoCandidates.Count; j++) + { + if (_gizmoCandidates[j].Center == center && _gizmoCandidates[j].Kind == GizmoCandidateKind.Discoverable) + { + _gizmoCandidates[j] = new GizmoCandidate(center, finalKind); + replaced = true; + break; + } + } + + // _visible への追加後に Gizmo スナップショットが未登録の場合は追加する + if (!replaced) + { + _gizmoCandidates.Add(new GizmoCandidate(center, finalKind)); + } +#endif + } + } + + ApplyStates(); + } + + // 範囲内の候補から「カメラ視界内かつ非遮蔽」のものを _visible に集める(Discoverable 候補)。 + private void CollectVisible() + { + var playerPos = transform.position; + var camPos = _camera.transform.position; + + int hitCount = Physics.OverlapSphereNonAlloc( + playerPos, _discoverRadius, _hitBuffer, _interactableMask, QueryTriggerInteraction.Collide); + + for (int i = 0; i < hitCount; i++) + { + var hit = _hitBuffer[i]; + if (hit == null || !hit.gameObject.activeInHierarchy) continue; + + var interactable = hit.GetComponentInParent(); + if (interactable == null || !_seen.Add(interactable)) continue; // 複数コライダーの重複を排除 + + var center = interactable.CenterPosition; + + // カメラ視界(frustum)内か + var viewport = _camera.WorldToViewportPoint(center); + if (viewport.z <= 0f || viewport.x < 0f || viewport.x > 1f || viewport.y < 0f || viewport.y > 1f) + { +#if UNITY_EDITOR + _gizmoCandidates.Add(new GizmoCandidate(center, GizmoCandidateKind.OutOfView)); +#endif + continue; + } + + // 遮蔽(壁越し)を除外:カメラ→中心の間に遮蔽物があれば不可視 + var toCenter = center - camPos; + float dist = toCenter.magnitude; + if (dist > OcclusionMargin && + Physics.Raycast(camPos, toCenter, dist - OcclusionMargin, _occluderMask, QueryTriggerInteraction.Ignore)) + { +#if UNITY_EDITOR + _gizmoCandidates.Add(new GizmoCandidate(center, GizmoCandidateKind.Occluded)); + _gizmoOcclusionRays.Add(new GizmoOcclusionRay(camPos, center, blocked: true)); +#endif + continue; + } + +#if UNITY_EDITOR + // 非遮蔽レイもスナップショットに記録する + if (dist > OcclusionMargin) + { + _gizmoOcclusionRays.Add(new GizmoOcclusionRay(camPos, center, blocked: false)); + } + + // _visible.Add より前に Discoverable として仮記録する(Scan の状態決定ループで最終 kind へ差し替える) + _gizmoCandidates.Add(new GizmoCandidate(center, GizmoCandidateKind.Discoverable)); +#endif + + _visible.Add(interactable); + } + } + + /// + /// レティクル(画面中心)から SphereCast を撃ち、ヒットした単一対象を Actionable として返す。 + /// エイムアシスト半径 ぶんの許容を持たせ、レティクルが対象コライダーに + /// 重なっているときのみ成立する。原点はカメラへのめり込み対策で 後退させる。 + /// マスクは Interactable のみ。遮蔽は (中心点への細いレイ遮蔽を通った集合)への + /// 包含チェックで担保し、Actionable ⊆ Discoverable を保証する。 + /// + private IInteractable SelectActionableByAimCast() + { + var ray = _camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); + var origin = ray.origin - ray.direction * AimCastBackstep; + float maxDist = _interactRadius + AimCastBackstep; + + bool hasHit = Physics.SphereCast(origin, _aimAssistRadius, ray.direction, out var hit, maxDist, _interactableMask, QueryTriggerInteraction.Collide); + +#if UNITY_EDITOR + _gizmoAimOrigin = origin; + _gizmoAimDir = ray.direction; + _gizmoAimMaxDist = maxDist; + _gizmoAimHasHit = hasHit; + _gizmoAimHitPoint = hasHit ? hit.point : Vector3.zero; +#endif + + if (!hasHit) + { + return null; + } + + var target = hit.collider.GetComponentInParent(); + if (target == null || !_visible.Contains(target)) return null; + + return target; + } + + // 前回との差分のみ通知する。今回不在の対象は Hidden に戻し、状態変化のみ反映する。 + private void ApplyStates() + { + foreach (var pair in _previousStates) + { + if (!_currentStates.ContainsKey(pair.Key) && IsAlive(pair.Key)) + { + pair.Key.SetInteractionState(InteractionState.Hidden, _camera); + } + } + + foreach (var pair in _currentStates) + { + if (!_previousStates.TryGetValue(pair.Key, out var previous) || previous != pair.Value) + { + pair.Key.SetInteractionState(pair.Value, _camera); + } + } + + (_previousStates, _currentStates) = (_currentStates, _previousStates); + } + + // 無効化時、提示中の対象を Hidden に戻して取り残しを防ぐ + private void OnDisable() + { + foreach (var pair in _previousStates) + { + if (IsAlive(pair.Key)) pair.Key.SetInteractionState(InteractionState.Hidden, _camera); + } + + _previousStates.Clear(); + _actionable = null; + _nextScanTime = 0f; + } + + // IInteractable 実装が破棄済み Unity オブジェクトでないかを安全に判定する + private static bool IsAlive(IInteractable interactable) + { + if (interactable is Object unityObject) return unityObject != null; + return interactable != null; + } + +#if UNITY_EDITOR + private void OnDrawGizmos() + { + if (!_drawGizmos) return; + + // 範囲スフィアは Play 外でも transform.position から描画できる + if (_drawDiscoverRadius) + { + Gizmos.color = GizmoColorDiscoverRadius; + Gizmos.DrawWireSphere(transform.position, _discoverRadius); + } + + if (_drawInteractRadius) + { + Gizmos.color = GizmoColorInteractRadius; + Gizmos.DrawWireSphere(transform.position, _interactRadius); + } + + // カメラ・スナップショット依存の描画は Play 中かつ参照が有効なときのみ + if (!Application.isPlaying || _camera == null) return; + + if (_drawCameraFrustum) + { + Gizmos.color = GizmoColorFrustum; + Gizmos.matrix = _camera.transform.localToWorldMatrix; + Gizmos.DrawFrustum( + Vector3.zero, + _camera.fieldOfView, + _camera.farClipPlane, + _camera.nearClipPlane, + _camera.aspect); + Gizmos.matrix = Matrix4x4.identity; + } + + if (_drawOcclusionRays) + { + foreach (var ray in _gizmoOcclusionRays) + { + Gizmos.color = ray.Blocked ? GizmoColorOcclusionRayBlocked : GizmoColorOcclusionRayClear; + Gizmos.DrawLine(ray.From, ray.To); + } + } + + if (_drawAimCast) + { + Gizmos.color = _gizmoAimHasHit ? GizmoColorAimCastHit : GizmoColorAimCastMiss; + DrawSphereCast(_gizmoAimOrigin, _gizmoAimDir, _aimAssistRadius, _gizmoAimMaxDist, _gizmoAimHasHit, _gizmoAimHitPoint); + } + + if (_drawCandidates) + { + foreach (var candidate in _gizmoCandidates) + { + Gizmos.color = candidate.Kind switch + { + GizmoCandidateKind.Actionable => GizmoColorCandidateActionable, + GizmoCandidateKind.Discoverable => GizmoColorCandidateDiscoverable, + GizmoCandidateKind.Occluded => GizmoColorCandidateOccluded, + _ => GizmoColorCandidateOutOfView, + }; + Gizmos.DrawWireSphere(candidate.Center, 0.15f); + } + } + } + + /// + /// SphereCast の軌道を Gizmo で可視化する。始点・終点に球、軸線で軌跡を表現する。 + /// + /// キャスト始点(AimCastBackstep 後退済みの原点) + /// キャスト方向 + /// 球の半径 + /// 最大距離 + /// ヒットした場合 true + /// ヒット点(hasHit が false の場合は未使用) + private static void DrawSphereCast(Vector3 origin, Vector3 dir, float radius, float maxDist, bool hasHit, Vector3 hitPoint) + { + var endpoint = hasHit ? hitPoint : origin + dir * maxDist; + Gizmos.DrawWireSphere(origin, radius); + Gizmos.DrawWireSphere(endpoint, radius); + Gizmos.DrawLine(origin, endpoint); + } +#endif + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionDetector.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionDetector.cs.meta new file mode 100644 index 00000000..a70fb60a --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionDetector.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c74449a1721cdad439af4791b74e437d \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionOutlineHighlighter.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionOutlineHighlighter.cs new file mode 100644 index 00000000..c0b562db --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionOutlineHighlighter.cs @@ -0,0 +1,76 @@ +using System; +using UnityEngine; + +namespace Game.Shared.Interaction +{ + /// + /// 対象 Renderer の materials にアウトライン用 Material を一時的に追加してハイライトする。 + /// の割り当てのみを差し替えることで、 + /// マテリアルのインスタンス化(リーク)を避けつつ追加パス描画を実現する。 + /// + public class InteractionOutlineHighlighter : MonoBehaviour + { + [Tooltip("背面押し出しアウトライン用 Material(Game/InteractionOutline シェーダー)")] + [SerializeField] private Material _outlineMaterial; + + [Tooltip("対象 Renderer。未指定なら自身と子から自動取得する")] + [SerializeField] private Renderer[] _renderers; + + // 各 Renderer の元の共有マテリアル割り当て(解除時に戻すための参照) + private Material[][] _originalSharedMaterials; + private bool _isHighlighted; + + private void Awake() + { + if (_renderers == null || _renderers.Length == 0) + { + _renderers = GetComponentsInChildren(includeInactive: true); + } + + _originalSharedMaterials = new Material[_renderers.Length][]; + for (int i = 0; i < _renderers.Length; i++) + { + _originalSharedMaterials[i] = _renderers[i] != null ? _renderers[i].sharedMaterials : Array.Empty(); + } + } + + /// + /// ハイライト表示を切り替える。同じ状態への再呼び出しは無視する(二重付与防止)。 + /// + public void SetHighlighted(bool highlighted) + { + if (_isHighlighted == highlighted) return; + _isHighlighted = highlighted; + + if (_outlineMaterial == null) return; + + for (int i = 0; i < _renderers.Length; i++) + { + var targetRenderer = _renderers[i]; + if (targetRenderer == null) continue; + + if (highlighted) + { + var original = _originalSharedMaterials[i]; + var extended = new Material[original.Length + 1]; + Array.Copy(original, extended, original.Length); + extended[original.Length] = _outlineMaterial; + targetRenderer.sharedMaterials = extended; + } + else + { + targetRenderer.sharedMaterials = _originalSharedMaterials[i]; + } + } + } + + // 無効化・破棄時にハイライトが残らないよう確実に元へ戻す + private void OnDisable() + { + if (_isHighlighted) + { + SetHighlighted(false); + } + } + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionOutlineHighlighter.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionOutlineHighlighter.cs.meta new file mode 100644 index 00000000..3c33cd2e --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionOutlineHighlighter.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3208eea20eafef44c8cd8901879d2d4c \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionPromptView.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionPromptView.cs new file mode 100644 index 00000000..f51ff114 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionPromptView.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +namespace Game.Shared.Interaction +{ + /// + /// インタラクト対象の位置に出すワールド空間プロンプト。対象(Interactable)が所有し、対象プレハブの子として配置する。 + /// 検出器から渡される に応じて発見可能/実行可能の見た目を出し分け、視点カメラへビルボードする。 + /// 見た目の意味(発見/実行可能)は検出器が決め、ここは表示と正対だけを担う。 + /// 既定は非アクティブ運用で、Hidden では自身を無効化し描画もビルボードも止める。 + /// + public class InteractionPromptView : MonoBehaviour + { + [Tooltip("発見可能(対象だと分かる)状態の見た目")] + [SerializeField] private GameObject _discoverableView; + + [Tooltip("実行可能(インタラクトできる)状態の見た目")] + [SerializeField] private GameObject _actionableView; + + private Camera _viewCamera; + + /// + /// 提示状態を反映する。Hidden で自身を無効化し、Discoverable/Actionable で対応する見た目だけを出す。 + /// はビルボードの正対先(Hidden 時は未使用)。 + /// + public void SetState(InteractionState state, Camera viewCamera) + { + _viewCamera = viewCamera; + + bool discoverable = state == InteractionState.Discoverable; + bool actionable = state == InteractionState.Actionable; + + if (_discoverableView != null) _discoverableView.SetActive(discoverable); + if (_actionableView != null) _actionableView.SetActive(actionable); + + gameObject.SetActive(discoverable || actionable); + } + + private void LateUpdate() + { + if (_viewCamera != null) + { + transform.rotation = _viewCamera.transform.rotation; + } + } + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionPromptView.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionPromptView.cs.meta new file mode 100644 index 00000000..1c0965a2 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionPromptView.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4209e929371b0c3458546114fb7defb6 \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionState.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionState.cs new file mode 100644 index 00000000..8deac238 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionState.cs @@ -0,0 +1,17 @@ +namespace Game.Shared.Interaction +{ + /// + /// インタラクト対象の提示状態。検出器が距離・可視性から判定し、対象側のプロンプト表示へ反映する。 + /// + public enum InteractionState + { + /// 非提示(検出範囲外・視界外・遮蔽)。 + Hidden, + + /// 発見可能。対象だと分かるが、まだインタラクトできない(距離が遠い)。複数同時に成立しうる。 + Discoverable, + + /// インタラクト可能。画面中心に最も近い単一対象のみが成立する。 + Actionable, + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionState.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionState.cs.meta new file mode 100644 index 00000000..9b36ad7a --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Interaction/InteractionState.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0bfbf7e77a631b1489072a19998cd2bd \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizationEvents.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizationEvents.cs new file mode 100644 index 00000000..7878748e --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizationEvents.cs @@ -0,0 +1,17 @@ +using System; +using R3; +using UnityEngine.Localization; +using UnityEngine.Localization.Settings; + +namespace Game.Shared.Localization +{ + public static class LocalizationEvents + { + public static Observable OnLocaleChanged + => Observable.FromEvent, Locale>( + h => h, + h => LocalizationSettings.SelectedLocaleChanged += h, + h => LocalizationSettings.SelectedLocaleChanged -= h); + + } +} diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizationEvents.cs.meta b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizationEvents.cs.meta new file mode 100644 index 00000000..aadfe6a0 --- /dev/null +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizationEvents.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6af7d626558c4ec3b800820cf46cb6cd +timeCreated: 1781751275 \ No newline at end of file diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeDropdown.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeDropdown.cs index 2f29bfec..97238c63 100644 --- a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeDropdown.cs +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeDropdown.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using R3; using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; @@ -17,12 +18,7 @@ private void Awake() { if (_tmpDropdown == null) TryGetComponent(out _tmpDropdown); - LocalizationSettings.SelectedLocaleChanged += OnChangedLocale; - } - - private void OnDestroy() - { - LocalizationSettings.SelectedLocaleChanged -= OnChangedLocale; + LocalizationEvents.OnLocaleChanged.Subscribe(x => OnLocaleChanged(x)).AddTo(this); } private void OnEnable() @@ -33,10 +29,10 @@ private void OnEnable() [ContextMenu("Update Locale")] public void UpdateLocale() { - OnChangedLocale(LocalizationSettings.SelectedLocale); + OnLocaleChanged(LocalizationSettings.SelectedLocale); } - private void OnChangedLocale(Locale newLocale) + private void OnLocaleChanged(Locale newLocale) { var tmpDropdownOptions = new List(_dropdownOptions.Count); foreach (var dropdownOption in _dropdownOptions) diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeFontMaterial.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeFontMaterial.cs index 70e89a08..3832a622 100644 --- a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeFontMaterial.cs +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeFontMaterial.cs @@ -1,8 +1,7 @@ -using System.Collections.Generic; -using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks; +using R3; using UnityEngine; using UnityEngine.Localization; -using UnityEngine.Localization.Settings; using TMPro; using UnityEditor; @@ -18,20 +17,15 @@ private void Awake() { if (_tmp == null) TryGetComponent(out _tmp); - LocalizationSettings.SelectedLocaleChanged += ChangedLocale; + LocalizationEvents.OnLocaleChanged.Subscribe(x => OnLocaleChanged(x)).AddTo(this); } - private void OnDestroy() + private void OnLocaleChanged(Locale newLocale) { - LocalizationSettings.SelectedLocaleChanged -= ChangedLocale; + OnLocaleChangedAsync(newLocale).Forget(); } - private void ChangedLocale(Locale newLocale) - { - ChangedLocaleAsync(newLocale).Forget(); - } - - private async UniTask ChangedLocaleAsync(Locale newLocale) + private async UniTask OnLocaleChangedAsync(Locale newLocale) { _tmp.fontSharedMaterial = await _fontMaterial.LoadAssetAsync().ToUniTask(); } diff --git a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeStrings.cs b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeStrings.cs index 31005de0..112db464 100644 --- a/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeStrings.cs +++ b/src/Game.Client/Assets/Programs/Runtime/Shared/Localization/LocalizeStrings.cs @@ -16,12 +16,7 @@ public class LocalizeStrings : MonoBehaviour private void Awake() { - LocalizationSettings.SelectedLocaleChanged += SelectedLocaleChanged; - } - - private void OnDestroy() - { - LocalizationSettings.SelectedLocaleChanged -= SelectedLocaleChanged; + LocalizationEvents.OnLocaleChanged.Subscribe(x => OnLocaleChanged(x)).AddTo(this); } private void OnEnable() @@ -32,10 +27,10 @@ private void OnEnable() [ContextMenu("Update Locale")] public void UpdateLocale() { - SelectedLocaleChanged(LocalizationSettings.SelectedLocale); + OnLocaleChanged(LocalizationSettings.SelectedLocale); } - private void SelectedLocaleChanged(Locale newLocale) + private void OnLocaleChanged(Locale newLocale) { _strings = new string[_localizedStrings.Length]; diff --git a/src/Game.Client/Assets/ProjectAssets/Horror/HorrorOptionDialog.prefab b/src/Game.Client/Assets/ProjectAssets/Horror/HorrorOptionDialog.prefab index 3b142800..0d328891 100644 --- a/src/Game.Client/Assets/ProjectAssets/Horror/HorrorOptionDialog.prefab +++ b/src/Game.Client/Assets/ProjectAssets/Horror/HorrorOptionDialog.prefab @@ -8394,7 +8394,7 @@ MonoBehaviour: - m_TableReference: m_TableCollectionName: GUID:2cc7cf7ec22e69241b4d071651007bf7 m_TableEntryReference: - m_KeyId: 483635457687552 + m_KeyId: 6465602920128512 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 @@ -15089,8 +15089,8 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3271000611976609107} - - {fileID: 7321167726328103510} - {fileID: 4036270655355700777} + - {fileID: 7321167726328103510} - {fileID: 5692176500247773740} m_Father: {fileID: 7337786248745576176} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -15154,12 +15154,12 @@ MonoBehaviour: - _tab: {fileID: 4407457442671658888} _tabContent: {fileID: 5825901446882256100} _firstSelectable: {fileID: 6802981768607562189} - - _tab: {fileID: 9147347096868443825} - _tabContent: {fileID: 7216870724724073885} - _firstSelectable: {fileID: 4095502674537021207} - _tab: {fileID: 4342105382734352075} _tabContent: {fileID: 8820221933286825385} _firstSelectable: {fileID: 4423970100486267297} + - _tab: {fileID: 9147347096868443825} + _tabContent: {fileID: 7216870724724073885} + _firstSelectable: {fileID: 4095502674537021207} - _tab: {fileID: 2986580764817631354} _tabContent: {fileID: 9083898922614142786} _firstSelectable: {fileID: 4940530688796753995} @@ -23904,8 +23904,8 @@ RectTransform: m_Children: - {fileID: 5773870475033361026} - {fileID: 3782782146472869397} - - {fileID: 1858488433004225244} - {fileID: 5496554054974584835} + - {fileID: 1858488433004225244} - {fileID: 9781424959107029} m_Father: {fileID: 1889253254155075518} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -45410,7 +45410,7 @@ GameObject: m_Component: - component: {fileID: 1858488433004225244} m_Layer: 5 - m_Name: TabContent (1) + m_Name: TabContent (2) m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -47311,7 +47311,7 @@ GameObject: - component: {fileID: 4036270655355700777} - component: {fileID: 4342105382734352075} m_Layer: 5 - m_Name: Toggle (2) + m_Name: Toggle (1) m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -52753,7 +52753,7 @@ MonoBehaviour: - m_TableReference: m_TableCollectionName: GUID:2cc7cf7ec22e69241b4d071651007bf7 m_TableEntryReference: - m_KeyId: 483635457687552 + m_KeyId: 6465602920128512 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 @@ -54398,7 +54398,7 @@ GameObject: - component: {fileID: 5496554054974584835} - component: {fileID: 2754357831805096757} m_Layer: 5 - m_Name: TabContent (2) + m_Name: TabContent (1) m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -56149,7 +56149,7 @@ GameObject: - component: {fileID: 7321167726328103510} - component: {fileID: 9147347096868443825} m_Layer: 5 - m_Name: Toggle (1) + m_Name: Toggle (2) m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/src/Game.Client/Assets/ProjectAssets/Horror/HorrorPlayer.prefab b/src/Game.Client/Assets/ProjectAssets/Horror/HorrorPlayer.prefab index ff42d18c..7439e33d 100644 --- a/src/Game.Client/Assets/ProjectAssets/Horror/HorrorPlayer.prefab +++ b/src/Game.Client/Assets/ProjectAssets/Horror/HorrorPlayer.prefab @@ -137,6 +137,90 @@ MonoBehaviour: m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 m_Version: 2 +--- !u!1 &1853895984491719094 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5126711315736670585} + - component: {fileID: 3701998614938783907} + - component: {fileID: 4054187089009888677} + m_Layer: 5 + m_Name: OverlayCanvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5126711315736670585 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853895984491719094} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 9221922205495207645} + m_Father: {fileID: 78722406302841152} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &3701998614938783907 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853895984491719094} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &4054187089009888677 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1853895984491719094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.CanvasScaler + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1920, y: 1080} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0.5 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 --- !u!1 &3649338037539827978 GameObject: m_ObjectHideFlags: 0 @@ -151,6 +235,7 @@ GameObject: - component: {fileID: 2106959460308340998} - component: {fileID: 1795677415710958266} - component: {fileID: 579882215014566955} + - component: {fileID: 8001035782658720818} m_Layer: 6 m_Name: HorrorPlayer m_TagString: Player @@ -172,6 +257,7 @@ Transform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3108793209200739432} + - {fileID: 5126711315736670585} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2150554309678237392 @@ -303,3 +389,101 @@ MonoBehaviour: serializedVersion: 2 m_Bits: 520 _lookRotationSpeed: 0.1 + _interactionDetector: {fileID: 8001035782658720818} +--- !u!114 &8001035782658720818 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3649338037539827978} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c74449a1721cdad439af4791b74e437d, type: 3} + m_Name: + m_EditorClassIdentifier: Game.Shared::Game.Shared.Interaction.InteractionDetector + _camera: {fileID: 6031481874108313397} + _discoverRadius: 6 + _interactRadius: 3 + _scanInterval: 0.1 + _interactableMask: + serializedVersion: 2 + m_Bits: 1024 + _occluderMask: + serializedVersion: 2 + m_Bits: 521 +--- !u!1 &6853252730508953924 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9221922205495207645} + - component: {fileID: 6225604774251074927} + - component: {fileID: 1166145205959247092} + m_Layer: 5 + m_Name: Reticle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &9221922205495207645 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6853252730508953924} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5126711315736670585} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 8, y: 8} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6225604774251074927 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6853252730508953924} + m_CullTransparentMesh: 1 +--- !u!114 &1166145205959247092 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6853252730508953924} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 diff --git a/src/Game.Client/Assets/ProjectAssets/Horror/InteractableProp.prefab b/src/Game.Client/Assets/ProjectAssets/Horror/InteractableProp.prefab new file mode 100644 index 00000000..37fbdbcd --- /dev/null +++ b/src/Game.Client/Assets/ProjectAssets/Horror/InteractableProp.prefab @@ -0,0 +1,377 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2370059137242679700 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4521616455389761557} + - component: {fileID: 3122530118763237390} + - component: {fileID: 6897306515561596321} + - component: {fileID: 9185099571006861220} + - component: {fileID: 4210744080654593999} + - component: {fileID: 3459488448602718721} + m_Layer: 10 + m_Name: InteractableProp + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4521616455389761557 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2370059137242679700} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7702425761677231579} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &3122530118763237390 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2370059137242679700} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!65 &6897306515561596321 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2370059137242679700} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &9185099571006861220 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2370059137242679700} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &4210744080654593999 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2370059137242679700} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3208eea20eafef44c8cd8901879d2d4c, type: 3} + m_Name: + m_EditorClassIdentifier: Game.Shared::Game.Shared.Interaction.InteractionOutlineHighlighter + _outlineMaterial: {fileID: 2100000, guid: eaf08f643893b234d8d3b2d848977090, type: 2} + _renderers: [] +--- !u!114 &3459488448602718721 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2370059137242679700} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b200b3ffde9a6684b9fb58ab9ca1d347, type: 3} + m_Name: + m_EditorClassIdentifier: Game.Shared::Game.Shared.Interaction.DebugInteractable + _label: TestCube + _centerOverride: {fileID: 0} + _highlighter: {fileID: 4210744080654593999} + _promptView: {fileID: 7470606940327279703} +--- !u!1 &2915891914776573175 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6338716362026147487} + - component: {fileID: 1207585223051931135} + m_Layer: 0 + m_Name: Discoverable + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6338716362026147487 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2915891914776573175} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.3, y: 0.3, z: 0.3} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7702425761677231579} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &1207585223051931135 +SpriteRenderer: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2915891914776573175} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_Sprite: {fileID: -2413806693520163455, guid: e0a396cdafe4edc4d89d36c048b88155, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 0.4} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_SpriteSortPoint: 0 +--- !u!1 &3080340344588292183 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1953690948070087577} + - component: {fileID: 2809519297262676362} + m_Layer: 0 + m_Name: Actionable + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1953690948070087577 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3080340344588292183} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7702425761677231579} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &2809519297262676362 +SpriteRenderer: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3080340344588292183} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_Sprite: {fileID: -2413806693520163455, guid: e0a396cdafe4edc4d89d36c048b88155, type: 3} + m_Color: {r: 1, g: 0.92, b: 0.35, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_SpriteSortPoint: 0 +--- !u!1 &7474064028384245418 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7702425761677231579} + - component: {fileID: 7470606940327279703} + m_Layer: 0 + m_Name: InteractionPrompt + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &7702425761677231579 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7474064028384245418} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.664, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6338716362026147487} + - {fileID: 1953690948070087577} + m_Father: {fileID: 4521616455389761557} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &7470606940327279703 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7474064028384245418} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4209e929371b0c3458546114fb7defb6, type: 3} + m_Name: + m_EditorClassIdentifier: Game.Shared::Game.Shared.Interaction.InteractionPromptView + _discoverableView: {fileID: 2915891914776573175} + _actionableView: {fileID: 3080340344588292183} diff --git a/src/Game.Client/Assets/ProjectAssets/Horror/InteractableProp.prefab.meta b/src/Game.Client/Assets/ProjectAssets/Horror/InteractableProp.prefab.meta new file mode 100644 index 00000000..cb0e2146 --- /dev/null +++ b/src/Game.Client/Assets/ProjectAssets/Horror/InteractableProp.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9425083eb7f4dc1488081a1da3a6d4f2 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Game.Client/Assets/Shaders/Outline.meta b/src/Game.Client/Assets/Shaders/Outline.meta new file mode 100644 index 00000000..e6043507 --- /dev/null +++ b/src/Game.Client/Assets/Shaders/Outline.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3ff3e4b21c933514e8350903a47bc1de +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.mat b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.mat new file mode 100644 index 00000000..a9b36250 --- /dev/null +++ b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.mat @@ -0,0 +1,32 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: InteractionOutline + m_Shader: {fileID: 4800000, guid: b04b6383d0565374c9b155ea5c12bb32, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Ints: [] + m_Floats: + - _OutlineWidth: 2 + m_Colors: + - _OutlineColor: {r: 0.9, g: 0.9019608, b: 0.9, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.mat.meta b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.mat.meta new file mode 100644 index 00000000..767ff636 --- /dev/null +++ b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eaf08f643893b234d8d3b2d848977090 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.shader b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.shader new file mode 100644 index 00000000..13019467 --- /dev/null +++ b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.shader @@ -0,0 +1,87 @@ +Shader "Game/InteractionOutline" +{ + // インタラクト可能の視覚表現用。背面を法線方向へ押し出して単色描画する + // 単一パスのアウトライン専用シェーダー。対象 Renderer の materials に + // このマテリアルを一時追加することでアウトラインを重ねる(QuickOutline 型)。 + Properties + { + [HDR] _OutlineColor("Outline Color", Color) = (1, 0.85, 0.3, 1) + _OutlineWidth("Outline Width", Range(0, 10)) = 2 + } + + SubShader + { + Tags + { + "RenderType" = "Opaque" + "RenderPipeline" = "UniversalPipeline" + "Queue" = "Geometry+1" + } + + // 背面押し出しパス(URP のデフォルト Unlit パスとして描画される) + Pass + { + Name "InteractionOutline" + Tags { "LightMode" = "SRPDefaultUnlit" } + + Cull Front + ZWrite On + ZTest LEqual + + HLSLPROGRAM + #pragma target 3.5 + + #pragma multi_compile_instancing + + #pragma vertex OutlineVert + #pragma fragment OutlineFrag + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + + CBUFFER_START(UnityPerMaterial) + float4 _OutlineColor; + float _OutlineWidth; + CBUFFER_END + + struct Attributes + { + float4 positionOS : POSITION; + float3 normalOS : NORMAL; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct Varyings + { + float4 positionCS : SV_POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + Varyings OutlineVert(Attributes input) + { + Varyings output = (Varyings)0; + + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + // 法線方向へワールド空間でオフセット(ToonLit の Outline パスと同方式) + float3 normalWS = TransformObjectToWorldNormal(input.normalOS); + float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); + positionWS += normalWS * _OutlineWidth * 0.001; + + output.positionCS = TransformWorldToHClip(positionWS); + return output; + } + + half4 OutlineFrag(Varyings input) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + return _OutlineColor; + } + ENDHLSL + } + } + + Fallback Off +} diff --git a/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.shader.meta b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.shader.meta new file mode 100644 index 00000000..5c1c5b4b --- /dev/null +++ b/src/Game.Client/Assets/Shaders/Outline/InteractionOutline.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b04b6383d0565374c9b155ea5c12bb32 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Game.Client/Assets/StoreAssets/Abandoned_Asylum/Show.unity b/src/Game.Client/Assets/StoreAssets/Abandoned_Asylum/Show.unity index cc32c8dd..d58c446b 100644 --- a/src/Game.Client/Assets/StoreAssets/Abandoned_Asylum/Show.unity +++ b/src/Game.Client/Assets/StoreAssets/Abandoned_Asylum/Show.unity @@ -1215,6 +1215,63 @@ Transform: m_Children: [] m_Father: {fileID: 1291821140} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &328047174 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 2370059137242679700, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_Name + value: InteractableProp + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.x + value: -3.197 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.y + value: 0.816 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.z + value: 0.56073 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} --- !u!114 &328763674 MonoBehaviour: m_ObjectHideFlags: 0 @@ -3950,6 +4007,63 @@ Transform: m_Children: [] m_Father: {fileID: 1291821140} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1216100915 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 2370059137242679700, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_Name + value: InteractableProp (1) + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.x + value: -1.813 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.y + value: 0.816 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.z + value: 0.906 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} --- !u!1 &1225706784 GameObject: m_ObjectHideFlags: 0 @@ -5001,6 +5115,63 @@ MonoBehaviour: m_ShadowLayerMask: 1 m_RenderingLayers: 1 m_ShadowRenderingLayers: 1 +--- !u!1001 &1646454103 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 2370059137242679700, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_Name + value: InteractableProp (2) + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.x + value: -0.773 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.y + value: 0.816 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalPosition.z + value: -0.679 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4521616455389761557, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 9425083eb7f4dc1488081a1da3a6d4f2, type: 3} --- !u!114 &1657558749 MonoBehaviour: m_ObjectHideFlags: 0 @@ -7944,3 +8115,6 @@ SceneRoots: - {fileID: 1291821140} - {fileID: 7889189494809962464} - {fileID: 2037320964} + - {fileID: 328047174} + - {fileID: 1216100915} + - {fileID: 1646454103} diff --git a/src/Game.Client/Packages/manifest.json b/src/Game.Client/Packages/manifest.json index d4ec66e9..75bed660 100644 --- a/src/Game.Client/Packages/manifest.json +++ b/src/Game.Client/Packages/manifest.json @@ -9,7 +9,7 @@ } ], "dependencies": { - "com.coplaydev.unity-mcp": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v9.7.1", + "com.coplaydev.unity-mcp": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v9.7.3", "com.cysharp.magiconion.client.unity": "https://github.com/Cysharp/MagicOnion.git?path=src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion.Client.Unity#7.0.9", "com.cysharp.memorypack": "https://github.com/Cysharp/MemoryPack.git?path=src/MemoryPack.Unity/Assets/MemoryPack.Unity", "com.cysharp.messagepipe": "https://github.com/Cysharp/MessagePipe.git?path=src/MessagePipe.Unity/Assets/Plugins/MessagePipe", diff --git a/src/Game.Client/Packages/packages-lock.json b/src/Game.Client/Packages/packages-lock.json index 97d0dd5d..f97a61d6 100644 --- a/src/Game.Client/Packages/packages-lock.json +++ b/src/Game.Client/Packages/packages-lock.json @@ -1,14 +1,21 @@ { "dependencies": { "com.coplaydev.unity-mcp": { - "version": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v9.7.1", + "version": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v9.7.3", "depth": 0, "source": "git", "dependencies": { + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", "com.unity.nuget.newtonsoft-json": "3.0.2", "com.unity.test-framework": "1.1.31" }, - "hash": "78ee5418415953b79c358bfe6355fcc3fde7912b" + "hash": "85c101f5329ec1b0c6f70cba44614166dd78f53c" }, "com.cysharp.magiconion.client.unity": { "version": "https://github.com/Cysharp/MagicOnion.git?path=src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion.Client.Unity#7.0.9", diff --git a/src/Game.Client/ProjectSettings/ProjectSettings.asset b/src/Game.Client/ProjectSettings/ProjectSettings.asset index 82d0d715..e994e7e8 100644 --- a/src/Game.Client/ProjectSettings/ProjectSettings.asset +++ b/src/Game.Client/ProjectSettings/ProjectSettings.asset @@ -148,6 +148,7 @@ PlayerSettings: - {fileID: -944628639613478452, guid: 577a9d3b97e66d84c9bb35e58b05590d, type: 3} - {fileID: -944628639613478452, guid: 72fd472ba9a8dca43a0b96927f073670, type: 3} - {fileID: 11400000, guid: 8b1ffd3f298079841841fba6f08dc772, type: 2} + - {fileID: 11400000, guid: cc41d2c817d48ec4385d5efab9392103, type: 2} metroInputSource: 0 wsaTransparentSwapchain: 0 m_HolographicPauseOnTrackingLoss: 1 diff --git a/src/Game.Client/ProjectSettings/TagManager.asset b/src/Game.Client/ProjectSettings/TagManager.asset index 0dcc50ab..b40bdb25 100644 --- a/src/Game.Client/ProjectSettings/TagManager.asset +++ b/src/Game.Client/ProjectSettings/TagManager.asset @@ -19,7 +19,7 @@ TagManager: - Enemy - Item - Structure - - + - Interactable - - -