Unity学习记录8——“迷失岛2”场景切换

前言:最近逛某站,发现了一个宝藏老师~麦扣老师(M_Studio),然后呢~又又又在他主页看到了这个迷失岛教程,于是又开始了这个学习记录~学习永无止境~

一、场景创建

创建素材中的场景

SetActiveScene: 设置获得场景

UnloadScene:设置卸载场景

注:Persistent场景呢,我们用来放UI,数据管理物体(用来挂载数据管理的脚本),这样呢,方便我们更好地组织代码和逻辑~这样可以使代码更易于理解、维护和扩展~

然后,例如在H1场景下,创建一个GameObject物体,并加入碰撞体,用来实现鼠标检测碰撞,从而转移场景功能,同时,我们设置一个标签,后续用来判断是什么物体,执行什么功能

之后,我们打开File-Building Setting,把全部场景都载入

二、脚本部分

首先呢~我们创建一个场景枚举类

/// <summary>
/// 场景的枚举类型
/// </summary>
public enum SceneEnums
{
    H1,H2,H2A,H3,H4
}

接着创建场景转换类SceneTransititon

public class SceneTransition : MonoBehaviour
{
    public SceneEnums currentScene; // 当前场景
    public SceneEnums targetScene; // 目标场景

    public void MoveScene()
    {
        // 获取场景管理器
        ScenesManager.Instance.Transition(currentScene, targetScene);
    }

}

接着,我们创建一个统一管理场景转换类SceneManager~

注:采用单例模式~单例模式可以确保一个类只有一个实例,提供一个全局访问点,多个场景可以统一使用这个类~

先实现一个泛型单例的父类

using UnityEngine;

/// <summary>
///  泛型单例
/// </summary>
public class Singleton<T> : MonoBehaviour where T: Singleton<T>
{
    private static T instance; // 唯一实例

    // 向外提供
    public static T Instance 
    {
        get { return instance; }
    }

    // 是否创建
    public static bool IsInitialized
    {
        get { return instance != null; }
    }

    protected virtual void Awake()
    {
        // 要是不为空,表示已经存在一个单例 销毁
        if(instance != null)
        {
            Destroy(instance);
        }else
        {
            // 强转单例
            instance = (T)this;
        }
    }



    protected virtual void OnDestroy()
    {
        // 销毁当前单例
        if(instance == this)
        {
            instance = null;
        }
    }
}

接着实现一个SceneManager类,继承刚刚的单例父类,并挂载到Persistent场景中

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

/// <summary>
/// 场景转换管理脚本
/// </summary>
public class ScenesManager : Singleton<ScenesManager>
{

    public CanvasGroup fadePanel; // 淡出画布

    private bool isFade; // 判断是否淡出
    private float duration = 0.5f; // 淡出持续时间

    /// <summary>
    /// 场景转换
    /// </summary>
    /// <param name="currentScene"></param>
    /// <param name="targetScene"></param>
    public void Transition(SceneEnums currentScene, SceneEnums targetScene)
    {
        // 没有淡出时
        if (!isFade)
        {
            StartCoroutine(TransitionToScene(currentScene, targetScene));
        }
    }

    /// <summary>
    /// 场景转换协程
    /// </summary>
    /// <param name="currentScene"></param>
    /// <param name="targetScene"></param>
    /// <returns></returns>

    private IEnumerator TransitionToScene(SceneEnums currentScene, SceneEnums targetScene)
    {
        // 开始淡出
        yield return FadeAction(1);
        // 卸载当前场景 当前场景此时有persistent H1 0 1
        yield return SceneManager.UnloadSceneAsync(currentScene.ToString());
        // 加载新场景 场景:persistent 0
        yield return SceneManager.LoadSceneAsync(targetScene.ToString(), LoadSceneMode.Additive);
        // 获取新场景 场景: persitent H2 索引 0 1 
        Scene newScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
        // 激活场景
        SceneManager.SetActiveScene(newScene);
        // 结束淡出
        yield return FadeAction(0);
    }

    /// <summary>
    /// 淡出动画
    /// </summary>
    /// <param name="alpha"></param>
    /// <returns></returns>
    private IEnumerator FadeAction(float alpha)
    {
        isFade = true; // 正在淡出
        fadePanel.blocksRaycasts = true; // 隐藏鼠标点击
        // 淡出速度
        float speed = Mathf.Abs(fadePanel.alpha - alpha) / duration;
        // 当非常接近时
        while (!Mathf.Approximately(fadePanel.alpha, alpha))
        {
            // alpha值过渡
            fadePanel.alpha = Mathf.MoveTowards(fadePanel.alpha,alpha,speed * Time.deltaTime);
            yield return null;
        }
        fadePanel.blocksRaycasts = false;
        isFade = false;
    }
}

上面代码中关于淡出的操作:我们在Persistent场景中,创建一个UI——Canvas——Panel,Canvas如下设置

注:Scale with Screen Size 可以在不同屏幕分辨率下自动调整 UI 元素的缩放比例

Reference Resolution是它的基准

接着设置Panel

紧接着,我们创建一个CurSorManager脚本,用来检测我们鼠标是否与场景碰撞体是否方式碰撞,同时挂载到persistent场景上面的cursorManager物体上面

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

/// <summary>
/// 鼠标事件管理脚本
/// </summary>
public class CursorManager : MonoBehaviour
{
    // 更换鼠标坐标 => C# 6 引入的属性表达式体语法 默认只读
    private Vector3 mouseWorldPos => Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));

    // 判断是否可以点击
    private bool canClick;


    private void Update()
    {
        // 判断是否有场景转移碰撞体
        canClick = MouseCollider();
        if(canClick && Input.GetMouseButtonDown(0))
        {
            // 执行鼠标碰撞处理函数
            ClickAction(MouseCollider().gameObject); // MouseCollider().gameObject 函数返回的碰撞体
        }
    }

    /// <summary>
    /// 返回鼠标碰撞 该点是否存在碰撞体
    /// </summary>
    /// <returns></returns>
    private Collider2D MouseCollider()
    {
        return Physics2D.OverlapPoint(mouseWorldPos);
    }


    /// <summary>
    /// 鼠标碰撞处理
    /// </summary>
    /// <param name="clickObj">检测到的碰撞体</param>
    private void ClickAction(GameObject clickObj)
    {
        // 碰撞体上面的标签
        switch (clickObj.tag)
        {
            case "Scene":
                // 获取身上的脚本代码 var 声明变量而不显式指定变量的数据类型
                var scene = clickObj.GetComponent<SceneTransition>();
                // 执行函数
                scene.MoveScene();
                break;
        }
    }


}

三、效果展示

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值