From ebb7ff5713e480f723961bf9f84413bc44e20926 Mon Sep 17 00:00:00 2001 From: Mathew Date: Wed, 8 Jul 2026 18:08:34 +0200 Subject: [PATCH] (Feat) Bed Systeme --- Assets/GAME/3D/Build.meta | 8 + Assets/GAME/Materials/Build.meta | 8 + Assets/GAME/Prefabs/Dual Bed.prefab | 181 ++++++++++++++++++ Assets/GAME/Prefabs/Dual Bed.prefab.meta | 7 + Assets/GAME/Script/Building/Bed.cs | 51 +++++ Assets/GAME/Script/Building/Bed.cs.meta | 2 + .../GAME/Script/Player/Events/PlayerEvents.cs | 11 ++ Assets/GAME/Script/Player/PlayerLifecycle.cs | 79 ++++++-- Assets/GAME/Textures/Build.meta | 8 + Assets/Resources/DefaultPrefabObjects.asset | 2 - .../Import for BiRP.unitypackage.meta | 14 -- .../Import for HDRP.unitypackage.meta | 14 -- .../Import for URP.unitypackage.meta | 14 -- 13 files changed, 344 insertions(+), 55 deletions(-) create mode 100644 Assets/GAME/3D/Build.meta create mode 100644 Assets/GAME/Materials/Build.meta create mode 100644 Assets/GAME/Prefabs/Dual Bed.prefab create mode 100644 Assets/GAME/Prefabs/Dual Bed.prefab.meta create mode 100644 Assets/GAME/Script/Building/Bed.cs create mode 100644 Assets/GAME/Script/Building/Bed.cs.meta create mode 100644 Assets/GAME/Textures/Build.meta delete mode 100644 Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage.meta delete mode 100644 Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage.meta delete mode 100644 Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage.meta diff --git a/Assets/GAME/3D/Build.meta b/Assets/GAME/3D/Build.meta new file mode 100644 index 00000000..528d307e --- /dev/null +++ b/Assets/GAME/3D/Build.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 286d47ba18aaede41a95ea42de5ee2aa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GAME/Materials/Build.meta b/Assets/GAME/Materials/Build.meta new file mode 100644 index 00000000..9897e428 --- /dev/null +++ b/Assets/GAME/Materials/Build.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90713256b1707c340ad52edc4c1289fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GAME/Prefabs/Dual Bed.prefab b/Assets/GAME/Prefabs/Dual Bed.prefab new file mode 100644 index 00000000..e740cca6 --- /dev/null +++ b/Assets/GAME/Prefabs/Dual Bed.prefab @@ -0,0 +1,181 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &80555091247393707 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5155531265051259965} + m_Layer: 9 + m_Name: Respanw Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5155531265051259965 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 80555091247393707} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.185} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1974791568506913495} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1410034494400494434 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1974791568506913495} + - component: {fileID: 7121555757307145449} + - component: {fileID: 8025352644449905843} + m_Layer: 9 + m_Name: Dual Bed + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1974791568506913495 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1410034494400494434} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 38.80009, y: 0, z: 37.555004} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2750452856085184630} + - {fileID: 5155531265051259965} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &7121555757307145449 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1410034494400494434} + 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: 2.1684494, y: 0.7840714, z: 1.781552} + m_Center: {x: -0.06585312, y: 0.40030995, z: 0} +--- !u!114 &8025352644449905843 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1410034494400494434} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5b64acb9b3e11a6408744a646644c073, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Ashwild.Building.Bed + respawnAnchor: {fileID: 5155531265051259965} + interactionPrompt: "D\xE9finir le point de r\xE9veil" +--- !u!1001 &2423265566855260061 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1974791568506913495} + m_Modifications: + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalRotation.x + value: 0.00000006717942 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -7511558181221131132, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: 'm_Materials.Array.data[0]' + value: + objectReference: {fileID: 2100000, guid: 123e30390bfadba49a381ecd9775b93f, type: 2} + - target: {fileID: 919132149155446097, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_Name + value: dual bed + objectReference: {fileID: 0} + - target: {fileID: 919132149155446097, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + propertyPath: m_Layer + value: 9 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} +--- !u!4 &2750452856085184630 stripped +Transform: + m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: daccda73d2db7124db470c2a2f478fcf, type: 3} + m_PrefabInstance: {fileID: 2423265566855260061} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/GAME/Prefabs/Dual Bed.prefab.meta b/Assets/GAME/Prefabs/Dual Bed.prefab.meta new file mode 100644 index 00000000..6f799dc1 --- /dev/null +++ b/Assets/GAME/Prefabs/Dual Bed.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 75709898450916748958db6a8ae2a48f +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GAME/Script/Building/Bed.cs b/Assets/GAME/Script/Building/Bed.cs new file mode 100644 index 00000000..dac84b6c --- /dev/null +++ b/Assets/GAME/Script/Building/Bed.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using Ashwild.Interaction; +using Ashwild.Player; + +namespace Ashwild.Building +{ + /// + /// A placed bed the local player interacts with to make it their respawn point (Valheim-style + /// claim). Interacting pushes the bed's pose onto the bus, where the local PlayerLifecycle adopts + /// it — so the respawn point is per-player and never networked: one bed at the base can serve as + /// everyone's spawn, yet each teammate only rebinds their own by interacting, and a bed placed + /// far away changes nobody else's. The bed itself is an ordinary built structure (instantiated + /// locally on every client from the BuildRegistry), never a NetworkObject — so there is nothing + /// to add on the build side: dropping this component on a buildable's BuiltPrefab is enough. + /// + [DisallowMultipleComponent] + [RequireComponent(typeof(Collider))] + public class Bed : MonoBehaviour, IInteractable + { + #region Serialized Fields + + [Header("Respawn")] + [Tooltip("Where the player reappears when respawning here — a child placed beside the bed, facing away from it. Falls back to the bed's own transform when left empty.")] + [SerializeField] private Transform respawnAnchor; + + [Tooltip("Label shown under the crosshair while aiming at the bed.")] + [SerializeField] private string interactionPrompt = "Définir le point de réveil"; + + #endregion + + #region IInteractable + + /// + /// Label shown under the crosshair while aiming at the bed. + /// + public string InteractionPrompt => interactionPrompt; + + /// + /// Claims this bed as the local player's respawn point by broadcasting its pose over the bus. + /// Called by PlayerInteractor on the interacting client only (it is owner-gated), so only that + /// player rebinds — teammates are untouched. + /// + public void Interact() + { + Transform anchor = respawnAnchor != null ? respawnAnchor : transform; + PlayerEvents.RaiseRespawnPointChanged(anchor.position, anchor.rotation); + } + + #endregion + } +} diff --git a/Assets/GAME/Script/Building/Bed.cs.meta b/Assets/GAME/Script/Building/Bed.cs.meta new file mode 100644 index 00000000..ffa35d89 --- /dev/null +++ b/Assets/GAME/Script/Building/Bed.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5b64acb9b3e11a6408744a646644c073 \ No newline at end of file diff --git a/Assets/GAME/Script/Player/Events/PlayerEvents.cs b/Assets/GAME/Script/Player/Events/PlayerEvents.cs index cf9794e2..9ea80dc6 100644 --- a/Assets/GAME/Script/Player/Events/PlayerEvents.cs +++ b/Assets/GAME/Script/Player/Events/PlayerEvents.cs @@ -151,6 +151,7 @@ namespace Ashwild.Player public static event Action Died; public static event Action Respawned; public static event Action DeathChanged; + public static event Action RespawnPointChanged; // the local player's respawn pose was reassigned (e.g. claimed a bed) // ============================================================ // Network / session events @@ -318,6 +319,16 @@ namespace Ashwild.Player DeathChanged?.Invoke(false); } + /// + /// Reassigns the local player's respawn pose (e.g. after claiming a bed). Owner-side only; + /// the pose is pure local state and is never networked — each client keeps its own. + /// + public static void RaiseRespawnPointChanged(Vector3 position, Quaternion rotation) + { + Log(nameof(RespawnPointChanged)); + RespawnPointChanged?.Invoke(position, rotation); + } + public static void RaiseSessionStarting() { Log(nameof(SessionStarting)); SessionStarting?.Invoke(); } public static void RaiseSessionStarted(string code) { diff --git a/Assets/GAME/Script/Player/PlayerLifecycle.cs b/Assets/GAME/Script/Player/PlayerLifecycle.cs index 06c51e81..69779bbf 100644 --- a/Assets/GAME/Script/Player/PlayerLifecycle.cs +++ b/Assets/GAME/Script/Player/PlayerLifecycle.cs @@ -2,12 +2,25 @@ using UnityEngine; namespace Ashwild.Player { + /// + /// Owns the local player's death-and-return. It flips locomotion into its dead state when the + /// player dies, and on teleports the body back to the current respawn pose, + /// revives the stats and clears the dead state. The respawn pose starts at the assigned spawn + /// point (or wherever the player begins) and is reassigned live when the player claims a bed — + /// pushed in over the bus, so it stays pure local state that never crosses the wire (§3). + /// [DisallowMultipleComponent] public class PlayerLifecycle : MonoBehaviour { + #region Serialized Fields + [Header("Spawn point (auto-captured at scene start if left empty)")] [SerializeField] private Transform spawnPoint; + #endregion + + #region State + private PlayerLocomotion locomotion; private Rigidbody rb; @@ -15,12 +28,23 @@ namespace Ashwild.Player private Quaternion spawnRotation; private bool isDead; + #endregion + + #region Unity Lifecycle + + /// + /// Caches the sibling components the respawn drives. + /// private void Awake() { locomotion = GetComponent(); rb = GetComponent(); } + /// + /// Seeds the respawn pose from the assigned spawn point, or the player's starting pose when + /// none is set, so a death before any bed is claimed still returns somewhere valid. + /// private void Start() { if (spawnPoint != null) @@ -35,9 +59,31 @@ namespace Ashwild.Player } } - private void OnEnable() { PlayerEvents.Died += OnDied; } - private void OnDisable() { PlayerEvents.Died -= OnDied; } + /// + /// Subscribes to death and to respawn-point reassignments (claiming a bed). + /// + private void OnEnable() + { + PlayerEvents.Died += OnDied; + PlayerEvents.RespawnPointChanged += HandleRespawnPointChanged; + } + /// + /// Unsubscribes — mirrors OnEnable exactly. + /// + private void OnDisable() + { + PlayerEvents.Died -= OnDied; + PlayerEvents.RespawnPointChanged -= HandleRespawnPointChanged; + } + + #endregion + + #region Event Handlers + + /// + /// Freezes the player into its dead state once, ignoring repeat death events. + /// private void OnDied() { if (isDead) return; @@ -45,6 +91,21 @@ namespace Ashwild.Player if (locomotion != null) locomotion.SetDead(true); } + /// + /// Adopts a new respawn pose pushed over the bus (the player claimed a bed). Local state + /// only — the respawn location is never networked, so each client keeps its own. + /// + private void HandleRespawnPointChanged(Vector3 position, Quaternion rotation) + => SetSpawnPoint(position, rotation); + + #endregion + + #region Public API + + /// + /// Returns the player to the current respawn pose: zeroes momentum, teleports the body, + /// revives the stats and clears the dead state. + /// public void Respawn() { if (rb != null) @@ -52,8 +113,7 @@ namespace Ashwild.Player rb.linearVelocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } - transform.position = spawnPosition; - transform.rotation = spawnRotation; + transform.SetPositionAndRotation(spawnPosition, spawnRotation); if (PlayerStats.Instance != null) PlayerStats.Instance.Revive(); if (locomotion != null) locomotion.SetDead(false); @@ -61,18 +121,15 @@ namespace Ashwild.Player isDead = false; } + /// + /// Overrides the respawn pose directly with a world position and rotation. + /// public void SetSpawnPoint(Vector3 position, Quaternion rotation) { spawnPosition = position; spawnRotation = rotation; } - public void SetSpawnPoint(Transform t) - { - if (t == null) return; - spawnPoint = t; - spawnPosition = t.position; - spawnRotation = t.rotation; - } + #endregion } } diff --git a/Assets/GAME/Textures/Build.meta b/Assets/GAME/Textures/Build.meta new file mode 100644 index 00000000..b4bc1bb6 --- /dev/null +++ b/Assets/GAME/Textures/Build.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 621b98b56bb4c1744bd3b5a2b3f5cfc1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/DefaultPrefabObjects.asset b/Assets/Resources/DefaultPrefabObjects.asset index 47f0a090..2524c985 100644 --- a/Assets/Resources/DefaultPrefabObjects.asset +++ b/Assets/Resources/DefaultPrefabObjects.asset @@ -13,13 +13,11 @@ MonoBehaviour: m_Name: DefaultPrefabObjects m_EditorClassIdentifier: FishNet.Runtime::FishNet.Managing.Object.DefaultPrefabObjects _prefabs: - - {fileID: 6514514229620551208, guid: 39b04625f47cbc24a93966c3eb0194d2, type: 3} - {fileID: 4512293259955182956, guid: fe2b65b02f0484b41aa8cfa9fbbb0e1d, type: 3} - {fileID: 4512293259955182956, guid: 35639798ad77fc145871588b25d66259, type: 3} - {fileID: 201277550, guid: 26a567abbe21227428f5c3d309d1d73c, type: 3} - {fileID: 4512293259955182956, guid: 0d6d0f48b03b17f49a6340103cd9b9d0, type: 3} - {fileID: 7847709848979142105, guid: 6a3ea20bb46e81c44ad6959bbe90e0dd, type: 3} - - {fileID: 1293470452171110175, guid: d2b6fea7c913fb844a1939788445af18, type: 3} - {fileID: 8475222101369129519, guid: 8cf33e8e99a9b0c4c8f29ff725650de6, type: 3} - {fileID: 4512293259955182956, guid: dafef736ca1ae384e9a19eb672843563, type: 3} - {fileID: 201277550, guid: 5b712878ecece354ba4ffb026c0a221c, type: 3} diff --git a/Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage.meta b/Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage.meta deleted file mode 100644 index 2d22b097..00000000 --- a/Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: 2f1b9c7f4731e2d44af6b3606190070b -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: -AssetOrigin: - serializedVersion: 1 - productId: 271742 - packageName: 'COZY: Stylized Weather 3' - packageVersion: 3.6.20 - assetPath: Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage - uploadId: 939148 diff --git a/Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage.meta b/Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage.meta deleted file mode 100644 index e52b9d6e..00000000 --- a/Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: c226d4e6697573345932a7bf39dd615a -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: -AssetOrigin: - serializedVersion: 1 - productId: 271742 - packageName: 'COZY: Stylized Weather 3' - packageVersion: 3.6.20 - assetPath: Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage - uploadId: 939148 diff --git a/Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage.meta b/Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage.meta deleted file mode 100644 index 9327ea4e..00000000 --- a/Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: 3643c0d76ec153646b1203880bfb64ed -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: -AssetOrigin: - serializedVersion: 1 - productId: 271742 - packageName: 'COZY: Stylized Weather 3' - packageVersion: 3.6.20 - assetPath: Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage - uploadId: 939148