This commit is contained in:
2026-06-04 23:01:39 +07:00
parent 45d3fe8c21
commit 67910bf6c8
68 changed files with 5978 additions and 404 deletions

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI; // Cần thiết để dùng NavMesh
using Hallucinate.Audio;
[RequireComponent(typeof(NavMeshAgent))] // Tự động thêm component này nếu chưa có
public class EnemyAI : MonoBehaviour
@@ -28,6 +29,11 @@ public class EnemyAI : MonoBehaviour
public float minShootDelay = 1f;
public float maxShootDelay = 3f;
[Header("Audio")]
public string alertSound = "Enemy_Alert";
public string shootSound = "Enemy_Shoot";
private bool hasSpottedPlayer; // Để chỉ kêu alert 1 lần
private float nextShootTime;
private NavMeshAgent agent;
@@ -37,10 +43,10 @@ public class EnemyAI : MonoBehaviour
{
agent = GetComponent<NavMeshAgent>();
agent.speed = moveSpeed;
// Lưu lại vị trí ban đầu để làm tâm của khu vực tuần tra
startPosition = transform.position;
nextShootTime = Time.time + Random.Range(minShootDelay, maxShootDelay);
InitBehaviorTree();
FindPlayer();
@@ -109,9 +115,15 @@ public class EnemyAI : MonoBehaviour
if (distance <= detectRange)
{
if (!hasSpottedPlayer)
{
hasSpottedPlayer = true;
AudioManager.Instance?.Play(alertSound, position: transform.position);
}
return NodeState.Success;
}
hasSpottedPlayer = false; // Reset nếu player ra khỏi tầm mắt
return NodeState.Failure;
}
@@ -139,7 +151,7 @@ public class EnemyAI : MonoBehaviour
Vector3 randomDirection = Random.insideUnitSphere * patrolRadius;
randomDirection += startPosition;
NavMeshHit hit;
// Đảm bảo điểm ngẫu nhiên nằm trên bề mặt NavMesh hợp lệ
if (NavMesh.SamplePosition(randomDirection, out hit, patrolRadius, 1))
{
@@ -157,7 +169,7 @@ public class EnemyAI : MonoBehaviour
if (player == null) return NodeState.Failure;
// Debug.Log("Chasing Player");
if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
agent.isStopped = false;
@@ -172,7 +184,7 @@ public class EnemyAI : MonoBehaviour
if (player == null) return NodeState.Failure;
// Debug.Log("Focus and Shoot!");
if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
// Dừng NavMeshAgent lại để đứng bắn, tránh bị trượt
@@ -202,6 +214,7 @@ public class EnemyAI : MonoBehaviour
{
if (laserPrefab == null || firePoint == null) return;
Instantiate(laserPrefab, firePoint.position, firePoint.rotation);
AudioManager.Instance?.Play(shootSound, position: transform.position);
// Debug.Log("Laser Shot!");
}

View File

@@ -4,6 +4,7 @@ using System.Text;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using Hallucinate.Audio;
[Serializable]
public class Part
@@ -44,12 +45,17 @@ public class GerminiNPC : MonoBehaviour
public float interactionDistance = 5f; // Khoảng cách tối đa để nói chuyện
public Transform playerTransform; // Gán transform của Player vào đây
[Header("Audio")]
public string startTalkSound = "NPC_Interact";
public string responseSound = "NPC_Response";
private void Update()
{
if (Keyboard.current != null && Keyboard.current.fKey.wasPressedThisFrame)
{
if (CanSeePlayer())
{
AudioManager.Instance?.Play(startTalkSound, position: transform.position);
StartCoroutine(GetGerminiReponse());
}
else
@@ -121,6 +127,7 @@ public class GerminiNPC : MonoBehaviour
{
var npcResponse = geminiResponse.candidates[0].content.parts[0].text;
Debug.Log($"<color=green>Tom:</color> {npcResponse}");
AudioManager.Instance?.Play(responseSound, position: transform.position);
}
}
catch (Exception e)

View File

@@ -1,10 +1,14 @@
using UnityEngine;
using Hallucinate.Audio;
public class LaserProjectile : MonoBehaviour
{
public float speed = 5f;
public float lifeTime = 5f;
[Header("Audio")]
public string hitSound = "Laser_Hit";
private void Start()
{
Destroy(gameObject, lifeTime);
@@ -24,6 +28,8 @@ public class LaserProjectile : MonoBehaviour
{
Debug.Log("Player Hit");
AudioManager.Instance?.Play(hitSound, position: transform.position);
Destroy(gameObject);
}
}

View File

@@ -238,18 +238,30 @@ namespace Invector.vCamera
public virtual void ToggleCameraView()
{
Debug.Log($"[vThirdPersonCamera] ToggleCameraView called. Current Mode: {currentState.cameraMode}");
if (currentState.cameraMode == TPCameraMode.FirstPerson)
{
Debug.Log("[vThirdPersonCamera] Switching to Default (TPV)");
ChangeState("Default");
}
else
{
Debug.Log("[vThirdPersonCamera] Switching to FirstPerson");
ChangeState("FirstPerson");
// If the state "FirstPerson" does not exist in the list,
// we force the mode to FirstPerson anyway
if (currentStateName != "FirstPerson")
// If the state was not found in the list, Invector might have reverted it to Default.
// We force it here by creating a temporary state if necessary.
if (currentState.cameraMode != TPCameraMode.FirstPerson)
{
currentState.cameraMode = TPCameraMode.FirstPerson;
Debug.Log("[vThirdPersonCamera] FirstPerson state not found in list, creating a temporary one to prevent revert.");
vThirdPersonCameraState fpState = new vThirdPersonCameraState("FirstPerson");
fpState.cameraMode = TPCameraMode.FirstPerson;
fpState.defaultDistance = 0;
fpState.height = 0;
fpState.fov = fpvFOV;
lerpState = fpState;
currentState.CopyState(fpState);
currentStateName = "FirstPerson";
}
}

View File

@@ -1,6 +1,7 @@
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using Hallucinate.Audio; // Import namespace for AudioManager
public class FinishGate : MonoBehaviour
{
@@ -18,6 +19,11 @@ public class FinishGate : MonoBehaviour
public GameObject winStar2;
public GameObject winStar3;
[Header("Cài đặt Âm thanh")]
public string winSound = "UI_Win";
public string warningSound = "UI_Warning";
public string clickSound = "UI_Click";
private void Start()
{
Time.timeScale = 1f;
@@ -76,6 +82,8 @@ public class FinishGate : MonoBehaviour
winPanel.SetActive(true);
UpdateWinStarsUI(count); // Hiện số sao tương ứng trên bảng kết thúc
}
AudioManager.PlayGlobal(winSound); // Chạy âm thanh thắng cuộc
Time.timeScale = 0f;
Cursor.lockState = CursorLockMode.None;
@@ -86,18 +94,23 @@ public class FinishGate : MonoBehaviour
{
if (ui == null) yield break;
ui.SetActive(true);
if (ui == warningUI) AudioManager.PlayGlobal(warningSound); // Chạy âm thanh cảnh báo
yield return new WaitForSeconds(3f);
ui.SetActive(false);
}
public void RestartGame()
{
AudioManager.PlayGlobal(clickSound); // Âm thanh click nút
Time.timeScale = 1f;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void QuitGame()
{
AudioManager.PlayGlobal(clickSound); // Âm thanh click nút
Application.Quit();
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;

View File

@@ -1,11 +1,15 @@
using UnityEngine;
using System.Collections;
using Hallucinate.Audio;
public class TreasureItem : MonoBehaviour
{
[Header("Cài đặt UI thông báo")]
public GameObject notificationText; // Text "Đã nhặt Cổ vật"
[Header("Cài đặt Âm thanh")]
public string pickupSound = "Item_Pickup";
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
@@ -29,6 +33,12 @@ public class TreasureItem : MonoBehaviour
// 3. Kích hoạt trạng thái truy đuổi cho toàn bộ Enemy AI
SetEnemiesAlertState(true);
// 4. Chạy âm thanh nhặt đồ
if (AudioManager.Instance != null)
{
AudioManager.Instance.Play(pickupSound, position: transform.position);
}
if (notificationText != null)
{
StopAllCoroutines();

View File

@@ -164,6 +164,7 @@ namespace OnlyScove.Scripts
{
if (context.performed)
{
Debug.Log("[InputReader] ToggleView Action Performed!");
wasToggleViewPressed = true;
OnToggleViewEvent?.Invoke();
}

View File

@@ -1,4 +1,5 @@
using System.Collections;
using Invector;
using OnlyScove.Scripts;
using UnityEngine;
using UnityEngine.Events;
@@ -485,10 +486,7 @@ namespace Invector.vCharacterController
public virtual void StrafeInput()
{
if (inputReader != null && inputReader.ConsumeToggleView())
{
cc.Strafe();
}
// Removed inputReader.ConsumeToggleView() logic that was incorrectly triggering Strafe
}
public virtual void SprintInput()
@@ -610,6 +608,10 @@ namespace Invector.vCharacterController
{
tpCamera.ChangeState(customCameraState, customlookAtPoint, smoothCameraState);
}
else if (tpCamera.currentState.cameraMode == TPCameraMode.FirstPerson)
{
// Do nothing, let FirstPerson mode stay active
}
else if (cc.isCrouching)
{
tpCamera.ChangeState("Crouch", true);

View File

@@ -310,3 +310,30 @@ MonoBehaviour:
eulerAngle: {x: 24.449335, y: 135.46579, z: 0.001277386}
freeRotation: 1
cameraMode: 2
- Name: FirstPerson
forward: 70
right: 0
defaultDistance: 0
maxDistance: 0
minDistance: 0
height: 0
smooth: 10
smoothDamp: 0
xMouseSensitivity: 3
yMouseSensitivity: 3
yMinLimit: -40
yMaxLimit: 80
xMinLimit: -360
xMaxLimit: 360
rotationOffSet: {x: 0, y: 0, z: 0}
cullingHeight: 0.2
cullingMinDist: 0.1
fov: 113.1
useZoom: 0
fixedAngle: {x: 0, y: 0}
lookPoints:
- pointName: point_01
positionPoint: {x: 6.950366, y: 2.8947582, z: -24.111038}
eulerAngle: {x: 24.449337, y: 315.46573, z: 0.0012745722}
freeRotation: 1
cameraMode: 3

View File

@@ -32,13 +32,13 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: db48e0e5caa2999469a4f3aa249c188b, type: 3}
m_Texture: {fileID: 2800000, guid: 1ba5636bfdd687347966f548dbf5a0bc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: []
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 8, g: 0, b: 0, a: 1}
- _Vector0: {r: 1, g: 1, b: 0, a: 0}
m_BuildTextureStacks: []
m_AllowLocking: 1