unity游戏开发(二): 场景的切换

创建场景状态接口类 与 场景状态基类

public interface IBaseSceneState  {

    void EnterScene();
    void ExitScene();

}
public class BaseSceneState : IBaseSceneState
{
    protected UIFacade mUIFacade;

    public BaseSceneState(UIFacade uIFacade)
    {
        mUIFacade = uIFacade;
    }

    public virtual void EnterScene()
    {
        mUIFacade.InitPanel();
    }

    public virtual void ExitScene()
    {
        mUIFacade.ClearPanel();
    }
}

在Canvas和GameManager上挂载脚本

public class CanvasDontDesOnLoad : MonoBehaviour {
	  void Start ()
        {
             DontDestroyOnLoad(this.gameObject);
	}
}

游戏总管理类: GameManager  --游戏总管理,负责管理所有的管理者

UI管理者类:UIManager - 负责管理UI的管理者

UI中介者类: UIFacade -- UI中介,上层与管理者们做交互,下层与UI面板进行交互(使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互)

 

场景切换流程:
1. 调用ChangeScene方法 -- 在UIFacade中将当前场景赋值给上一个场景,将传入的场景赋值给当前场景
2. 在显示遮罩的2秒后调用上一个场景的Exit()方法:先清理当前场景字典中 Panel身上的IBasePanel的引用(直接Clear()) ,再清理Panel游戏物体,将其放入工厂后clear()字典
3. 再调用当前场景的Enter()方法 : 将当前场景所需的Panel游戏物体添加进存储Panel游戏物体的字典中,再实例化当前字典中的Panel面板并获取Panel面板上的Panel脚本,调用Panel脚本的Init()初始化方法并将Panel脚本添加进Panel脚本的字典中;
4. 最后用2秒逐渐隐藏遮罩,显示场景

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

/// <summary>
/// 游戏总管理,负责管理所有的管理者
/// </summary>
public class GameManager : MonoBehaviour
{
    private static GameManager _instance;
    public static GameManager instance
    {
        get
        {
            return _instance;
        }
    }

    public FactoryManager factoryManager;
    public UIManager uIManager;

    private void Awake()
    {
        _instance = this;
        factoryManager = new FactoryManager();
        uIManager = new UIManager();
        //第一次需要手动控制场景的加载
        uIManager.mUIFacade.currentSceneState.EnterScene();
    }


