前言
我将设计一个Unity3D游戏客户端框架的多场景管理系统,包含场景加载、进度显示和过渡动画等功能。
设计思路
- 场景管理核心:单例管理器处理场景加载/卸载
- 加载界面:显示进度条、提示信息和加载动画
- 场景切换过渡:平滑的淡入淡出效果
- 多场景支持:支持叠加加载和单独加载
- 错误处理:场景加载失败提示
对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!
完整实现代码
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class SceneTransitionManager : MonoBehaviour
{
public static SceneTransitionManager Instance { get; private set; }
[Header("UI References")]
public CanvasGroup loadingScreen;
public Slider progressBar;
public Text progressText;
public Text tipText;
public Image loadingIcon;
[Header("Settings")]
public float fadeDuration = 0.5f;
public float minLoadTime = 1.5f;
public List<string> loadingTips = new List<string>
{
"小提示:探索场景可以找到隐藏道具",
"小提示:按ESC键可以打开设置菜单",
"小提示:完成每日任务可获得额外奖励"
};
private AsyncOperation currentAsyncOperation;
private bool isLoading;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
// 加载单个场景(替换当前场景)
public void LoadScene(string sceneName)
{
if (isLoading) return;
StartCoroutine(LoadSceneCoroutine(sceneName, LoadSceneMode.Single));
}
// 叠加加载场景(不卸载当前场景)
public void LoadSceneAdditive(string sceneName)
{
if (isLoading) return;
StartCoroutine(LoadSceneCoroutine(sceneName, LoadSceneMode.Additive));
}
// 卸载指定场景
public void UnloadScene(string sceneName)
{
StartCoroutine(UnloadSceneCoroutine(sceneName));
}
private IEnumerator LoadSceneCoroutine(string sceneName, LoadSceneMode mode)
{
isLoading = true;
// 显示随机提示
tipText.text = loadingTips[Random.Range(0, loadingTips.Count)];
// 淡入加载界面
yield return StartCoroutine(FadeLoadingScreen(0, 1, fadeDuration));
float timer = 0f;
progressBar.value = 0;
progressText.text = "0%";
// 开始异步加载场景
currentAsyncOperation = SceneManager.LoadSceneAsync(sceneName, mode);
currentAsyncOperation.allowSceneActivation = false;
// 旋转加载图标
StartCoroutine(RotateLoadingIcon());
while (!currentAsyncOperation.isDone)
{
timer += Time.deltaTime;
// 计算加载进度(0-0.9)
float loadProgress = Mathf.Clamp01(currentAsyncOperation.progress / 0.9f);
float percent = Mathf.Clamp01((timer / minLoadTime) * loadProgress);
progressBar.value = percent;
progressText.text = Mathf.Round(percent * 100) + "%";
// 加载完成但等待最小加载时间
if (currentAsyncOperation.progress >= 0.9f && timer >= minLoadTime)
{
progressBar.value = 1;
progressText.text = "100%";
currentAsyncOperation.allowSceneActivation = true;
}
yield return null;
}
// 淡出加载界面
yield return StartCoroutine(FadeLoadingScreen(1, 0, fadeDuration));
isLoading = false;
}
private IEnumerator UnloadSceneCoroutine(string sceneName)
{
AsyncOperation unloadOperation = SceneManager.UnloadSceneAsync(sceneName);
while (!unloadOperation.isDone)
{
yield return null;
}
}
private IEnumerator FadeLoadingScreen(float startAlpha, float endAlpha, float duration)
{
float time = 0;
loadingScreen.blocksRaycasts = true;
loadingScreen.interactable = true;
while (time < duration)
{
loadingScreen.alpha = Mathf.Lerp(startAlpha, endAlpha, time / duration);
time += Time.deltaTime;
yield return null;
}
loadingScreen.alpha = endAlpha;
if (endAlpha == 0)
{
loadingScreen.blocksRaycasts = false;
loadingScreen.interactable = false;
}
}
private IEnumerator RotateLoadingIcon()
{
while (isLoading)
{
loadingIcon.transform.Rotate(0, 0, -180 * Time.deltaTime);
yield return null;
}
}
}
使用说明
场景切换方法
- 加载单个场景:
SceneTransitionManager.Instance.LoadScene("MainScene");
叠加加载场景:
SceneTransitionManager.Instance.LoadSceneAdditive("InventoryScene");
卸载场景:
SceneTransitionManager.Instance.UnloadScene("InventoryScene");
编辑器设置
- 创建UI Canvas用于加载界面
- 添加以下元素:
- 半透明背景Panel
- 进度条Slider
- 进度百分比Text
- 提示信息Text
- 旋转加载图标Image
- 将组件拖拽到SceneTransitionManager脚本的对应字段
功能特点
- 平滑过渡:使用CanvasGroup实现淡入淡出效果
- 最小加载时间:确保玩家能看到加载提示和进度
- 随机提示:每次加载显示不同的游戏提示
- 进度可视化:实时显示加载进度百分比
- 动画效果:旋转图标增强视觉效果
- 错误保护:防止重复加载场景
最佳实践建议
- 场景组织:
- 将核心系统放在常驻场景
- 按功能模块划分场景(如UI、关卡、角色等)
- 资源管理:
- 使用Addressables或AssetBundle管理资源
- 在加载场景前预加载必要资源
- 场景通信:
- 使用事件系统解耦场景间通信
- 通过GameObject.FindGameObjectWithTag查找关键对象
- 性能优化:
- 对大型场景使用分区域加载
- 异步加载资源避免卡顿
- 使用对象池管理频繁创建销毁的对象
这个多场景管理系统提供了游戏开发中常见的场景管理功能,可以作为游戏框架的核心组件之一。您可以根据项目需求扩展错误处理、场景依赖管理等功能。
更多教学视频