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

Unity中通用Timer类的方法调用时机选择疑问

问题解答

核心原则:单一职责与通用性

既然Timer是通用脚本,不能和任何场景、UI绑定,那计时的核心逻辑(数值递减)必须放在Timer内部的Update里,SumoController只负责读取Timer的数值、更新UI以及触发游戏状态变更即可。

具体实现方案

1. 优化Timer类

保留Timer自身的Update处理计时逻辑,同时把内部计时字段设为私有,通过只读属性对外暴露,避免外部直接修改数值,保证封装性:

using UnityEngine;

public class Timer : MonoBehaviour
{
    [SerializeField] private float _startCountdown = 5f;
    [SerializeField] private float _endCountdown = 300f;

    // 提供只读属性供外部访问计时数值
    public float StartCountdown => _startCountdown;
    public float EndCountdown => _endCountdown;

    private void Update()
    {
        UpdateStartTimer();
        UpdateEndTimer();
    }

    // 内部私有方法处理计时递减逻辑
    private void UpdateStartTimer()
    {
        if (_startCountdown >= 0f)
        {
            _startCountdown -= Time.deltaTime;
        }
    }

    private void UpdateEndTimer()
    {
        if (_endCountdown >= 0f)
        {
            _endCountdown -= Time.deltaTime;
        }
    }

    // 可选:增加重置计时器的方法,提升通用性
    public void ResetStartTimer(float newValue = 5f)
    {
        _startCountdown = newValue;
    }

    public void ResetEndTimer(float newValue = 300f)
    {
        _endCountdown = newValue;
    }
}

2. 优化SumoController类

移除SumoController中重复的计时逻辑,只保留UI更新和游戏状态控制的职责:

using UnityEngine;

public class SumoController : MonoBehaviour
{
    public bool isWin;
    public bool isGameOver;
    public bool isGameStart;
    public SumoTankController player;
    public SumoTankAI bot;
    public SumoUIManager sumoUIManager;
    public Timer timer;

    private void Start()
    {
        player.sumoController = this;
        player.GetComponentInChildren<SumoTankGun>().sumoController = this;
        bot.sumoController = this;
        bot.GetComponentInChildren<SumoTankAIGun>().sumoController = this;
        
        sumoUIManager.matchResultText.gameObject.SetActive(false);
        sumoUIManager.timeToStartGame.gameObject.SetActive(true);
    }

    private void Update()
    {
        UpdateStartGameUI();
        UpdateEndGameUI();
    }

    public void CheckMatchResult()
    {
        if (isGameOver) return;
        
        sumoUIManager.matchResultText.text = isWin ? "Вы победили!" : "Вы проиграли!";
        sumoUIManager.matchResultText.gameObject.SetActive(true);
        isGameOver = true;
    }

    private void UpdateStartGameUI()
    {
        if (timer.StartCountdown >= 0f)
        {
            sumoUIManager.timeToStartGame.text = $"{timer.StartCountdown:f1}";
        }
        else if (!isGameStart)
        {
            sumoUIManager.timeToStartGame.gameObject.SetActive(false);
            isGameStart = true;
        }
    }

    private void UpdateEndGameUI()
    {
        if (timer.EndCountdown >= 0f)
        {
            int minutes = Mathf.FloorToInt(timer.EndCountdown / 60);
            int seconds = Mathf.FloorToInt(timer.EndCountdown % 60);
            sumoUIManager.timeToEndGame.text = $"{minutes:00}:{seconds:00}";
        }
        else if (!isGameOver)
        {
            sumoUIManager.backBtn.onClick.Invoke();
            isGameOver = true;
        }
    }
}

方案优势

  • 保证Timer通用性:Timer只专注于计时逻辑,不依赖任何场景或UI,可直接在其他项目中复用。
  • 遵循单一职责:SumoController只处理游戏流程和UI更新,职责清晰,代码更易维护。
  • 提升封装性:Timer的内部数值通过只读属性暴露,避免外部误修改导致的逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 02:10:34