Unity引擎2D游戏开发,场景淡入淡出效果

非强专业性文章,本文仅供学习与交流使用

淡入淡出的实现逻辑

在Persistent中,创建一个新的Canvas,命名为Fade Canvas

注意它的Sort Oder属性,该属性值越大,图层优先级越高,可以遮蔽屏幕上的任何图层

接着在Fade Canvas 中,新建一个Image,命名为Fade Image

Anchor Presets窗口中,按住alt+shift键,选中右下角,即可填充整个屏幕

那么这时候,调整Color属性中的alpha值,即可实现淡入效果

取消勾选Raycast Target。该属性会导致遮蔽的时候会将UI按钮给遮蔽,无法正常点击不该遮蔽的按钮

代码实现

从assetstore上,下载导入DOTween插件

assetstore.unity.com/packages/to...

然后将其import导入到项目当中,点击Setup DOTween

在Documentation文档当中,即将使用的就是DOBlendableColor()方法。可以通过一定的时间转换到一个指定的颜色上

现在就需要通过Scriptable跨脚本调用事件的方式来实现该功能。因为淡入淡出效果是要在SceneLoader脚本中进行代码实现,而当前Canvas调整是在Fade Canvas脚本中实现的

在FadeCanvas中,创建一个OnFadeEvent()事件,内部调用Image的DOBlendableColor()方法

c# 复制代码
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

public class FadeCanvas : MonoBehaviour
{
    public Image fadeImage;

    /// <summary>
    /// 淡入淡出事件
    /// </summary>
    /// <param name="targetColor">转换的目标颜色</param>
    /// <param name="duration">动画时间</param>
    private void OnFadeEvent(Color targetColor, float duration)
    {
        fadeImage.DOBlendableColor(targetColor, duration);
    }
}

在ScriptableObject中创建FadeEventSO脚本

创建UnityAction对象的OnEventRaised变量,然后创建RaiseEvent()方法,携带三个必要的参数在内部调用OnEventRaised事件的Invoke方法

之后,创建FadeIn和FadeOut方法,调用RaiseEvent方法,注意这时候分别传入不同的布尔值,如果为true,则启动淡入效果,反之,则淡出效果

c# 复制代码
using UnityEngine;
using UnityEngine.Events;

[CreateAssetMenu(menuName = "Event/FadeEventSO")]
public class FadeEventSO : ScriptableObject
{
    public UnityAction<Color, float, bool> OnEventRaised;

    /// <summary>
    /// 逐渐变黑
    /// </summary>
    /// <param name="duration"></param>
    public void FadeIn(float duration)
    {
        // 启动事件订阅的函数方法
        RaiseEvent(Color.black, duration, true);
    }

    /// <summary>
    /// 逐渐透明
    /// </summary>
    /// <param name="duration"></param>
    public void FadeOut(float duration) 
    {
        RaiseEvent(Color.clear, duration, false);
    }

    public void RaiseEvent(Color targetColor, float duration, bool fadeType)
    {
        OnEventRaised?.Invoke(targetColor, duration, fadeType);
    }
}

在SceneLoader脚本中,修改两处地方,分别调用FadeInFadeOut实现淡入淡出效果

c# 复制代码
public FadeEventSO fadeEventSO;

private IEnumerator UnloadPreviousScene()
{
    if (fadeScreen)
    {
        // 实现淡入
        fadeEventSO.FadeIn(fadeTime);
    }
    // 等待淡入淡出的指定时间
    yield return new WaitForSeconds(fadeTime);
    // 非空判断
    yield return currentLoadScene.assetReference.UnLoadScene();
    // 关闭人物
    playerTrans.gameObject.SetActive(false);

    LoadNewScene();
}
c# 复制代码
private void OnLoadComplete(AsyncOperationHandle<SceneInstance> handle)
{
    currentLoadScene = targetSceneToGo;

    playerTrans.position = targetPositionToGo;
    // 启动人物
    playerTrans.gameObject.SetActive(true);

    if (fadeScreen)
    {
        // 实现淡出
        fadeEventSO.FadeOut(fadeTime);
    }
    // 加载完毕,则把标识置为false
    isLoading = false;
    // 场景加载完成后的事件
    afterSceneLoadedEvent.RaiseEvent();
}

之后,在FadeCanvas脚本中,添加事件监听的变量

c# 复制代码
[Header("事件监听")]
public FadeEventSO fadeEvent;

再对其创建注册和销毁的方法

c# 复制代码
private void OnEnable()
{
    fadeEvent.OnEventRaised += OnFadeEvent;
}

