diff --git a/.idea/.idea.VR-GAME/.idea/indexLayout.xml b/.idea/.idea.VR-GAME/.idea/indexLayout.xml
deleted file mode 100644
index 7b08163..0000000
--- a/.idea/.idea.VR-GAME/.idea/indexLayout.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Assets/Prefab/Sphere.prefab b/Assets/Prefab/Sphere.prefab
index c0ca996..a9461c0 100644
--- a/Assets/Prefab/Sphere.prefab
+++ b/Assets/Prefab/Sphere.prefab
@@ -13,6 +13,7 @@ GameObject:
- component: {fileID: 4871679746275035045}
- component: {fileID: 1403353099253554078}
- component: {fileID: 4684177289331536007}
+ - component: {fileID: 5080108737146792294}
m_Layer: 0
m_Name: Sphere
m_TagString: Ball
@@ -140,3 +141,16 @@ Rigidbody:
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
+--- !u!114 &5080108737146792294
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7093238386133182062}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 15dabd6ae947f12439f46655ed59fd7c, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::BouncyBall
+ shotPosition: {x: 0, y: 0, z: 0}
diff --git a/Assets/Script/BallShooter.cs b/Assets/Script/BallShooter.cs
index ddb6903..fee135f 100644
--- a/Assets/Script/BallShooter.cs
+++ b/Assets/Script/BallShooter.cs
@@ -6,9 +6,23 @@ public class BallShooter : MonoBehaviour
public Transform shootPoint; // Kéo điểm ShootPoint vào đây
public float shootForce = 500f;
public float upwardForce = 200f; // Lực ném vòng cung lên trên
+
+ [Header("Shooting Limit")]
+ public float shootCooldown = 2f; // Thời gian chờ giữa 2 lần ném
+ private float nextShootTime = 0f;
public void ShootBall()
{
+ // Kiểm tra xem đã đến lúc được ném chưa
+ if (Time.time < nextShootTime)
+ {
+ Debug.Log($"Chờ một chút! Cần {(nextShootTime - Time.time):F1}s nữa để ném tiếp.");
+ return;
+ }
+
+ // Cập nhật thời gian ném tiếp theo
+ nextShootTime = Time.time + shootCooldown;
+
// 1. Lấy vị trí ném: Từ Camera lùi xuống dưới một chút (giống tay người cầm bóng)
Vector3 spawnPosition = Camera.main.transform.position
+ Camera.main.transform.forward * 0.5f
@@ -20,6 +34,13 @@ public class BallShooter : MonoBehaviour
// 3. Đảm bảo bóng không bị dính vào Image Target
newBall.transform.SetParent(null);
+ // Gán vị trí ném vào script BouncyBall
+ BouncyBall ballScript = newBall.GetComponent();
+ if (ballScript != null)
+ {
+ ballScript.shotPosition = Camera.main.transform.position;
+ }
+
Rigidbody rb = newBall.GetComponent();
if (rb != null)
{
diff --git a/Assets/Script/BouncyBall.cs b/Assets/Script/BouncyBall.cs
index cacdd9e..3834b33 100644
--- a/Assets/Script/BouncyBall.cs
+++ b/Assets/Script/BouncyBall.cs
@@ -2,10 +2,13 @@ using UnityEngine;
public class BouncyBall : MonoBehaviour
{
+ public Vector3 shotPosition;
+ public bool isScored = false;
+
void Start()
{
- // Tự động gán Tag để chắc chắn ScoreManager nhận ra quả bóng
- gameObject.tag = "Ball";
+ // Loại bỏ việc gán Tag bằng code để tránh lỗi nếu chưa tạo Tag trong Unity
+ // Chúng ta sẽ nhận diện bóng bằng Component BouncyBall cho chắc chắn
Rigidbody rb = GetComponent();
if (rb != null)
diff --git a/Assets/Script/ScoreManager.cs b/Assets/Script/ScoreManager.cs
index 216b4f8..b5c0d43 100644
--- a/Assets/Script/ScoreManager.cs
+++ b/Assets/Script/ScoreManager.cs
@@ -1,60 +1,161 @@
using UnityEngine;
-using TMPro; // Dùng UnityEngine.UI nếu bạn xài Text thường
+using TMPro;
+using UnityEngine.UI;
+using System.Collections;
public class ScoreManager : MonoBehaviour
{
- public TextMeshProUGUI scoreText; // Kéo UI Text điểm số vào đây
+ [Header("UI References")]
+ public TextMeshProUGUI scoreText;
+ public TextMeshProUGUI timerText;
+ public TextMeshProUGUI winStatusText;
+ public GameObject distanceCanvas;
+ public TextMeshProUGUI distanceText;
+
+ [Header("Game Settings")]
+ public float gameDuration = 300f;
+ public int targetScore = 50;
+
private int currentScore = 0;
+ private float timeRemaining;
+ private bool isGameOver = false;
void Start()
{
currentScore = 0;
- UpdateScoreUI();
+ timeRemaining = gameDuration;
+ isGameOver = false;
- // CHẨN ĐOÁN LỖI:
- Collider col = GetComponent();
- if (col == null)
- Debug.LogError("LỖI NẶNG: Object này (" + gameObject.name + ") CHƯA CÓ COLLIDER. Hãy add Box Collider ngay!");
- else if (!col.isTrigger)
- Debug.LogWarning("CẢNH BÁO: Collider của rổ chưa tích 'Is Trigger'. Hãy tích vào!");
-
- Debug.Log("Script ScoreManager đang hoạt động trên: " + gameObject.name + "");
+ UpdateScoreUI();
+ if (distanceCanvas != null) distanceCanvas.SetActive(false);
+ if (winStatusText != null) winStatusText.text = "";
+
+ Debug.Log("ScoreManager đã khởi tạo thành công!");
+ }
+
+ void Update()
+ {
+ if (isGameOver) return;
+
+ if (timeRemaining > 0)
+ {
+ timeRemaining -= Time.deltaTime;
+ UpdateTimerUI();
+
+ if (currentScore >= targetScore)
+ {
+ WinGame();
+ }
+ }
+ else
+ {
+ GameOver();
+ }
}
- // Bắt va chạm kiểu Trigger (Xuyên qua)
private void OnTriggerEnter(Collider other)
{
- GhiDiem(other.gameObject, "TRIGGER");
+ Debug.Log("Va chạm Trigger với: " + other.gameObject.name);
+ ProcessScore(other.gameObject);
}
- // Bắt va chạm kiểu Vật lý (Đập vào nhau) - Dự phòng nếu bạn chưa tích Is Trigger
private void OnCollisionEnter(Collision collision)
{
- GhiDiem(collision.gameObject, "PHYSICS");
+ Debug.Log("Va chạm Vật lý với: " + collision.gameObject.name);
+ ProcessScore(collision.gameObject);
}
- void GhiDiem(GameObject obj, string type)
+ void ProcessScore(GameObject obj)
{
- Debug.Log("PHÁT HIỆN VA CHẠM [" + type + "] với: " + obj.name + " | Tag: " + obj.tag);
+ if (isGameOver) return;
- if (obj.CompareTag("Ball") || obj.name.Contains("Sphere") || obj.name.Contains("ball"))
+ // Ưu tiên kiểm tra script BouncyBall
+ BouncyBall ball = obj.GetComponent();
+
+ // Nếu không có script, hoặc bóng đã được tính điểm rồi thì bỏ qua
+ if (ball == null || ball.isScored)
{
- currentScore += 2;
- UpdateScoreUI();
- Debug.Log("===> GHI ĐIỂM THÀNH CÔNG! Điểm hiện tại: " + currentScore + "");
- Destroy(obj, 0.2f);
+ return;
}
+
+ // Đánh dấu đã ghi điểm ngay lập tức
+ ball.isScored = true;
+
+ // Tính khoảng cách
+ float distance = Vector3.Distance(ball.shotPosition, transform.position);
+ int points = CalculatePoints(distance);
+
+ currentScore += points;
+ UpdateScoreUI();
+
+ // Hiển thị khoảng cách trên rổ
+ if (distanceCanvas != null)
+ {
+ StopAllCoroutines(); // Dừng các lần hiện trước đó để tránh chồng chéo
+ StartCoroutine(ShowDistanceUI(distance));
+ }
+ else
+ {
+ Debug.LogWarning("distanceCanvas chưa được gán trong Inspector!");
+ }
+
+ Debug.Log($"GHI ĐIỂM: {points}pt | Khoảng cách ném: {distance:F2}m | Tổng điểm: {currentScore}");
+
+ // Vô hiệu hóa script hoặc quả bóng để không tính điểm lại
+ ball.enabled = false;
+ Destroy(obj, 0.5f);
+ }
+
+ int CalculatePoints(float distance)
+ {
+ // Điều chỉnh lại logic: Nếu trong AR khoảng cách tính bằng Unity Unit có thể rất nhỏ
+ // Bạn có thể cần nhân distance với một hệ số nếu tỉ lệ scale của bạn khác 1:1 mét
+ if (distance >= 10f) return 3;
+ if (distance >= 5f) return 2;
+ if (distance >= 3f) return 1;
+ return 1;
}
void UpdateScoreUI()
{
- if (scoreText != null)
+ if (scoreText != null) scoreText.text = "Score: " + currentScore;
+ }
+
+ void UpdateTimerUI()
+ {
+ if (timerText != null)
{
- scoreText.text = "Score: " + currentScore;
+ int minutes = Mathf.FloorToInt(timeRemaining / 60);
+ int seconds = Mathf.FloorToInt(timeRemaining % 60);
+ timerText.text = string.Format("Time: {0:00}:{1:00}", minutes, seconds);
}
- else
+ }
+
+ IEnumerator ShowDistanceUI(float distance)
+ {
+ if (distanceText != null) distanceText.text = $"{distance:F1}m";
+ distanceCanvas.SetActive(true);
+ yield return new WaitForSeconds(2.5f);
+ distanceCanvas.SetActive(false);
+ }
+
+ void WinGame()
+ {
+ isGameOver = true;
+ if (winStatusText != null)
{
- Debug.LogWarning("ScoreText chưa được kéo vào ScoreManager!");
+ winStatusText.text = "YOU WIN!";
+ winStatusText.color = Color.green;
+ }
+ }
+
+ void GameOver()
+ {
+ isGameOver = true;
+ if (winStatusText != null)
+ {
+ winStatusText.text = "GAME OVER";
+ winStatusText.color = Color.red;
}
}
}
diff --git a/Library/ArtifactDB b/Library/ArtifactDB
index 1459bb6..bc6bde3 100644
Binary files a/Library/ArtifactDB and b/Library/ArtifactDB differ