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: 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}
|
||||
|
||||
@@ -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($"<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)
|
||||
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<BouncyBall>();
|
||||
if (ballScript != null)
|
||||
{
|
||||
ballScript.shotPosition = Camera.main.transform.position;
|
||||
}
|
||||
|
||||
Rigidbody rb = newBall.GetComponent<Rigidbody>();
|
||||
if (rb != null)
|
||||
{
|
||||
|
||||
@@ -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<Rigidbody>();
|
||||
if (rb != null)
|
||||
|
||||
@@ -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<Collider>();
|
||||
if (col == null)
|
||||
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.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>");
|
||||
UpdateScoreUI();
|
||||
if (distanceCanvas != null) distanceCanvas.SetActive(false);
|
||||
if (winStatusText != null) winStatusText.text = "";
|
||||
|
||||
Debug.Log("<color=green>ScoreManager đã khởi tạo thành công!</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)
|
||||
{
|
||||
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<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;
|
||||
UpdateScoreUI();
|
||||
Debug.Log("<color=cyan>===> GHI ĐIỂM THÀNH CÔNG! Điểm hiện tại: " + currentScore + "</color>");
|
||||
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($"<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()
|
||||
{
|
||||
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