You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity快艇竞速游戏最佳圈计时不更新问题求助

最佳圈计时功能修复方案

核心问题分析

  1. 第一圈逻辑错误:初始bestHour/bestMinute/bestSecond默认值为0,第一圈完成时的判断逻辑冗余,且未在第一圈结束后切换isFirstLap状态,导致后续圈无法进入正确的时间比较分支。
  2. 非第一圈比较逻辑漏洞:单独拆分小时、分钟、秒进行比较的方式不严谨,无法准确判断总时长是否更短;同时存在笔误——currentMinute = currentMinute完全无效,未对bestMinute赋值。
  3. TimerFunction重复调用:OnTriggerEnter中两个条件都会触发计时逻辑,导致时间计算混乱。
  4. 时间重置与状态重置缺失:当前代码未在圈数完成后重置isCalled,影响下一圈的冲线判断;时间进位逻辑使用==判断,易因浮点精度问题跳过进位。

修复步骤

1. 统一时间比较逻辑

将当前时间和最佳时间转换为总秒数进行比较,避免分单位比较的逻辑漏洞,确保判断结果准确。

2. 修正第一圈状态切换

第一圈完成后立即将isFirstLap设为false,确保后续圈进入正确的时间比较分支。

3. 清理重复触发逻辑

移除OnTriggerEnter中重复调用TimerFunction的代码,确保每圈仅触发一次计时更新。

4. 优化时间进位与初始化

将最佳时间初始化为极大值,保证第一圈必然更新;时间进位时改用减法替代直接重置,避免精度丢失;用>=替代==判断进位条件。

修改后的完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class Race_Manager : MonoBehaviour {
    [HideInInspector]
    public bool enter = false;
    [HideInInspector]
    public bool isCalled = true;
    [HideInInspector]
    public bool lapCompleted = false;
    [HideInInspector]
    public bool raceStarted = false;
    [HideInInspector]
    public float currentHour;
    [HideInInspector]
    public float currentMinute;
    [HideInInspector]
    public float currentSecond;
    [HideInInspector]
    public float bestHour;
    [HideInInspector]
    public float bestMinute;
    [HideInInspector]
    public float bestSecond;
    public float timerSpeed = 10f;
    [HideInInspector]
    public int lapsDone;
    public int lapsToDo = 5;
    [HideInInspector]
    public int pointsHit;
    [HideInInspector]
    public Race_Checkpoint[] checkpoints;
    public Text currentTimeCounter;
    public Text bestTimeCounter;
    public Text lapCounter;
    public Canvas normalUI;
    public Canvas completionUI;
    public AudioSource successMusic;
    private bool raceOver = false;
    private CarCameras carCamera;
    private GameObject playerCar;
    private bool mainFunctionCalled = false;
    private bool timerActivated = false;
    private bool isFirstLap = true;

    void Start () {
        playerCar = GameObject.FindWithTag ("Player");
        carCamera = GameObject.FindObjectOfType<CarCameras> ();
        checkpoints = GetComponentsInChildren<Race_Checkpoint> ();
        // 初始化最佳时间为极大值,确保第一圈必然更新
        bestHour = 99;
        bestMinute = 59;
        bestSecond = 59;
    }

    void Update () {
        lapCounter.text = string.Format("Laps: {0} / {1}", lapsDone, lapsToDo);
        currentTimeCounter.text = string.Format("Current Time: {0:00}:{1:00}:{2:00}", currentHour, currentMinute, currentSecond);
        bestTimeCounter.text = string.Format("Best Time: {0:00}:{1:00}:{2:00}", bestHour, bestMinute, bestSecond);
        
        if (raceOver == true && mainFunctionCalled == true) {
            StartCoroutine (WinFunction());
        }
        if (raceOver == true) {
            playerCar.GetComponent<CarController> ().handbrakeInput = 1f;
        }
        if (timerActivated == true) {
            currentSecond += Time.deltaTime * timerSpeed;
        }
        if (currentSecond > 60f)
        {
            currentSecond -= 60f; // 用减法替代重置,避免精度丢失
            currentMinute += 1f;
        }
        if (currentMinute >= 60f) { // 用>=替代==,避免浮点精度问题
            currentMinute -= 60f;
            currentHour += 1f;
        }
        if (enter == true) {
            foreach (Race_Checkpoint point in checkpoints)
                point.ResetPoint ();
        }
    }

    void OnTriggerEnter (Collider other)
    {
        if (other.transform.parent.transform.parent.transform.tag == "Player" && raceStarted == false && lapsDone == 0 && isCalled == true) {
            timerActivated = true;
            raceStarted = true;
            lapsDone += 1;
            isCalled = false;
            enter = true;
        } else if (other.transform.parent.transform.parent.transform.tag == "Player" && raceStarted == true && isCalled == true && lapCompleted) {
            lapCompleted = false;
            isCalled = false;
            lapsDone += 1;
            pointsHit = 0;
            enter = true;
            // 仅在此处调用计时更新,避免重复触发
            StartCoroutine (TimerFunction ());
        } else {
            enter = false;
        }

        if (enter == true && lapsDone == lapsToDo + 1)
        {
            mainFunctionCalled = true;
            raceOver = true;
        }
    }

    IEnumerator WinFunction() {
        yield return new WaitForSeconds (0f);
        RestartGame restarter = GetComponent<RestartGame> ();
        successMusic.Play ();
        raceOver = true;
        normalUI.gameObject.SetActive (false);
        completionUI.gameObject.SetActive(true);
        playerCar.GetComponent<CarController> ().handbrakeInput = 1f;
        playerCar.GetComponent<CarController> ().throttleInput = 0f;
        playerCar.GetComponent<CarController> ().steerInput = 0f;
        playerCar.GetComponent<CarDynamics> ().controller = CarDynamics.Controller.external;
        carCamera.GetComponent<CarCameras> ().enabled = false;
        carCamera.GetComponent<CarCamerasController> ().enabled = false;
        carCamera.GetComponent<Animation> ().Play ("Camera_Finish");
        timerActivated = false;
        mainFunctionCalled = false;
        if (restarter != null) {
            restarter.enabled = false;
        }
    }

    IEnumerator TimerFunction()
    {
        yield return null; // 等待一帧确保时间数据稳定
        
        // 转换为总秒数进行比较
        float currentTotalSeconds = currentHour * 3600 + currentMinute * 60 + currentSecond;
        float bestTotalSeconds = bestHour * 3600 + bestMinute * 60 + bestSecond;

        if (isFirstLap)
        {
            // 第一圈直接赋值为最佳时间
            bestHour = currentHour;
            bestMinute = currentMinute;
            bestSecond = currentSecond;
            isFirstLap = false; // 切换状态
        }
        else if (currentTotalSeconds < bestTotalSeconds)
        {
            // 当前圈时间更短,更新最佳时间
            bestHour = currentHour;
            bestMinute = currentMinute;
            bestSecond = currentSecond;
        }

        // 重置当前圈计时与触发状态
        currentHour = 0f;
        currentMinute = 0f;
        currentSecond = 0f;
        isCalled = true;
    }
}

额外优化说明

  • 初始最佳时间设为99:59:59,确保第一圈完成后必然更新最佳记录。
  • 时间进位采用减法逻辑,避免直接重置为0导致的浮点精度丢失。
  • 在TimerFunction末尾重置isCalled,保证下一圈能正常触发冲线判断。

内容的提问来源于stack exchange,提问作者LukeyC116

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:34:52