update time , score
This commit is contained in:
8
.idea/.idea.VR-GAME/.idea/indexLayout.xml
generated
8
.idea/.idea.VR-GAME/.idea/indexLayout.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="UserContentModel">
|
|
||||||
<attachedFolders />
|
|
||||||
<explicitIncludes />
|
|
||||||
<explicitExcludes />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -13,6 +13,7 @@ GameObject:
|
|||||||
- component: {fileID: 4871679746275035045}
|
- component: {fileID: 4871679746275035045}
|
||||||
- component: {fileID: 1403353099253554078}
|
- component: {fileID: 1403353099253554078}
|
||||||
- component: {fileID: 4684177289331536007}
|
- component: {fileID: 4684177289331536007}
|
||||||
|
- component: {fileID: 5080108737146792294}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Sphere
|
m_Name: Sphere
|
||||||
m_TagString: Ball
|
m_TagString: Ball
|
||||||
@@ -140,3 +141,16 @@ Rigidbody:
|
|||||||
m_Interpolate: 0
|
m_Interpolate: 0
|
||||||
m_Constraints: 0
|
m_Constraints: 0
|
||||||
m_CollisionDetection: 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}
|
||||||
|
|||||||
@@ -6,9 +6,23 @@ public class BallShooter : MonoBehaviour
|
|||||||
public Transform shootPoint; // Kéo điểm ShootPoint vào đây
|
public Transform shootPoint; // Kéo điểm ShootPoint vào đây
|
||||||
public float shootForce = 500f;
|
public float shootForce = 500f;
|
||||||
public float upwardForce = 200f; // Lực ném vòng cung lên trên
|
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()
|
public void ShootBall()
|
||||||
{
|
{
|
||||||
|
// Kiểm tra xem đã đến lúc được ném chưa
|
||||||
|
if (Time.time < nextShootTime)
|
||||||
|
{
|
||||||
|
Debug.Log($"<color=yellow>Chờ một chút! Cần {(nextShootTime - Time.time):F1}s nữa để ném tiếp.</color>");
|
||||||
|
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)
|
// 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
|
Vector3 spawnPosition = Camera.main.transform.position
|
||||||
+ Camera.main.transform.forward * 0.5f
|
+ 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
|
// 3. Đảm bảo bóng không bị dính vào Image Target
|
||||||
newBall.transform.SetParent(null);
|
newBall.transform.SetParent(null);
|
||||||
|
|
||||||
|
// Gán vị trí ném vào script BouncyBall
|
||||||
|
BouncyBall ballScript = newBall.GetComponent<BouncyBall>();
|
||||||
|
if (ballScript != null)
|
||||||
|
{
|
||||||
|
ballScript.shotPosition = Camera.main.transform.position;
|
||||||
|
}
|
||||||
|
|
||||||
Rigidbody rb = newBall.GetComponent<Rigidbody>();
|
Rigidbody rb = newBall.GetComponent<Rigidbody>();
|
||||||
if (rb != null)
|
if (rb != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ using UnityEngine;
|
|||||||
|
|
||||||
public class BouncyBall : MonoBehaviour
|
public class BouncyBall : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
public Vector3 shotPosition;
|
||||||
|
public bool isScored = false;
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
// Tự động gán Tag để chắc chắn ScoreManager nhận ra quả bóng
|
// Loại bỏ việc gán Tag bằng code để tránh lỗi nếu chưa tạo Tag trong Unity
|
||||||
gameObject.tag = "Ball";
|
// Chúng ta sẽ nhận diện bóng bằng Component BouncyBall cho chắc chắn
|
||||||
|
|
||||||
Rigidbody rb = GetComponent<Rigidbody>();
|
Rigidbody rb = GetComponent<Rigidbody>();
|
||||||
if (rb != null)
|
if (rb != null)
|
||||||
|
|||||||
@@ -1,60 +1,161 @@
|
|||||||
using UnityEngine;
|
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 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 int currentScore = 0;
|
||||||
|
private float timeRemaining;
|
||||||
|
private bool isGameOver = false;
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
currentScore = 0;
|
currentScore = 0;
|
||||||
UpdateScoreUI();
|
timeRemaining = gameDuration;
|
||||||
|
isGameOver = false;
|
||||||
|
|
||||||
// CHẨN ĐOÁN LỖI:
|
UpdateScoreUI();
|
||||||
Collider col = GetComponent<Collider>();
|
if (distanceCanvas != null) distanceCanvas.SetActive(false);
|
||||||
if (col == null)
|
if (winStatusText != null) winStatusText.text = "";
|
||||||
Debug.LogError("<color=red>LỖI NẶNG: Object này (" + gameObject.name + ") CHƯA CÓ COLLIDER. Hãy add Box Collider ngay!</color>");
|
|
||||||
else if (!col.isTrigger)
|
Debug.Log("<color=green>ScoreManager đã khởi tạo thành công!</color>");
|
||||||
Debug.LogWarning("<color=yellow>CẢNH BÁO: Collider của rổ chưa tích 'Is Trigger'. Hãy tích vào!</color>");
|
}
|
||||||
|
|
||||||
Debug.Log("<color=white>Script ScoreManager đang hoạt động trên: " + gameObject.name + "</color>");
|
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)
|
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)
|
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<BouncyBall>();
|
||||||
|
|
||||||
|
// 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;
|
return;
|
||||||
UpdateScoreUI();
|
|
||||||
Debug.Log("<color=cyan>===> GHI ĐIỂM THÀNH CÔNG! Điểm hiện tại: " + currentScore + "</color>");
|
|
||||||
Destroy(obj, 0.2f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Đá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($"<color=cyan>GHI ĐIỂM: {points}pt | Khoảng cách ném: {distance:F2}m | Tổng điểm: {currentScore}</color>");
|
||||||
|
|
||||||
|
// 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()
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user