private void OnDisable()
{
    fadeEvent.OnEventRaised -= OnFadeEvent;
}

注意修改下OnFadeEvent()方法的参数

c# 复制代码
/// <summary>
/// 淡入淡出事件
/// </summary>
/// <param name="targetColor">转换的目标颜色</param>
/// <param name="duration">动画时间</param>
/// <param name="fadeType">动画类型</param>
private void OnFadeEvent(Color targetColor, float duration, bool fadeType)
{
    fadeImage.DOBlendableColor(targetColor, duration);
}

在Events文件夹中,创建FadeEventSO

拖入到SceneLoad ManagerFade Cavas指定的属性中,注意FadeImage也要选择指定的实体对象

注意调整Fade Time,给一个合适的时间,即可实现淡入淡出效果

解决传送过程中仍然能操作的问题

SceneLoader脚本内,添加一个事件,携带一个布尔值参数,标志着是否正在传送

c# 复制代码
public UnityEvent<bool> playerTeleport;

OnLoadRequestEvent()启动传送的方法内,添加一行代码进行事件的广播,见13行

c# 复制代码
private void OnLoadRequestEvent(GameSceneSO sceneToGo, Vector3 positionToGo, bool fadeScreen)
{
    // 如果正在加载,则不执行加载过程中的任何操作
    if (isLoading)
    {
        return;
    }
    isLoading = true;
    targetSceneToGo = sceneToGo;
    targetPositionToGo = positionToGo;
    this.fadeScreen = fadeScreen;
    // 传送事件,传入一个是否正在加载的布尔值给PlayerControl脚本的指定方法内
    playerTeleport?.Invoke(isLoading);

    // 卸载当前场景,装载下一个场景
    if (currentLoadScene != null)
    {
        StartCoroutine(UnloadPreviousScene());
    } else
    {
        LoadNewScene();
    }
}

再在OnLoadComplete()传送完毕的方法内,添加一行代码,再一次广播事件

c# 复制代码
private void OnLoadComplete(AsyncOperationHandle<SceneInstance> handle)
{
    currentLoadScene = targetSceneToGo;

    playerTrans.position = targetPositionToGo;
    // 启动人物
    playerTrans.gameObject.SetActive(true);
    // 加载完毕,则把标识置为false
    isLoading = false;
    // 场景加载完成后的事件
    afterSceneLoadedEvent.RaiseEvent();
    if (fadeScreen)
    {
        // 实现淡出
        fadeEventSO.FadeOut(fadeTime);
    }
    // 传送完毕,再一次广播事件
    playerTeleport?.Invoke(isLoading);
}

在PlayerController脚本内,添加一个PlayerTeleporting()方法,在里面判断布尔值,是否正在传送

如果正在传送,则禁止Input操作,反之,启动操作

c# 复制代码
/// <summary>
/// 玩家正常传送中,禁止一切操作
/// </summary>
public void PlayerTeleporting(bool isLoading)
{
    if (isLoading)
    {
        playerInputControl.Gameplay.Disable();
    } else
    {
        playerInputControl.Gameplay.Enable();
    }
    
}

最后一步,在面板上,选择Player,并在旁边选择PlayerController的PlayerTeleporting()方法进行监听

相关推荐
技术小甜甜18 小时前
【Blender Texture】【游戏开发】高质感 Blender 4K 材质资源推荐合集 —— 提升场景真实感与美术表现力
blender·游戏开发·材质·texture
Thomas游戏开发1 天前
Unity3D TextMeshPro终极使用指南
前端·unity3d·游戏开发
Thomas游戏开发2 天前
Unity3D 逻辑代码性能优化策略
前端框架·unity3d·游戏开发
Thomas游戏开发3 天前
Unity3D HUD高性能优化方案
前端框架·unity3d·游戏开发
陈哥聊测试4 天前
游戏公司如何同时管好上百个游戏项目?
游戏·程序员·游戏开发
一名用户5 天前
unity随机生成未知符号教程
c#·unity3d·游戏开发
Be_Somebody10 天前
计算机图形学——Games101深度解析_第二章
游戏开发·计算机图形学·games101
GameTomato10 天前
【IOS】【OC】【应用内打印功能的实现】如何在APP内实现打印功能,连接本地打印机,把想要打印的界面打印成图片
macos·ios·objective-c·xcode·游戏开发·cocos2d
Be_Somebody11 天前
计算机图形学——Games101深度解析_第一章
游戏开发·计算机图形学·games101
Thomas_YXQ17 天前
Unity3D HUD UI性能优化方案
开发语言·ui·搜索引擎·性能优化·全文检索·unity3d