Unity UGUI 问题汇总

前言

前段时间做了一个纯UI界面切换的项目,切换逻辑又比较复杂,几十个页面不同的动效,每个页面又有大量的图片和文字,使用UGUI与DOTween插件,遇到的一些问题记录下来。

问题

DOTween在UGUI中的移动问题

第一种情况

当一个UI父物体的RectTransform为全屏,如下图
父物体RectTransform
则他的子物体PosXPosYPosZ为本身的localPosition也就是SomeoneGameObject.transform.localPosition的值,故而使用SomeoneGameObject.transform.DOLocalMove是没有问题的。
子物体RectTransform
移动代码为

//移动localPosition
SomeoneGameObject.transform.DOLocalMove(SomeoneGameObject.transform.localPosition, 2f);

第二种情况

父物体的RectTransform不为全屏模式,如下图。
父物体RectTransform
此时子物体的PosXPosYPosZ为本身 SomeoneGameObject.GetComponent<RectTransform>().anchoredPosition的值。
子物体的RectTransform
此时的移动可以使用

//获取移动UI的RectTransform
RectTransform rectTransform = someoneObject.GetComponent<RectTransform>();
//获取当前的anchoredPosition
Vector2 myPos = rectTransform.anchoredPosition;
//设置结束位置
Vector2 endPos = Vector2.zero;
//使用DoTween让V2变量变化
DOTween.To(() => myPos, x => myPos= x, endPos, 1).OnUpdate(() =>
    {
    	//每帧进行位置赋值
        rectTransform.anchoredPosition = vector2;
    });

显示隐藏大界面时使用CanvasGroup而不是SetActive

SetActive会导致卡顿(当一个大界面在Enable时,需要重建大量内部数据,如Mask、Scroll View,导致了异常的卡顿,会卡主线程),而设置CanvasGroup则没有这个问题,带来的影响只是加载场景变慢一点,但是场景加载完毕后是流畅的。

//拿到CanvasGroup组件
CanvasGroup canvasGroup = SomeTransform.GetComponent<CanvasGroup>();
//获取当前透明度
float myFloat = canvasGroup.alpha;
//动画期间屏蔽点击
canvasGroup.interactable = false;
//动画期间使UI不阻挡鼠标(点击)事件
canvasGroup.blocksRaycasts = false;
//让myFloat从当前透明度过渡到1,用时2s
DOTween.To(() => myFloat, c => myFloat = c, 1f, 2).OnUpdate(() => {
			//每帧都要重新赋值透明度
            canvasGroup.alpha = myFloat;
        }).OnComplete(() => {
			//动画期间屏蔽点击
			canvasGroup.interactable = true;
			//动画期间使UI不阻挡鼠标(点击)事件
			canvasGroup.blocksRaycasts = true;
        }).SetEase(Ease.InOutQuad);

便捷的控制层级

当一个界面出现时,可以使用SomeoneGameObject.transform.SetAsLastSibling();将其列为最前方的一个,也就是Hierarchy中最靠下面的一个,反之SomeoneGameObject.transform.SetAsFirstSibling();会被放置到当前目录树的最顶上,也就是最下层。

CanvasGroup交叉显隐问题

当一个界面包含CanvasGroup而其子界面也包含CanvasGroup时,当父物体CanvasGroup与子物体CanvasGroupalpha同时改变的时候,需要注意,每个UI最终的透明度是由此值和自身的alpha数值相乘得到。此时可以勾选子物体CanvasGroup的Ignore Parent Groups忽略父级对象中的CanvasGroup的设置。
勾选Ignore Parent Groups

对添加Mask组件的UI进行透明度变化

需要取消勾选Show Mask Graphic,移除对Mask的渲染
取消勾选ShowMaskGraphic

异步场景切换延迟

当异步加载场景开始之前建议在IEnumerator中加一个小等待,尤其是大场景加载之前,否则会导致UI出不来或者逻辑卡顿问题(会卡到主线程,当你的场景足够大)。
附上一个简单的异步场景加载:

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

/// <summary>
/// 场景管理器
/// </summary>
public class ScenesManager : Singleton<ScenesManager>
{

    /// <summary>
    /// 将当前进度扔出去的方法Action
    /// </summary>
    public Action<int> loadProgressEvent;
    /// <summary>
    /// 场景加载结束Action
    /// </summary>
    public Action loadEndEvent;

    /// <summary>
    /// 加载场景的Async
    /// </summary>
    AsyncOperation loadSceneAsync;
    /// <summary>
    /// 虚假进度
    /// </summary>
    private int falseNumber;

    /// <summary>
    /// 外界获取的虚假进度
    /// </summary>
    public int FalseNumber
    {
        get {
            return falseNumber;
        }
        set {
            falseNumber = value; 
            loadProgressEvent?.Invoke(falseNumber); 
        } 
    }

    /// <summary>
    /// 要加载的场景名称
    /// </summary>
    private string loadSceneName;
    /// <summary>
    /// 真实进度
    /// </summary>
    private int trueNum = 0;


    /// <summary>
    /// 异步加载某一个场景
    /// </summary>
    /// <param name="scenename"></param>
    public void LoadScenes(string scenename)
    {
        loadSceneName = scenename;
        StartCoroutine(LoadScenesEnumerator());
    }
    /// <summary>
    /// 加载
    /// </summary>
    /// <returns></returns>
    IEnumerator LoadScenesEnumerator()
    {
    	//这里不等一下会卡主线
        yield return new WaitForSeconds(0.1f);
        loadSceneAsync = SceneManager.LoadSceneAsync(loadSceneName, LoadSceneMode.Single);
        // 禁止载入后自己切换
        loadSceneAsync.allowSceneActivation = false;

        while (loadSceneAsync.progress < 0.9f)
        {
            //加载进度
            trueNum = (int)(loadSceneAsync.progress * 100);
            while (FalseNumber < trueNum)
            {
                FalseNumber=FalseNumber+1;
                //等待时长
                yield return new WaitForSeconds(0.1f);
            }
        }
        trueNum = 100;
        //增加平滑效果
        while (FalseNumber < trueNum)
        {
            FalseNumber = FalseNumber + 1;
            //等待时长
            yield return new WaitForSeconds(0);
        }
        //加载场景激活 当虚假值完成后,才算加载完成
        loadSceneAsync.allowSceneActivation = true;
        yield return new WaitForSeconds(0.1f);
        LoadEndFunction();
    }
    /// <summary>
    /// 加载结束
    /// </summary>
    private void LoadEndFunction()
    {
        loadEndEvent?.Invoke();
        loadSceneAsync = null;
        //进度变0
        trueNum = 0;
        FalseNumber = 0;
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值