diff --git a/Assets/01_Scenes/WhaleAdventure_VR/Rooms/BaseRoom.unity b/Assets/01_Scenes/WhaleAdventure_VR/Rooms/BaseRoom.unity index 3c6c0f70..7fd1b961 100644 --- a/Assets/01_Scenes/WhaleAdventure_VR/Rooms/BaseRoom.unity +++ b/Assets/01_Scenes/WhaleAdventure_VR/Rooms/BaseRoom.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d91961b345730018d138f13c1e145d34fe959cd77205c70269b5464f4a264257 -size 1836734 +oid sha256:df3509989e10bd6c0d42f720cbe4d0c57950775d56bf8a107893aaa1eeaa6f32 +size 1907482 diff --git a/Assets/02_Scripts/ISceneInitializable.cs b/Assets/02_Scripts/ISceneInitializable.cs new file mode 100644 index 00000000..c8949dc4 --- /dev/null +++ b/Assets/02_Scripts/ISceneInitializable.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public interface ISceneInitializable +{ + public void OnSceneLoaded(); +} \ No newline at end of file diff --git a/Assets/02_Scripts/ISceneInitializable.cs.meta b/Assets/02_Scripts/ISceneInitializable.cs.meta new file mode 100644 index 00000000..74a4a530 --- /dev/null +++ b/Assets/02_Scripts/ISceneInitializable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bcdbb0f5d9b20b248a68735a72da71e4 \ No newline at end of file diff --git a/Assets/02_Scripts/Managers.meta b/Assets/02_Scripts/Managers.meta new file mode 100644 index 00000000..d112baef --- /dev/null +++ b/Assets/02_Scripts/Managers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed45df9bef7ca3c41876538192c8458d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/02_Scripts/Managers/GameManager.cs b/Assets/02_Scripts/Managers/GameManager.cs new file mode 100644 index 00000000..bab52aa9 --- /dev/null +++ b/Assets/02_Scripts/Managers/GameManager.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class GameManager : MonoBehaviour,ISceneInitializable +{ + public static GameManager Instance; + + private void Awake() + { + if (Instance == null) + { + Instance = this; //만들어진 자신을 인스턴스로 설정 + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴 + } + } + + public void OnSceneLoaded() + { + + } +} \ No newline at end of file diff --git a/Assets/02_Scripts/Managers/GameManager.cs.meta b/Assets/02_Scripts/Managers/GameManager.cs.meta new file mode 100644 index 00000000..ad5127c7 --- /dev/null +++ b/Assets/02_Scripts/Managers/GameManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 80bc92795d0805849afa6755063fb9d5 \ No newline at end of file diff --git a/Assets/02_Scripts/Managers/InputManager.cs b/Assets/02_Scripts/Managers/InputManager.cs new file mode 100644 index 00000000..62ab7b2e --- /dev/null +++ b/Assets/02_Scripts/Managers/InputManager.cs @@ -0,0 +1,42 @@ +using System; +using UnityEngine; +using UnityEngine.InputSystem; + +public class InputManager : MonoBehaviour, GameInput.IPlayerActions +{ + // 외부에서 InputManager.Instance.OnXxx_Event += handler 형태로 구독. + public static InputManager Instance { get; private set; } + + private GameInput _input; + + // ─── 입력 이벤트들 (PlayerController 등이 구독) ────────────────────── + public event Action OnJump_Event; // 한 번씩 (눌렀을 때) + + private void Awake() + { + if (Instance == null) + { + Instance = this; //만들어진 자신을 인스턴스로 설정 + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴 + } + + _input = new GameInput(); + // IPlayerActions의 OnJump/... 메서드를 인풋 액션의 콜백으로 자동 연결. + _input.Player.SetCallbacks(this); + } + + // GameInput은 활성/비활성 토글이 필요한 자원 ?. 처리로 Awake보다 OnEnable이 먼저 호출되는 경우 보호. + private void OnEnable() => _input?.Player.Enable(); + private void OnDisable() => _input?.Player.Disable(); + private void OnDestroy() => _input?.Dispose(); + + public void OnJump(InputAction.CallbackContext ctx) + { + if (ctx.phase == InputActionPhase.Started) + OnJump_Event?.Invoke(); + } +} diff --git a/Assets/02_Scripts/Managers/InputManager.cs.meta b/Assets/02_Scripts/Managers/InputManager.cs.meta new file mode 100644 index 00000000..ba09cf87 --- /dev/null +++ b/Assets/02_Scripts/Managers/InputManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4d8ea6a700fa8a44a9fc25c4aa211098 \ No newline at end of file diff --git a/Assets/02_Scripts/Managers/SceneLoadManager.cs b/Assets/02_Scripts/Managers/SceneLoadManager.cs new file mode 100644 index 00000000..055c7dba --- /dev/null +++ b/Assets/02_Scripts/Managers/SceneLoadManager.cs @@ -0,0 +1,120 @@ +using System; +using UnityEngine; +using UnityEngine.SceneManagement; +public class SceneLoadManager : MonoBehaviour +{ + public static SceneLoadManager Instance; + + [SerializeField] private GameObject _loadingRoot; + [SerializeField] private Camera _loadingCam; + [SerializeField] private Transform _loadingCamTargetTransform; + + private void Awake() + { + if (Instance == null) + { + Instance = this; //만들어진 자신을 인스턴스로 설정 + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴 + } + } + + private void Start() + { + SceneManager.sceneLoaded += OnSceneLoaded; + OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single); + } + + private void Update() + { + if(_loadingCamTargetTransform != null) + { + _loadingRoot.transform.position = _loadingCamTargetTransform.position; + } + } + + //씬이 로드되었을때 호출 + private void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + MonoBehaviour[] allObjs = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None); + + foreach (var obj in allObjs) + { + if (obj is ISceneInitializable initializable) + { + //씬에서 ISceneInitializable 인터페이스를 가진 오브젝트의 초기화 로직을 실행 + initializable.OnSceneLoaded(); + } + } + } + + public void SetSceneLoadingProgressValue(float value) + { + + } + + public void RequestSceneChange(string sceneName) + { + _ = SceneChange(sceneName); + } + + private async Awaitable SceneChange(string sceneName) + { + try + { + //로딩바 수치 0으로 설정 + SetSceneLoadingProgressValue(0f); + + AsyncOperation op = SceneManager.LoadSceneAsync(sceneName); + + //자동 전환을 하고 싶지 않을 경우 해당값을 false로 두었다가 true로 바꾸면 그 때 전환됨 + op.allowSceneActivation = false; + + //화면에 보여줄 로딩 수치 + float displayProgress = 0f; + + //op.progress 0.9가 데이터 로딩이 끝난 기준 allowSceneActivation이 트루면 다음으로 넘어가면서 op.isDone이 true가 된다. + while (op.progress < 0.9f) + { + //실제 로딩 수치 + float realProgress = Mathf.Clamp01(op.progress / 0.9f); + + //보여줄 값을 실제값을 향해 부드럽게 이동 + displayProgress = Mathf.MoveTowards(displayProgress, realProgress, Time.deltaTime * 0.5f); + + // 로딩바 UI에 값 적용 + SetSceneLoadingProgressValue(displayProgress); + + //자기자신이 파괴될때 토큰에 취소요청을 보냄 + await Awaitable.NextFrameAsync(this.destroyCancellationToken); + } + + //로딩바 수치 1(100%)로 설정 (데이터 로딩은 이미 끝이기 때문에) + SetSceneLoadingProgressValue(1); + + // 잠시 대기했다가 전환 + await Awaitable.WaitForSecondsAsync(1.0f, this.destroyCancellationToken); + + // 다음씬으로 넘어가도 됨을 알림 + op.allowSceneActivation = true; + + // 씬 활성화가 완전히 끝날 때까지 대기 + // allowSceneActivation가 true가 되고 완전히 전환되기까지는 몇프레임 걸림. op.isDone 은 이 과정이 끝난 뒤에 true가 됨. + while(!op.isDone) + { + await Awaitable.NextFrameAsync(this.destroyCancellationToken); + } + + //VR용 로직 + //트래킹이 중단되면 안되기 때문에 카메라를 유지해야 한다 + _loadingCamTargetTransform = Camera.main.transform; // 새로운 씬의 메인카메라를 따라가게끔 설정 + } + catch (OperationCanceledException) + { + Debug.Log("씬 전환 작업이 취소됨"); + } + } +} \ No newline at end of file diff --git a/Assets/02_Scripts/Managers/SceneLoadManager.cs.meta b/Assets/02_Scripts/Managers/SceneLoadManager.cs.meta new file mode 100644 index 00000000..60fba904 --- /dev/null +++ b/Assets/02_Scripts/Managers/SceneLoadManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 01c67a0d5e5e96240a6b1f1c8e34e749 \ No newline at end of file diff --git a/Assets/02_Scripts/Player.meta b/Assets/02_Scripts/Player.meta new file mode 100644 index 00000000..05b826a4 --- /dev/null +++ b/Assets/02_Scripts/Player.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d33246055dff62479d621abdd5e4066 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/02_Scripts/Player/PlayerController.cs b/Assets/02_Scripts/Player/PlayerController.cs new file mode 100644 index 00000000..f3312f2f --- /dev/null +++ b/Assets/02_Scripts/Player/PlayerController.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerController : MonoBehaviour,ISceneInitializable +{ + public void OnSceneLoaded() + { + InputManager.Instance.OnJump_Event += this.OnJump; + } + + public void OnJump() + { + + } +} \ No newline at end of file diff --git a/Assets/02_Scripts/Player/PlayerController.cs.meta b/Assets/02_Scripts/Player/PlayerController.cs.meta new file mode 100644 index 00000000..48214fe2 --- /dev/null +++ b/Assets/02_Scripts/Player/PlayerController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2a803a0dad9eb494a89b1befc37bbdff \ No newline at end of file diff --git a/Assets/99_Settings/Input.meta b/Assets/99_Settings/Input.meta new file mode 100644 index 00000000..194fa7d9 --- /dev/null +++ b/Assets/99_Settings/Input.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0aeb8722199f1b14899ca0c8008e7e5d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/99_Settings/Input/GameInput.cs b/Assets/99_Settings/Input/GameInput.cs new file mode 100644 index 00000000..de2e319d --- /dev/null +++ b/Assets/99_Settings/Input/GameInput.cs @@ -0,0 +1,312 @@ +//------------------------------------------------------------------------------ +// +// This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator +// version 1.17.0 +// from Assets/99_Settings/Input/GameInput.inputactions +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Utilities; + +/// +/// Provides programmatic access to , , and instances defined in asset "Assets/99_Settings/Input/GameInput.inputactions". +/// +/// +/// This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified. +/// +/// +/// +/// using namespace UnityEngine; +/// using UnityEngine.InputSystem; +/// +/// // Example of using an InputActionMap named "Player" from a UnityEngine.MonoBehaviour implementing callback interface. +/// public class Example : MonoBehaviour, MyActions.IPlayerActions +/// { +/// private MyActions_Actions m_Actions; // Source code representation of asset. +/// private MyActions_Actions.PlayerActions m_Player; // Source code representation of action map. +/// +/// void Awake() +/// { +/// m_Actions = new MyActions_Actions(); // Create asset object. +/// m_Player = m_Actions.Player; // Extract action map object. +/// m_Player.AddCallbacks(this); // Register callback interface IPlayerActions. +/// } +/// +/// void OnDestroy() +/// { +/// m_Actions.Dispose(); // Destroy asset object. +/// } +/// +/// void OnEnable() +/// { +/// m_Player.Enable(); // Enable all actions within map. +/// } +/// +/// void OnDisable() +/// { +/// m_Player.Disable(); // Disable all actions within map. +/// } +/// +/// #region Interface implementation of MyActions.IPlayerActions +/// +/// // Invoked when "Move" action is either started, performed or canceled. +/// public void OnMove(InputAction.CallbackContext context) +/// { +/// Debug.Log($"OnMove: {context.ReadValue<Vector2>()}"); +/// } +/// +/// // Invoked when "Attack" action is either started, performed or canceled. +/// public void OnAttack(InputAction.CallbackContext context) +/// { +/// Debug.Log($"OnAttack: {context.ReadValue<float>()}"); +/// } +/// +/// #endregion +/// } +/// +/// +public partial class @GameInput: IInputActionCollection2, IDisposable +{ + /// + /// Provides access to the underlying asset instance. + /// + public InputActionAsset asset { get; } + + /// + /// Constructs a new instance. + /// + public @GameInput() + { + asset = InputActionAsset.FromJson(@"{ + ""version"": 1, + ""name"": ""GameInput"", + ""maps"": [ + { + ""name"": ""Player"", + ""id"": ""5d026a6e-8169-45f1-bc0c-240db1a29d82"", + ""actions"": [ + { + ""name"": ""Jump"", + ""type"": ""Button"", + ""id"": ""546a2fae-0afa-4133-8c4a-aa15ff66e23d"", + ""expectedControlType"": """", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false + } + ], + ""bindings"": [ + { + ""name"": """", + ""id"": ""5bb26581-2c13-4476-bc62-503239d4d151"", + ""path"": ""{RightHand}/{PrimaryButton}"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Jump"", + ""isComposite"": false, + ""isPartOfComposite"": false + } + ] + } + ], + ""controlSchemes"": [] +}"); + // Player + m_Player = asset.FindActionMap("Player", throwIfNotFound: true); + m_Player_Jump = m_Player.FindAction("Jump", throwIfNotFound: true); + } + + ~@GameInput() + { + UnityEngine.Debug.Assert(!m_Player.enabled, "This will cause a leak and performance issues, GameInput.Player.Disable() has not been called."); + } + + /// + /// Destroys this asset and all associated instances. + /// + public void Dispose() + { + UnityEngine.Object.Destroy(asset); + } + + /// + public InputBinding? bindingMask + { + get => asset.bindingMask; + set => asset.bindingMask = value; + } + + /// + public ReadOnlyArray? devices + { + get => asset.devices; + set => asset.devices = value; + } + + /// + public ReadOnlyArray controlSchemes => asset.controlSchemes; + + /// + public bool Contains(InputAction action) + { + return asset.Contains(action); + } + + /// + public IEnumerator GetEnumerator() + { + return asset.GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + public void Enable() + { + asset.Enable(); + } + + /// + public void Disable() + { + asset.Disable(); + } + + /// + public IEnumerable bindings => asset.bindings; + + /// + public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) + { + return asset.FindAction(actionNameOrId, throwIfNotFound); + } + + /// + public int FindBinding(InputBinding bindingMask, out InputAction action) + { + return asset.FindBinding(bindingMask, out action); + } + + // Player + private readonly InputActionMap m_Player; + private List m_PlayerActionsCallbackInterfaces = new List(); + private readonly InputAction m_Player_Jump; + /// + /// Provides access to input actions defined in input action map "Player". + /// + public struct PlayerActions + { + private @GameInput m_Wrapper; + + /// + /// Construct a new instance of the input action map wrapper class. + /// + public PlayerActions(@GameInput wrapper) { m_Wrapper = wrapper; } + /// + /// Provides access to the underlying input action "Player/Jump". + /// + public InputAction @Jump => m_Wrapper.m_Player_Jump; + /// + /// Provides access to the underlying input action map instance. + /// + public InputActionMap Get() { return m_Wrapper.m_Player; } + /// + public void Enable() { Get().Enable(); } + /// + public void Disable() { Get().Disable(); } + /// + public bool enabled => Get().enabled; + /// + /// Implicitly converts an to an instance. + /// + public static implicit operator InputActionMap(PlayerActions set) { return set.Get(); } + /// + /// Adds , and callbacks provided via on all input actions contained in this map. + /// + /// Callback instance. + /// + /// If is null or have already been added this method does nothing. + /// + /// + public void AddCallbacks(IPlayerActions instance) + { + if (instance == null || m_Wrapper.m_PlayerActionsCallbackInterfaces.Contains(instance)) return; + m_Wrapper.m_PlayerActionsCallbackInterfaces.Add(instance); + @Jump.started += instance.OnJump; + @Jump.performed += instance.OnJump; + @Jump.canceled += instance.OnJump; + } + + /// + /// Removes , and callbacks provided via on all input actions contained in this map. + /// + /// + /// Calling this method when have not previously been registered has no side-effects. + /// + /// + private void UnregisterCallbacks(IPlayerActions instance) + { + @Jump.started -= instance.OnJump; + @Jump.performed -= instance.OnJump; + @Jump.canceled -= instance.OnJump; + } + + /// + /// Unregisters and unregisters all input action callbacks via . + /// + /// + public void RemoveCallbacks(IPlayerActions instance) + { + if (m_Wrapper.m_PlayerActionsCallbackInterfaces.Remove(instance)) + UnregisterCallbacks(instance); + } + + /// + /// Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via . + /// + /// + /// If is null, calling this method will only unregister all existing callbacks but not register any new callbacks. + /// + /// + /// + /// + public void SetCallbacks(IPlayerActions instance) + { + foreach (var item in m_Wrapper.m_PlayerActionsCallbackInterfaces) + UnregisterCallbacks(item); + m_Wrapper.m_PlayerActionsCallbackInterfaces.Clear(); + AddCallbacks(instance); + } + } + /// + /// Provides a new instance referencing this action map. + /// + public PlayerActions @Player => new PlayerActions(this); + /// + /// Interface to implement callback methods for all input action callbacks associated with input actions defined by "Player" which allows adding and removing callbacks. + /// + /// + /// + public interface IPlayerActions + { + /// + /// Method invoked when associated input action "Jump" is either , or . + /// + /// + /// + /// + void OnJump(InputAction.CallbackContext context); + } +} diff --git a/Assets/99_Settings/Input/GameInput.cs.meta b/Assets/99_Settings/Input/GameInput.cs.meta new file mode 100644 index 00000000..7ed9756c --- /dev/null +++ b/Assets/99_Settings/Input/GameInput.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 34b0d0d41528a3244b8ce12d0b8df0db \ No newline at end of file diff --git a/Assets/99_Settings/Input/GameInput.inputactions b/Assets/99_Settings/Input/GameInput.inputactions new file mode 100644 index 00000000..014e3192 --- /dev/null +++ b/Assets/99_Settings/Input/GameInput.inputactions @@ -0,0 +1,35 @@ +{ + "version": 1, + "name": "GameInput", + "maps": [ + { + "name": "Player", + "id": "5d026a6e-8169-45f1-bc0c-240db1a29d82", + "actions": [ + { + "name": "Jump", + "type": "Button", + "id": "546a2fae-0afa-4133-8c4a-aa15ff66e23d", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false + } + ], + "bindings": [ + { + "name": "", + "id": "5bb26581-2c13-4476-bc62-503239d4d151", + "path": "{RightHand}/{PrimaryButton}", + "interactions": "", + "processors": "", + "groups": "", + "action": "Jump", + "isComposite": false, + "isPartOfComposite": false + } + ] + } + ], + "controlSchemes": [] +} \ No newline at end of file diff --git a/Assets/99_Settings/Input/GameInput.inputactions.meta b/Assets/99_Settings/Input/GameInput.inputactions.meta new file mode 100644 index 00000000..6d63aa76 --- /dev/null +++ b/Assets/99_Settings/Input/GameInput.inputactions.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 97db30ac5807bfa40be4e32b71f0abf3 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3} + generateWrapperCode: 1 + wrapperCodePath: + wrapperClassName: + wrapperCodeNamespace: diff --git a/Assets/Stylized Water 3/_Demo/DemoAssets/Terrain/SW3 Demo Island.asset b/Assets/Stylized Water 3/_Demo/DemoAssets/Terrain/SW3 Demo Island.asset index ba19f765..d28827e2 100644 --- a/Assets/Stylized Water 3/_Demo/DemoAssets/Terrain/SW3 Demo Island.asset +++ b/Assets/Stylized Water 3/_Demo/DemoAssets/Terrain/SW3 Demo Island.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e10e7718f4eb6bd89ec437aac2a30f6febc4663aec1387afdbcd3a7795a1648 +oid sha256:f43446fd5eebb49408047041da04710c4f9e043a8183eb752ee2d3efd27b3889 size 5581260 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index bf25a7af..c8e88b34 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c0034159550ff7726dfb45cceefdc5bfd61349c6504d81a6aaf3de6e90c70c1 +oid sha256:5adc987c1ef8f9f019bebc7114317f821c1c7d54c4e4ca88cd9505309309993d size 1156