diff --git a/.idea/.idea.HALLUCINATE/.idea/workspace.xml b/.idea/.idea.HALLUCINATE/.idea/workspace.xml
index f7666299..36a03fad 100644
--- a/.idea/.idea.HALLUCINATE/.idea/workspace.xml
+++ b/.idea/.idea.HALLUCINATE/.idea/workspace.xml
@@ -6,11 +6,12 @@
-
-
-
+
-
+
+
+
+
@@ -27,6 +28,7 @@
+
@@ -137,7 +139,8 @@
-
+
+
diff --git a/Assets/Resources/Localization.meta b/Assets/Resources/Localization.meta
new file mode 100644
index 00000000..b6bc3b60
--- /dev/null
+++ b/Assets/Resources/Localization.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 115b7971291d64d42bf41732f4d2fcb6
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/Localization/en.json b/Assets/Resources/Localization/en.json
new file mode 100644
index 00000000..8050ef78
--- /dev/null
+++ b/Assets/Resources/Localization/en.json
@@ -0,0 +1,15 @@
+{
+ "menu_create": "CREATE ROOM",
+ "menu_join": "JOIN ROOM",
+ "menu_settings": "SETTINGS",
+ "menu_exit": "EXIT",
+ "settings_title": "SETTINGS",
+ "settings_general": "GENERAL",
+ "settings_graphics": "GRAPHICS",
+ "settings_audio": "AUDIO",
+ "settings_controls": "CONTROLS",
+ "settings_back": "BACK",
+ "label_fov": "Field of View",
+ "label_sensitivity": "Sensitivity",
+ "label_language": "Language"
+}
diff --git a/Assets/Resources/Localization/en.json.meta b/Assets/Resources/Localization/en.json.meta
new file mode 100644
index 00000000..3de9f369
--- /dev/null
+++ b/Assets/Resources/Localization/en.json.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: d949fd6576700b54eb12847a360f99cd
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/Localization/vi.json b/Assets/Resources/Localization/vi.json
new file mode 100644
index 00000000..a20485d2
--- /dev/null
+++ b/Assets/Resources/Localization/vi.json
@@ -0,0 +1,15 @@
+{
+ "menu_create": "TẠO PHÒNG",
+ "menu_join": "VÀO PHÒNG",
+ "menu_settings": "CÀI ĐẶT",
+ "menu_exit": "THOÁT",
+ "settings_title": "CÀI ĐẶT",
+ "settings_general": "CHUNG",
+ "settings_graphics": "ĐỒ HỌA",
+ "settings_audio": "ÂM THANH",
+ "settings_controls": "ĐIỀU KHIỂN",
+ "settings_back": "QUAY LẠI",
+ "label_fov": "Tầm nhìn (FOV)",
+ "label_sensitivity": "Độ nhạy chuột",
+ "label_language": "Ngôn ngữ"
+}
diff --git a/Assets/Resources/Localization/vi.json.meta b/Assets/Resources/Localization/vi.json.meta
new file mode 100644
index 00000000..4d26e944
--- /dev/null
+++ b/Assets/Resources/Localization/vi.json.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 5f5574ecd78b063488d5a0a2609bf48a
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scove/UIScaleTest.unity b/Assets/Scove/UIScaleTest.unity
index 8a88abbb..a750c7ac 100644
--- a/Assets/Scove/UIScaleTest.unity
+++ b/Assets/Scove/UIScaleTest.unity
@@ -256,6 +256,7 @@ GameObject:
m_Component:
- component: {fileID: 666657093}
- component: {fileID: 666657092}
+ - component: {fileID: 666657094}
m_Layer: 0
m_Name: Doc_Profile
m_TagString: Untagged
@@ -301,6 +302,18 @@ Transform:
m_Children: []
m_Father: {fileID: 1183887570}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &666657094
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 666657091}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: fdea16b110511ef45889ed832b63560b, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::UI.ProfileController
--- !u!1 &1136953558
GameObject:
m_ObjectHideFlags: 0
@@ -311,6 +324,7 @@ GameObject:
m_Component:
- component: {fileID: 1136953560}
- component: {fileID: 1136953559}
+ - component: {fileID: 1136953561}
m_Layer: 0
m_Name: Doc_HUD
m_TagString: Untagged
@@ -356,6 +370,19 @@ Transform:
m_Children: []
m_Father: {fileID: 1183887570}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1136953561
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1136953558}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: e79b70607af6eeb458c8eb6605e39b56, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::UI.HUDController
+ hudDocument: {fileID: 1136953559}
--- !u!1 &1183887568
GameObject:
m_ObjectHideFlags: 0
@@ -382,26 +409,36 @@ MonoBehaviour:
m_GameObject: {fileID: 1183887568}
m_Enabled: 1
m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 3f728362556756d45bddb65280fdab1d, type: 3}
+ m_Script: {fileID: 11500000, guid: bcb7b8ed439bb4546b0648c627c2ce5d, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::UI.UIManager
screens:
- screenName: Doc_MainMenu
document: {fileID: 2003742651}
isActive: 0
+ isOverlay: 0
+ customCursor: {fileID: 0}
- screenName: Doc_Lobby
document: {fileID: 1471116802}
isActive: 0
+ isOverlay: 0
+ customCursor: {fileID: 0}
- screenName: Doc_HUD
document: {fileID: 1136953559}
isActive: 0
+ isOverlay: 0
+ customCursor: {fileID: 0}
- screenName: Doc_Settings
document: {fileID: 1582124357}
isActive: 0
+ isOverlay: 0
+ customCursor: {fileID: 0}
- screenName: Doc_Profile
document: {fileID: 666657092}
- isActive: 0
- globalOpacity: 1
+ isActive: 1
+ isOverlay: 0
+ customCursor: {fileID: 0}
+ defaultCursor: {fileID: 0}
--- !u!4 &1183887570
Transform:
m_ObjectHideFlags: 0
@@ -432,6 +469,7 @@ GameObject:
m_Component:
- component: {fileID: 1471116803}
- component: {fileID: 1471116802}
+ - component: {fileID: 1471116804}
m_Layer: 0
m_Name: Doc_Lobby
m_TagString: Untagged
@@ -477,6 +515,18 @@ Transform:
m_Children: []
m_Father: {fileID: 1183887570}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1471116804
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1471116801}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 9c37c552a9c18a242bcc8860a0a5212f, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::UI.LobbyController
--- !u!1 &1582124356
GameObject:
m_ObjectHideFlags: 0
@@ -487,6 +537,7 @@ GameObject:
m_Component:
- component: {fileID: 1582124358}
- component: {fileID: 1582124357}
+ - component: {fileID: 1582124359}
m_Layer: 0
m_Name: Doc_Settings
m_TagString: Untagged
@@ -532,6 +583,18 @@ Transform:
m_Children: []
m_Father: {fileID: 1183887570}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1582124359
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1582124356}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 5534bcf4869df944883c6fd2a17a6a5a, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::UI.SettingsController
--- !u!1 &1848374378
GameObject:
m_ObjectHideFlags: 0
@@ -679,6 +742,7 @@ GameObject:
m_Component:
- component: {fileID: 2003742650}
- component: {fileID: 2003742651}
+ - component: {fileID: 2003742652}
m_Layer: 0
m_Name: Doc_MainMenu
m_TagString: Untagged
@@ -724,6 +788,18 @@ MonoBehaviour:
m_PivotReferenceSize: 0
m_Pivot: 0
m_WorldSpaceCollider: {fileID: 0}
+--- !u!114 &2003742652
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2003742649}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 691980524acfc544f9660cfc35ce3616, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::UI.MainMenuController
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
diff --git a/Assets/Scripts/Player Controller/PlayerStateMachine.cs b/Assets/Scripts/Player Controller/PlayerStateMachine.cs
index ccac042f..3e302b04 100644
--- a/Assets/Scripts/Player Controller/PlayerStateMachine.cs
+++ b/Assets/Scripts/Player Controller/PlayerStateMachine.cs
@@ -47,36 +47,15 @@ namespace OnlyScove.Scripts
[field: SerializeField] public LayerMask InteractionMask { get; private set; }
[Networked] public Quaternion NetworkedCameraRotation { get; set; }
-
- public Quaternion CameraRotation
- {
- get
- {
- if (Runner != null && Runner.IsRunning && Object != null)
- return NetworkedCameraRotation;
-
- if (Cam != null)
- return Cam.PlanarRotation;
-
- return transform.rotation;
- }
- }
-
[Networked] public Vector2 NetworkedMoveInput { get; set; }
[Networked] public float NetworkedSpeed { get; set; }
[Networked] public Vector3 NetworkedPosition { get; set; }
[Header("Player Stats")]
- [Networked, OnChangedRender(nameof(OnHealthChangedRender))]
- public float Health { get; set; } = 100f;
+ [Networked, OnChangedRender(nameof(OnHealthChangedRender))] public float Health { get; set; } = 100f;
+ [Networked, OnChangedRender(nameof(OnStaminaChangedRender))] public float Stamina { get; set; } = 100f;
+ [Networked, OnChangedRender(nameof(OnNoiseLevelChangedRender))] public float NoiseLevel { get; set; } = 0f;
- [Networked, OnChangedRender(nameof(OnStaminaChangedRender))]
- public float Stamina { get; set; } = 100f;
-
- [Networked, OnChangedRender(nameof(OnNoiseLevelChangedRender))]
- public float NoiseLevel { get; set; } = 0f;
-
- // Sự kiện để UI lắng nghe
public event System.Action OnHealthChanged;
public event System.Action OnStaminaChanged;
public event System.Action OnNoiseLevelChanged;
@@ -87,19 +66,26 @@ namespace OnlyScove.Scripts
public float VelocityY { get; set; }
public bool IsGrounded { get; private set; }
public bool WasGrounded { get; private set; }
-
- private List interactablesNearby = new List();
- private int currentInteractableIndex = 0;
-
public string CurrentStateName => currentState != null ? currentState.GetType().Name : "None";
-
public static PlayerStateMachine Local { get; private set; }
+
+ public Quaternion CameraRotation
+ {
+ get
+ {
+ if (Runner != null && Runner.IsRunning && Object != null) return NetworkedCameraRotation;
+ return Cam != null ? Cam.PlanarRotation : transform.rotation;
+ }
+ }
private PlayerBaseState currentState;
private bool hasControl = true;
private bool hasSpeedParam;
private bool hasVelocityXParam;
private bool hasVelocityZParam;
+ private List interactablesNearby = new List();
+ private int currentInteractableIndex = 0;
+ private float localAnimatorSpeed;
protected virtual void Awake()
{
@@ -125,41 +111,30 @@ namespace OnlyScove.Scripts
private void Start()
{
- if (Runner == null || !Runner.IsRunning)
- {
- InitializePlayer();
- }
+ if (Runner == null || !Runner.IsRunning) InitializePlayer();
}
public override void Spawned()
{
InitializePlayer();
-
if (Object != null && !Object.HasInputAuthority && Runner.IsClient)
{
if (Controller != null) Controller.enabled = false;
}
}
- // Callbacks từ attribute OnChangedRender
void OnHealthChangedRender() => OnHealthChanged?.Invoke(Health);
void OnStaminaChangedRender() => OnStaminaChanged?.Invoke(Stamina);
void OnNoiseLevelChangedRender() => OnNoiseLevelChanged?.Invoke(NoiseLevel);
private void InitializePlayer()
{
- if (currentState == null)
- {
- SwitchState(new PlayerIdleState(this));
- }
+ if (currentState == null) SwitchState(new PlayerIdleState(this));
bool isOffline = Runner == null || !Runner.IsRunning;
- bool hasAuthority = Object != null && Object.HasInputAuthority;
-
- if (isOffline || hasAuthority)
+ if (isOffline || (Object != null && Object.HasInputAuthority))
{
Local = this;
-
CameraController cameraController = GameObject.FindAnyObjectByType();
if (cameraController != null)
{
@@ -167,26 +142,17 @@ namespace OnlyScove.Scripts
Cam.followTarget = transform;
Cam.inputReader = Input;
}
-
Input.OnNextInteractEvent += OnNextInteract;
Input.OnPreviousInteractEvent += OnPreviousInteract;
-
if (Controller != null) Controller.enabled = true;
}
}
- private float localAnimatorSpeed;
-
public void Rotate(Vector3 moveDirection, float deltaTime)
{
if (moveDirection == Vector3.zero) return;
-
Quaternion targetRot = Quaternion.LookRotation(moveDirection);
- transform.rotation = Quaternion.RotateTowards(
- transform.rotation,
- targetRot,
- RotationSpeed * deltaTime
- );
+ transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRot, RotationSpeed * deltaTime);
}
public void Move(Vector3 velocity, float animatorSpeed, float deltaTime)
@@ -197,40 +163,23 @@ namespace OnlyScove.Scripts
if (Controller != null && Controller.enabled)
{
Controller.Move(velocity * deltaTime);
- if (Object != null && Runner != null && Runner.IsRunning)
- {
- NetworkedPosition = transform.position;
- }
+ if (Object != null && Runner != null && Runner.IsRunning) NetworkedPosition = transform.position;
}
localAnimatorSpeed = animatorSpeed;
-
if (Object != null && Object.HasStateAuthority)
{
NetworkedSpeed = animatorSpeed;
NetworkedMoveInput = MoveInput;
}
-
UpdateAnimator(deltaTime);
}
private void UpdateAnimator(float deltaTime)
{
if (Anim == null) return;
-
- float speedValue;
- Vector2 inputVector;
-
- if (Runner == null || !Runner.IsRunning || Object.HasInputAuthority)
- {
- speedValue = localAnimatorSpeed;
- inputVector = MoveInput;
- }
- else
- {
- speedValue = NetworkedSpeed;
- inputVector = NetworkedMoveInput;
- }
+ float speedValue = (Runner == null || !Runner.IsRunning || Object.HasInputAuthority) ? localAnimatorSpeed : NetworkedSpeed;
+ Vector2 inputVector = (Runner == null || !Runner.IsRunning || Object.HasInputAuthority) ? MoveInput : NetworkedMoveInput;
if (hasSpeedParam) Anim.SetFloat(speedHash, speedValue, AnimationDamping, deltaTime);
if (hasVelocityXParam) Anim.SetFloat(velocityXHash, inputVector.x * speedValue, AnimationDamping, deltaTime);
@@ -242,14 +191,11 @@ namespace OnlyScove.Scripts
bool isRunning = Runner != null && Runner.IsRunning;
if (Object == null && isRunning) return;
- if (isRunning && NetworkedPosition != Vector3.zero)
+ if (isRunning && NetworkedPosition != Vector3.zero && !Object.HasInputAuthority)
{
- if (Controller != null && !Object.HasInputAuthority)
- {
- Controller.enabled = false;
- transform.position = NetworkedPosition;
- Controller.enabled = true;
- }
+ Controller.enabled = false;
+ transform.position = NetworkedPosition;
+ Controller.enabled = true;
}
if (GetInput(out PlayerInputData data))
@@ -269,52 +215,35 @@ namespace OnlyScove.Scripts
IsSprintHeld = false;
}
- bool isSimulating = !isRunning || Object.HasInputAuthority || Runner.IsServer;
-
- if (!isSimulating)
+ if (!isRunning || Object.HasInputAuthority || Runner.IsServer)
+ {
+ if (hasControl)
+ {
+ WasGrounded = IsGrounded;
+ CheckGround();
+ UpdateInteractablesList();
+ currentState?.Tick(isRunning ? Runner.DeltaTime : Time.fixedDeltaTime);
+ }
+ }
+ else
{
UpdateAnimator(Runner.DeltaTime);
- return;
}
-
- if (!hasControl) return;
-
- WasGrounded = IsGrounded;
- CheckGround();
- UpdateInteractablesList();
-
- float dt = isRunning ? Runner.DeltaTime : Time.fixedDeltaTime;
- currentState?.Tick(dt);
}
private void Update()
{
- if (Runner == null || !Runner.IsRunning)
- {
- FixedUpdateNetwork();
- }
+ if (Runner == null || !Runner.IsRunning) FixedUpdateNetwork();
}
- private void CheckGround()
- {
- IsGrounded = Physics.CheckSphere(transform.TransformPoint(GroundCheckOffset), GroundCheckRadius, GroundMask);
- }
+ private void CheckGround() => IsGrounded = Physics.CheckSphere(transform.TransformPoint(GroundCheckOffset), GroundCheckRadius, GroundMask);
private void UpdateInteractablesList()
{
interactablesNearby.Clear();
IInteractable target = Scanner.ScanForInteractable(InteractionRange, InteractionMask);
-
- if (target != null)
- {
- interactablesNearby.Add(target);
- OnInteractableTargetChanged?.Invoke(target);
- }
- else
- {
- OnInteractableTargetChanged?.Invoke(null);
- }
-
+ if (target != null) interactablesNearby.Add(target);
+ OnInteractableTargetChanged?.Invoke(target);
currentInteractableIndex = 0;
}
@@ -328,22 +257,13 @@ namespace OnlyScove.Scripts
private void OnPreviousInteract()
{
if (interactablesNearby.Count <= 1) return;
- currentInteractableIndex--;
- if (currentInteractableIndex < 0) currentInteractableIndex = interactablesNearby.Count - 1;
+ currentInteractableIndex = (currentInteractableIndex - 1 + interactablesNearby.Count) % interactablesNearby.Count;
OnInteractableTargetChanged?.Invoke(GetInteractable());
}
- public IInteractable GetInteractable()
- {
- if (interactablesNearby.Count == 0) return null;
- return interactablesNearby[currentInteractableIndex];
- }
+ public IInteractable GetInteractable() => interactablesNearby.Count == 0 ? null : interactablesNearby[currentInteractableIndex];
- public void SetGroundCheck(float radius, Vector3 offset)
- {
- GroundCheckRadius = radius;
- GroundCheckOffset = offset;
- }
+ public void SetGroundCheck(float radius, Vector3 offset) { GroundCheckRadius = radius; GroundCheckOffset = offset; }
public void SwitchState(PlayerBaseState newState)
{
diff --git a/Assets/Scripts/UI/HUDController.cs b/Assets/Scripts/UI/HUDController.cs
index 1ba21f86..f9d7937f 100644
--- a/Assets/Scripts/UI/HUDController.cs
+++ b/Assets/Scripts/UI/HUDController.cs
@@ -23,7 +23,6 @@ namespace UI
var root = hudDocument.rootVisualElement;
- // Tìm các thành phần UI theo Name (Bạn cần đặt tên này trong UXML)
_healthFill = root.Q("health-fill");
_staminaFill = root.Q("stamina-fill");
_healthText = root.Q