unity对话UI设置

思路

摆放好ui后用代码控制ui的图片和里面的文字

图片位置设置

这个设置图层位置

代码

using System.Collections;

using System.Collections.Generic;

using System.Data.Common;

using TMPro;

using UnityEngine;

using UnityEngine.UI;



public class TMp : MonoBehaviour

{

    /// <summary>

    /// 对话文本文件。.csv格式

    /// </summary>

    public TextAsset dialogDateFile;



    /// <summary>

    /// 左侧角色图像

    /// </summary>

    public SpriteRenderer spriteLeft;



    /// <summary>

    /// 右侧角色图像

    /// </summary>

    public SpriteRenderer spriteRight;



    /// <summary>

    /// 角色名字文本

    /// </summary>

    public TMP_Text nameText;



    /// <summary>

    /// 对话内容文本

    /// </summary>

    public TMP_Text dialogText;



    /// <summary>

    /// 角色图片列表

    /// 在unity里面手动添加可以

    /// </summary>

    public List<Sprite> sprites = new List<Sprite>();



    /// <summary>

    /// 角色名字对应图片的字典

    /// </summary>

    Dictionary<string,Sprite> imageDic = new Dictionary<string, Sprite>();



    /// <summary>

    /// 对话文本 按行分割

    /// </summary>

    public string[] dialogRows;



    /// <summary>

    /// 当前对话索引值

    /// </summary>

    private int dialogIndex;



    /// <summary>

    /// 对话继续按钮

    /// </summary>

    public Button nextButton;



    /// <summary>

    /// 选项预制体

    /// </summary>

    public GameObject optionButton;



    /// <summary>

    /// 选项父节点,用于自动排列

    /// </summary>

    public Transform buttonGroup;

    [Header("鱼")]

    public int yu;

    [Header("钱")]

    public int qian;

    private void Awake() {

        imageDic["渔夫"] = sprites[0];

        imageDic["剑客"]= sprites[1];

    }

   

    private void Start() {

        ReaText(dialogDateFile);

        ShowDialogRow();

        spriteRight.sprite = null;

        spriteLeft.sprite = null;

        // UpdateText("博士","这里是");

        // UpdateImage("渔夫",false);

    }

    public void UpdateText(string _name , string _text){

        nameText.text = _name;//人物名字

        dialogText.text = _text;//对话内容

    }

    public void UpdateImage(string _name,string _atLeft)//判断图片是否在左侧

    {

        if(_atLeft == "左"){

            spriteLeft.sprite = imageDic[_name];

            spriteRight.sprite = imageDic[_name];

        }

        else if(_atLeft == "右")

        {

            spriteRight.sprite = imageDic[_name];

            spriteLeft.sprite = imageDic[_name];

        }

    }

    public void ReaText(TextAsset _textAsset){

        dialogRows = _textAsset.text.Split('\n');//读取文件用Split('\n')分割

        Debug.Log("读取成功");

    }

    public void ShowDialogRow()

    {//dialogIndex是全局变量所以重新启动后dialogIndex还是变化后的值所以循环不会被打断

        for(int i = 0;i<dialogRows.Length;i++)

        {

            string[] cells = dialogRows[i].Split(',');

            //#条件时直接给对话框图片赋值

            if (cells[0]=="#" /*找判断条件*/&&int.Parse(cells[1]) == dialogIndex/*找id*/)

            {

                UpdateText(cells[2], cells[4]);//文本赋值

                UpdateImage(cells[2], cells[3]);//对话框赋值

                dialogIndex = int.Parse(cells[5]);//int.Parse()将内容转变为int类型赋值给对话索引

                nextButton.gameObject.SetActive(true);//显示回来

                break;

            }

            else if(cells[0]=="&" &&int.Parse(cells[1]) == dialogIndex){

                nextButton.gameObject.SetActive(false);

                GenerateOption(i);//需要传入的是第几列的值

            }

            else if(cells[0]=="END" &&int.Parse(cells[1]) == dialogIndex){

                nextButton.gameObject.SetActive(false);//显示回来

                spriteRight.sprite = null;

                spriteLeft.sprite = null;

                dialogText.text = "购买结束";

                Debug.Log("结束");

            }

        }

    }

    public void OnclickNext()//继续按键按下后执行的事件

    {

        ShowDialogRow();

    }

    public void GenerateOption(int _index)

    {

        string[] cells = dialogRows[_index].Split(',');

        if(cells[0] =="&")

        {

            GameObject button = Instantiate(optionButton,buttonGroup);

            //绑定按钮事件

            //button.GetComponentInChildren<TextMeshPro>().text= cells[4];//子物体的TextMeshPro

            TextMeshProUGUI textMeshPro = button.GetComponentInChildren<TextMeshProUGUI>();

            if (textMeshPro != null)  

            {  

                // 绑定按钮的文本  

                textMeshPro.text = cells[4];  

            }  

            else  

            {  

                // 处理TextMeshPro组件不存在的情况  

                Debug.LogError("TextMeshProUGUI component not found on the button or its children.");  

            }  

            button.GetComponent<Button>().onClick.AddListener(()=>

            {

                OnOptionClick(int.Parse(cells[5]));//赋值跳转的id

                //增加效果

                if(cells[6]!= ""&& cells[6].Contains("@"))

                {

                    string[] strings = cells[6].Split("@");

                    OptionEffect(strings[0],int.Parse(strings[1]));

                }

            });

            GenerateOption(_index+1);//生成多个预制体按钮

        }

    }

