Unity开发:如何根据玩家得分动态提升速度等级与物体生成速率
Unity 2D 得分动态调整游戏速度与生成速率的实现逻辑
现有代码存在的问题
- 硬编码得分阈值和速度倍率,后续调整难度高,新增等级需要手动加if判断
- 所有滚动对象都在Update中重复执行得分判断,场景内滚动对象较多时会产生不必要的性能损耗
- 只实现了滚动速度控制,没有涉及物体生成速率的调整逻辑
- 多if判断没有互斥逻辑,虽然高得分下高倍率会覆盖低倍率,但写法冗余易出错
正确实现逻辑
核心思路是把全局调速逻辑统一放在GameControl单例中,只有得分变化时才重新计算速度等级,再通过事件通知所有需要同步速度的模块,避免每帧重复判断。
1. 改造GameControl单例,新增调速逻辑
把速度等级、得分阈值、生成速率的映射关系统一配置,得分变化时自动计算新参数,对外抛出速度变化事件:
using UnityEngine; public class GameControl : MonoBehaviour { public static GameControl instance; public bool gameOver = false; public int score = 0; // 基础滚动速度 public float baseScrollSpeed = -2f; // 基础生成间隔(秒) public float baseSpawnInterval = 2f; // 对外暴露的当前参数 public float currentScrollSpeed { get; private set; } public float currentSpawnInterval { get; private set; } // 速度变化事件,所有需要同步速度的对象都可以订阅 public delegate void SpeedChangedHandler(float newSpeed, float newSpawnInterval); public event SpeedChangedHandler OnSpeedChanged; // 速度等级配置:<最低得分要求,速度倍率,生成间隔倍率> [System.Serializable] public class SpeedLevel { public int minScore; public float speedMultiplier; public float spawnIntervalMultiplier; } // 在Inspector面板配置等级即可,无需改代码 public SpeedLevel[] speedLevels; private void Awake() { if (instance == null) instance = this; else Destroy(gameObject); } private void Start() { // 初始化第一级速度 UpdateSpeedLevel(); } // 得分增加时调用这个方法 public void AddScore(int add) { if(gameOver) return; score += add; // 得分变化后才更新速度等级 UpdateSpeedLevel(); } private void UpdateSpeedLevel() { float targetSpeedMulti = 1f; float targetSpawnMulti = 1f; // 找到当前得分对应的最高等级 foreach (var level in speedLevels) { if (score >= level.minScore) { targetSpeedMulti = level.speedMultiplier; targetSpawnMulti = level.spawnIntervalMultiplier; } else { // 等级按得分从小到大排序的话,到不符合的就可以跳出 break; } } currentScrollSpeed = baseScrollSpeed * targetSpeedMulti; // 生成间隔倍率越小,生成越快 currentSpawnInterval = baseSpawnInterval * targetSpawnMulti; // 抛出事件通知所有订阅者 OnSpeedChanged?.Invoke(currentScrollSpeed, currentSpawnInterval); } }
你可以直接在Inspector面板按从小到大的顺序配置速度等级,比如:
- 0分:速度倍率1,生成间隔倍率1
- 5分:速度倍率3,生成间隔倍率0.7
- 10分:速度倍率5,生成间隔倍率0.4
2. 优化ScrollingObject代码,取消每帧判断
订阅GameControl的速度变化事件,只有速度更新时才修改刚体速度:
using UnityEngine; public class ScrollingObject : MonoBehaviour { private Rigidbody2D rb2d; private void Awake() { rb2d = GetComponent<Rigidbody2D>(); } private void OnEnable() { // 订阅速度变化事件 GameControl.instance.OnSpeedChanged += UpdateSpeed; // 初始化时直接取当前速度 UpdateSpeed(GameControl.instance.currentScrollSpeed, GameControl.instance.currentSpawnInterval); } private void OnDisable() { // 取消订阅避免内存泄漏 GameControl.instance.OnSpeedChanged -= UpdateSpeed; } private void UpdateSpeed(float newSpeed, float newSpawnInterval) { // 游戏结束时不修改速度 if(GameControl.instance.gameOver) return; rb2d.velocity = new Vector2(newSpeed, 0); } // 单独处理游戏结束逻辑,或者也可以在GameControl抛出游戏结束事件统一处理 private void Update() { if (GameControl.instance.gameOver) { rb2d.velocity = Vector2.zero; } } }
3. 新增物体生成速率控制逻辑
在你的场景物体生成脚本中,同样订阅速度变化事件,修改生成间隔即可:
using UnityEngine; public class ObjectSpawner : MonoBehaviour { // 要生成的物体预设 public GameObject spawnPrefab; private float currentSpawnTimer; private float currentSpawnInterval; private void OnEnable() { GameControl.instance.OnSpeedChanged += UpdateSpawnParam; currentSpawnInterval = GameControl.instance.currentSpawnInterval; } private void OnDisable() { GameControl.instance.OnSpeedChanged -= UpdateSpawnParam; } private void UpdateSpawnParam(float newSpeed, float newInterval) { currentSpawnInterval = newInterval; } private void Update() { if(GameControl.instance.gameOver) return; currentSpawnTimer += Time.deltaTime; if (currentSpawnTimer >= currentSpawnInterval) { currentSpawnTimer = 0; Instantiate(spawnPrefab, transform.position, Quaternion.identity); } } }
内容的提问来源于stack exchange,提问作者AAAAA98
相关产品推荐
相关产品推荐