    //获取Sprite资源
    public Sprite GetSprite(string resourcesName)
    {
        return factoryManager.spriteFactory.GetSingleResources(resourcesName);
    }
    //获取AudioClip资源
    public AudioClip GetAudioClip(string resourcesName)
    {
        return factoryManager.audioClipFactory.GetSingleResources(resourcesName);
    }
    // 得到游戏物体资源
    public GameObject GetGameObjectResources(FactoryType factoryType,string resourcesName)
    {
        return factoryManager.factoryDict[factoryType].GetItem(resourcesName);
    }
    //将游戏物体入栈
    public void PushGameObjectToFactory(FactoryType factoryType,string itemName,GameObject itemGO)
    {
        factoryManager.factoryDict[factoryType].PushItem(itemName, itemGO);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

/// <summary>
/// UI中介,上层与管理者们做交互,下层与UI面板进行交互
/// </summary>
public class UIFacade {

    private GameManager mGameManager;

    public Dictionary<string, IBasePanel> currentScenePanelDict = new Dictionary<string, IBasePanel>();

    public IBaseSceneState currentSceneState;
    public IBaseSceneState lastSceneState;

    private GameObject mask; //开始画面的遮罩
    private Image maskImage; //遮罩图片
    public Transform canvasTrans;
    public UIManager mUIManager;

    public UIFacade(UIManager uIManager)
    {
        mGameManager = GameManager.instance;
        mUIManager = uIManager;
        InitMask();
    }

    //初始化遮罩
    public void InitMask()
    {
        canvasTrans = GameObject.Find("Canvas").transform;
        //mask = GameManager.instance.GetGameObjectResources(FactoryType.UIFactory,"Img_Mask");
        mask = CreateUIAndSetPos("Img_Mask");
        maskImage = mask.GetComponent<Image>();
    }

    //实例化UI
    public GameObject CreateUIAndSetPos(string uiName)
    {
        GameObject itemGO = GameManager.instance.GetGameObjectResources(FactoryType.UIFactory, uiName);
        itemGO.transform.SetParent(canvasTrans);
        itemGO.transform.localScale = Vector3.one;
        itemGO.transform.localPosition = Vector3.zero;
        return itemGO;
    }

    //改变当前场景的状态
    public void ChangeSceneState(IBaseSceneState baseSceneState)
    {
        lastSceneState = currentSceneState;
        ShowMask();
        currentSceneState = baseSceneState;
    }

    //显示遮罩
    public void ShowMask()
    {
        mask.transform.SetSiblingIndex(10);
        Tween t = DOTween.To(() => maskImage.color, toColor => maskImage.color = toColor, new Color(0, 0, 0, 1), 2f);
        t.OnComplete(ExitSceneComplete);
    }

    //离开当前场景
    public void ExitSceneComplete()
    {
        lastSceneState.ExitScene();
        currentSceneState.EnterScene();
        HideMask();
    }

    public void HideMask()
    {
        mask.transform.SetSiblingIndex(10);
        DOTween.To(() => maskImage.color, toColor => maskImage.color = toColor, new Color(0, 0, 0, 0), 2f);
    }

    /// <summary>
    /// 添加UIPanel到UIManager字典
    /// </summary>
    public void AddPanelToUIManagerDict(string uiPanelName)
    {
        mUIManager.currentScenePanelDict.Add(uiPanelName,mGameManager.GetGameObjectResources(FactoryType.UIPanelFactory,uiPanelName));
    }

    /// <summary>
    /// 实例化当前所有面板并添加到当前字典并调用Panel的Init()方法
    /// </summary>
    public void InitPanel()
    {
        foreach (var item in mUIManager.currentScenePanelDict)
        {
            item.Value.transform.SetParent(canvasTrans);
            item.Value.transform.localPosition = Vector3.zero;
            item.Value.transform.localScale = Vector3.one;
            IBasePanel basePanel = item.Value.GetComponent<IBasePanel>();
            if (basePanel == null)
            {
                Debug.LogWarning("获取面板上的IBasePanel脚本失败");
            }
            basePanel.InitPanel();
            currentScenePanelDict.Add(item.Key,basePanel);
        }
    }

    public void ClearPanel()
    {
        currentScenePanelDict.Clear();
        mUIManager.ClearDict();
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 负责管理UI的管理者
/// </summary>
public class UIManager {

    public Dictionary<string, GameObject> currentScenePanelDict;
    public UIFacade mUIFacade;

    public UIManager()
    {
        mUIFacade = new UIFacade(this);
        currentScenePanelDict = new Dictionary<string, GameObject>();
        mUIFacade.currentSceneState = new StartLoadSceneState(mUIFacade);
    }

    //清空字典,清除的是GameObject
    public void ClearDict()
    {
        foreach (var item in currentScenePanelDict)
        {
            PushUIPanelToFactory(item.Value.name.Substring(0,item.Value.name.Length-7),item.Value);
        }
        currentScenePanelDict.Clear();
    }

    //将UIPanel放回工厂
    public void PushUIPanelToFactory (string itemName,GameObject item)
    {
        GameManager.instance.PushGameObjectToFactory(FactoryType.UIPanelFactory, itemName,item);
    }
}

游戏开始场景:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class StartLoadSceneState : BaseSceneState
{
    public StartLoadSceneState(UIFacade uIFacade):base(uIFacade)
    {
     
    }

    public override void EnterScene()
    {
        mUIFacade.AddPanelToUIManagerDict(StringManager.StartLoadPanel);
        base.EnterScene();
    }

    public override void ExitScene()
    {
        base.ExitScene();
        SceneManager.LoadScene(1);
    }
}

游戏主场景

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainSceneState : BaseSceneState
{
    public MainSceneState(UIFacade uIFacade) : base(uIFacade)
    {

    }

    public override void EnterScene()
    {
        mUIFacade.AddPanelToUIManagerDict(StringManager.HelpPanel);
        mUIFacade.AddPanelToUIManagerDict(StringManager.SetPanel);
        mUIFacade.AddPanelToUIManagerDict(StringManager.MainPanel);
        mUIFacade.AddPanelToUIManagerDict(StringManager.GameLoadPanel);
        base.EnterScene();
    }

    public override void ExitScene()
    {
        base.ExitScene();
        SceneManager.LoadScene(2);
    }

}

其他测试场景:

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

public class NormalGameOptionSceneState : BaseSceneState
{
    public NormalGameOptionSceneState(UIFacade uIFacade) : base(uIFacade)
    {
    }

    public override void EnterScene()
    {
        mUIFacade.AddPanelToUIManagerDict(StringManager.GameNormalOptionPanel);
        mUIFacade.AddPanelToUIManagerDict(StringManager.GameNormalBigLevelPanel);
        base.EnterScene();
    }

    public override void ExitScene()
    {
        base.ExitScene();
    }

}

游戏面板类

面板接口和面板基类

public interface IBasePanel  {

    void InitPanel();
    void EnterPanel();
    void ExitPanel();
    void UpdatePanel();
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BasePanel : MonoBehaviour, IBasePanel
{
    protected UIFacade mUIFacade;

    protected virtual void Awake()
    {
        mUIFacade = GameManager.instance.uIManager.mUIFacade;
    }

    public virtual void EnterPanel()
    {
        
    }

    public virtual void ExitPanel()
    {

    }

    public virtual void InitPanel()
    {

    }

    public virtual void UpdatePanel()
    {
        
    }
}

开始场景面板

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class StartLoadPanel : BasePanel
{
    protected override void Awake()
    {
        base.Awake();
        Invoke("LoadNextScene", 2);
    }

    private void LoadNextScene()
    {
        mUIFacade.ChangeSceneState(new MainSceneState(mUIFacade));
    }

}

主场景游戏面板

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class MainPanel : BasePanel
{
    private Tween[] mainPanelTween = new Tween[2];//0.右,1.左
    private Tween ExitTween;//离开主页时运行的动画

    protected override void Awake()
    {
        base.Awake();

        mainPanelTween[0] = transform.DOLocalMoveX(1920, 0.5f);
        mainPanelTween[0].SetAutoKill(false);
        mainPanelTween[0].Pause();

        mainPanelTween[1] = transform.DOLocalMoveX(-1920, 0.5f);
        mainPanelTween[1].SetAutoKill(false);
        mainPanelTween[1].Pause();
    }

    public override void EnterPanel()
    {
        if (ExitTween != null)
        {
            ExitTween.PlayBackwards();
        }
    }

    public override void ExitPanel()
    {
        ExitTween.PlayBackwards();
    }

    public void MainPanelMoveToLeft()
    {
        ExitTween = mainPanelTween[0];
        ExitTween.Play();
        mUIFacade.currentScenePanelDict[StringManager.SetPanel].EnterPanel();
    }

    public void MainPanelMoveToRight()
    {
        ExitTween = mainPanelTween[1];
        ExitTween.Play();
        mUIFacade.currentScenePanelDict[StringManager.HelpPanel].EnterPanel();
    }

    public void ChangeToNoramlScene()
    {
        mUIFacade.currentScenePanelDict[StringManager.GameLoadPanel].EnterPanel();
        mUIFacade.ChangeSceneState(new NormalGameOptionSceneState(mUIFacade));
    }

}

帮助和设置面板

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class HelpPanel : BasePanel
{
    private Tween helpPanelTween;

    protected override void Awake()
    {
        base.Awake();
        helpPanelTween = transform.DOLocalMoveX(0, 0.5f);
        helpPanelTween.SetAutoKill(false);
        helpPanelTween.Pause();
        transform.SetSiblingIndex(5);
    }

    public override void InitPanel()
    {
        transform.localPosition = new Vector3(1920, 0, 0);
    }

    public override void EnterPanel()
    {
        helpPanelTween.PlayForward(); //移动到中心
    }

    public override void ExitPanel()
    {
        if (mUIFacade.currentSceneState.GetType() == typeof(NormalGameOptionSceneState))
        {
            helpPanelTween.PlayBackwards();
        }
        else
        {
            helpPanelTween.PlayBackwards();
            mUIFacade.currentScenePanelDict[StringManager.MainPanel].EnterPanel();
        }
    }

    public void ReutnToMainPanel()
    {
        helpPanelTween.PlayBackwards();
    }

}


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class SetPanel : BasePanel
{
    private Tween setPanelTween;

    protected override void Awake()
    {
        base.Awake();
        setPanelTween = transform.DOLocalMoveX(0, 0.5f);
        setPanelTween.SetAutoKill(false);
        setPanelTween.Pause();
        transform.SetSiblingIndex(2);
    }

    public override void InitPanel()
    {
        transform.localPosition = new Vector3(-1920, 0, 0);
    }

    public override void EnterPanel()
    {
        setPanelTween.PlayForward();
        
    }

    public override void ExitPanel()
    {
        setPanelTween.PlayBackwards();
        mUIFacade.currentScenePanelDict[StringManager.MainPanel].EnterPanel();
    }
}

 

 

 

 


版权声明:本文为weixin_44003309原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。