    //销毁选项

    public void OnOptionClick(int _id){

        dialogIndex=_id;

        ShowDialogRow();

        for (int i = 0 ;i <buttonGroup.childCount;i++){

            Destroy(buttonGroup.GetChild(i).gameObject);

        }

    }

    //效果部分

    public void OptionEffect(string effect ,int zhi){

        if (effect=="鱼"){yu+=1;}

        if (effect=="钱"){qian+=1;}

    }

}

<think>我们正在讨论UnityUI长度的设置方法。根据之前的对话历史,用户遇到了设置localPosition为(0,0,0)但检查器显示不为零的问题,现在用户想了解Unity设置UI长度的方法。 结合引用内容,我们知道: 1. UGUIUnity自带的UI系统,基于游戏对象(引用[1])。 2. 使用布局组件(如Horizontal Layout Group)可以同步多个UI对象的长度(引用[2])。 3. 当父物体使用布局组时,克隆UI对象可能导致尺寸丢失,需要手动设置尺寸(引用[3])。 因此,设置UI长度的方法有多种,根据使用场景选择: ### 方法1:直接设置RectTransform的尺寸 适用于不使用布局组的情况。 ```csharp RectTransform rectTransform = GetComponent<RectTransform>(); // 设置宽度为100,高度不变 rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 100); // 或使用sizeDelta(注意:依赖于锚点配置) // rectTransform.sizeDelta = new Vector2(100, rectTransform.sizeDelta.y); ``` **注意事项**: - `sizeDelta`表示尺寸变化量,具体含义取决于锚点: - 当锚点拉伸(锚点Min和Max不同)时,`sizeDelta = (总宽度, 总高度)` - 当锚点固定(如居中)时,`sizeDelta = (宽, 高)` - 优先使用`SetSizeWithCurrentAnchors`方法避免锚点混淆。 ### 方法2:使用Content Size Fitter组件 适用于根据内容自动调整尺寸。 1. 添加`Content Size Fitter`组件到UI对象 2. 设置水平/垂直方向为`Preferred Size`(根据子物体)或`Min Size` **示例**:使文本宽度自适应内容 ```csharp // 添加组件 ContentSizeFitter fitter = gameObject.AddComponent<ContentSizeFitter>(); fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; ``` ### 方法3:使用布局组(Layout Group) 适用于统一管理多个子UI的尺寸(引用[2])。 1. 在父物体添加布局组件(如`HorizontalLayoutGroup`) 2. 勾选`Control Child Size`控制子物体尺寸 ```csharp HorizontalLayoutGroup layout = parent.AddComponent<HorizontalLayoutGroup>(); layout.childControlWidth = true; // 控制子物体宽度 layout.childControlHeight = false; // 不控制高度 ``` ### 方法4:克隆UI时手动设置尺寸 当从带有布局组的UI克隆对象时,需手动恢复尺寸(引用[3])。 ```csharp public RectTransform CloneUI(RectTransform original, Transform parent) { RectTransform clone = Instantiate(original, parent); // 重置尺寸(避免布局组导致尺寸为0) clone.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, original.rect.width); clone.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, original.rect.height); return clone; } ``` ### 关键概念:锚点(Anchors)与轴心(Pivot) - **锚点**:定义UI边角相对于父物体边界的定位方式 - 锚点重合时:UI尺寸由`sizeDelta`直接决定 - 锚点分离时:UI尺寸由父物体尺寸和`sizeDelta`共同决定 - **轴心**:旋转和缩放的中心点,不影响尺寸计算 ### 尺寸设置流程图 ```mermaid graph TD A[需要设置UI长度] --> B{是否使用布局系统?} B -- 是 --> C[使用LayoutGroup控制] B -- 否 --> D{是否需要自适应内容?} D -- 是 --> E[使用ContentSizeFitter] D -- 否 --> F[直接设置RectTransform尺寸] F --> G[注意锚点配置] ``` ### 常见问题解决方案 1. **设置尺寸后UI变形**:检查锚点是否拉伸,改用`SetSizeWithCurrentAnchors`方法 2. **布局组覆盖手动设置**:临时禁用布局组件或使用`LayoutElement`覆盖设置 ```csharp LayoutElement layoutElement = GetComponent<LayoutElement>(); layoutElement.preferredWidth = 100; // 覆盖布局组的宽度设置 ``` 3. **动态内容尺寸更新延迟**:调用`Canvas.ForceUpdateCanvases()`强制刷新布局 ### 最佳实践 - 优先使用RectTransform的锚点预设(如Top-Stretch)简化布局 - 需要精确控制尺寸时,使用`SetSizeWithCurrentAnchors(RectTransform.Axis, float)` - 避免同时使用多个冲突的布局控制方式(如ContentSizeFitter+手动设置) §§相关问题§§ 1. Unity中如何实现UI元素的等比例缩放? 2. 如何使ScrollView内容区域的高度根据子物体数量动态调整? 3. LayoutElement组件在UI布局中的作用是什么? 4. 如何解决Canvas刷新时UI位置闪烁的问题? 5. 如何在UGUI中创建响应不同屏幕尺寸的自适应UI? </think>### Unity设置UI长度的方法详解 在Unity UGUI系统中,设置UI元素的长度(宽度或高度)主要有以下方法: #### 1. **直接设置RectTransform尺寸** ```csharp // 获取RectTransform组件 RectTransform rt = GetComponent<RectTransform>(); // 方法1:设置具体尺寸 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 200f); // 宽度200 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 150f); // 高度150 // 方法2:使用sizeDelta(需考虑锚点配置) rt.sizeDelta = new Vector2(200f, 150f); // (宽度,高度) ``` **注意**:`sizeDelta`的实际效果取决于锚点配置。当锚点分离时(如左右拉伸),它表示相对于锚点位置的额外尺寸;当锚点重合时(如居中),它直接表示UI尺寸[^3]。 #### 2. **使用Content Size Fitter组件** 添加`Content Size Fitter`组件可实现自动尺寸调整: ```csharp ContentSizeFitter fitter = gameObject.AddComponent<ContentSizeFitter>(); fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; // 水平自适应 fitter.verticalFit = ContentSizeFitter.FitMode.Unconstrained; // 垂直不约束 ``` **适用场景**: - 文本/图片等根据内容自动调整宽度 - 需要动态适应内容变化的UI元素[^1] #### 3. **使用Layout Group组件** 在父物体添加布局组件可批量控制子物体尺寸: ```csharp // 添加水平布局组件到父物体 HorizontalLayoutGroup layout = parent.AddComponent<HorizontalLayoutGroup>(); layout.childControlWidth = true; // 控制子物体宽度 layout.childControlHeight = false; // 不控制高度 layout.childForceExpandWidth = true; // 子物体宽度填充可用空间 ``` **特点**: - 自动同步所有子物体的尺寸 - 适用于菜单、列表等统一布局的场景[^2] #### 4. **通过锚点(Anchors)设置** 在Inspector中可视化设置: ```csharp // 代码设置锚点范围(左下角0,0 到右上角1,1) rt.anchorMin = new Vector2(0.2f, 0); rt.anchorMax = new Vector2(0.8f, 1); ``` **效果**: - UI宽度将自动占父物体宽度的60% - 高度将填充父物体100%高度 #### 5. **特殊场景:克隆UI元素** 当从布局组克隆UI时,需手动恢复尺寸: ```csharp RectTransform CloneUI(RectTransform original) { RectTransform clone = Instantiate(original, parent); clone.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, original.rect.width); clone.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, original.rect.height); return clone; } ``` 这是因为布局组件会重置克隆体的尺寸[^3]。 --- ### 尺寸设置流程图 ```mermaid graph TD A[设置UI长度] --> B{使用布局系统?} B -->|是| C[使用LayoutGroup] B -->|否| D{需要自适应内容?} D -->|是| E[使用ContentSizeFitter] D -->|否| F[直接设置RectTransform] C --> G[注意克隆时需手动重置尺寸] F --> H[检查锚点配置] ``` --- ### 最佳实践建议 1. **优先使用锚点系统**:适应不同屏幕尺寸 2. **布局组与尺寸过滤器组合**: ```csharp // 父物体:Vertical Layout Group // 子物体:Content Size Fitter + LayoutElement LayoutElement le = child.AddComponent<LayoutElement>(); le.preferredWidth = 100; // 覆盖布局组的默认尺寸 ``` 3. **动态调整时刷新布局**: ```csharp Canvas.ForceUpdateCanvases(); // 强制立即更新布局 LayoutRebuilder.ForceRebuildLayoutImmediate(parentRT); ``` --- ### 常见问题解决 1. **设置尺寸无效**: - 检查父物体是否有布局组件覆盖 - 确认是否在动画系统中被覆盖 - 使用`SetSizeWithCurrentAnchors`替代直接赋值 2. **克隆后尺寸丢失**: ```csharp // 克隆后立即设置尺寸 clone.rect.Set(0, 0, original.rect.width, original.rect.height); ``` 3. **获取正确尺寸时机**: ```csharp IEnumerator Start() { yield return new WaitForEndOfFrame(); Debug.Log(rt.rect.width); // 此时获得最终尺寸 } ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值