首页 > 解决方案 > Unity:如何使用 C# 使 Canvas UI 响应所有屏幕

问题描述

我是 Unity 的新手。如何使 Canvas UI 像小按钮的小屏幕和大按钮的大屏幕一样具有响应性。但是当我测试小屏幕中的小按钮很大而大按钮是大屏幕时很小。我只是想扭转这个,所以它会响应,有可能做到吗?

标签: c#unity3duser-interfaceunity-container

解决方案


在 Unity UI 中实现完全可扩展设计的诀窍是永远不要对任何东西使用像素大小。Start 将所有矩形完全展开(所有边距为 0)并使用锚点按您的方式工作(使用 alt 强制边距归零)

锚定

我还可以推荐一个我写的RectAnchorHelper的小工具。如果您点击链接,您可能会收到 [exposemethodineditor] 依赖项的错误,只需将其注释掉,或下载整个 repo。我正在粘贴完整的类代码,并在下面剥离了依赖项。

RectAnchorHelper 做了什么,它公开了四个滑块,可让您以完全比例的方式调整您的位置,因此您可以在不参考像素大小的情况下设计您的 UI。

在此处输入图像描述

等式的另一部分是使用设置为 Scale with Screen Size 的画布缩放器,如 Rakib 所述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif

[ExecuteInEditMode]
public class RectAnchorHelper : MonoBehaviour
{
    RectTransform rect { get { if (_rect == null) _rect = GetComponent<RectTransform>(); return _rect; } }
    RectTransform _rect;
    [SerializeField] bool edit;
    [SerializeField] bool _symmetricalXMode;
    [SerializeField] bool _symmetricalYMode;
    public bool symmetricalXMode { get { return _symmetricalXMode; } set { _symmetricalXMode = value; CheckAndSet(); } }

    public bool symmetricalYMode { get { return _symmetricalYMode; } set { _symmetricalYMode = value; CheckAndSet(); } }

    [Range(0, 1)]
    [SerializeField] float _xAnchorMin;
    [Range(0, 1)]
    [SerializeField] float _xAnchorMax = 1;
    [Range(0, 1)]
    [SerializeField] float _yAnchorMin;
    [Range(0, 1)]
    [SerializeField] float _yAnchorMax = 1;
    public float xAnchorMin { get { return _xAnchorMin; } set { _xAnchorMin = value; CheckAndSet(); } }

    public float xAnchorMax { get { return _xAnchorMax; } set { _xAnchorMax = value; CheckAndSet(); } }

    public float yAnchorMin { get { return _yAnchorMin; } set { _yAnchorMin = value; CheckAndSet(); } }

    public float yAnchorMax { get { return _yAnchorMax; } set { _yAnchorMax = value; CheckAndSet(); } }

    // [SerializeField] [HideInInspector] Vector2 offsetMin;
    // [SerializeField] [HideInInspector] Vector2 offsetMax;
    public void SetMargin(float f) { margin = f; }

    [Range(-1, 15)]
    [SerializeField] float _margin = -1;
    public float margin { get { return _margin; } set { _margin = value; CheckAndSet(); } }
    void CheckAndSet()
    {
        if (symmetricalXMode) _xAnchorMax = 1 - _xAnchorMin;
        if (symmetricalYMode) _yAnchorMax = 1 - _yAnchorMin;
        SetValues();

    }
    void Reset()
    {
        PrepareRect();
        GetValues();
    }
    void OnValidate()
    {
        if (symmetricalXMode) xAnchorMax = 1 - xAnchorMin;
        if (symmetricalYMode) yAnchorMax = 1 - yAnchorMin;
        //      if (Application.isPlaying) return;
#if UNITY_EDITOR
        bool isSelected = false;
        foreach (var s in Selection.gameObjects)
        {
            if (s == gameObject) isSelected = true;
        }
        if (!isSelected) { edit = false; return; }
        Undo.RecordObject(rect, "RectAnchor");
#endif
        if (edit)
        {
            SetValues();
        }
        else
            GetValues();
    }

    void SetValues()
    {
        rect.anchorMin = new Vector2(xAnchorMin, yAnchorMin);
        rect.anchorMax = new Vector2(xAnchorMax, yAnchorMax);
        if (margin != -1)
        {
            rect.offsetMin = new Vector2(margin * margin, margin * margin);
            rect.offsetMax = new Vector2(-(margin * margin), -(margin * margin));
        }
    }
    void GetValues()
    {
        _xAnchorMin = rect.anchorMin.x;
        _xAnchorMax = rect.anchorMax.x;
        _yAnchorMin = rect.anchorMin.y;
        _yAnchorMax = rect.anchorMax.y;
    }

    void PrepareRect()
    {
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMax = Vector2.zero;
        rect.offsetMin = Vector2.zero;
        rect.localScale = Vector3.one;
    }
}

当然,您可以在没有我的课程的情况下完成这一切,但我个人发现输入浮点值相当乏味,上面的代码将为您提供滑块,使您可以轻松进行可视化编辑。


推荐阅读