U3D游戏开发按钮相关

有一天一个小伙伴跟我说,对于按钮相关网络某些教程并不全面,我大致看了,几乎差不多,接下来就大致补充一点代码相关的知识点了,还有我日常开发常用的一些按钮相关代码知识。

目录

1.UGUI的普通按钮相关

2.UGUI的异型按钮相关

3.NGUI按钮相关(需要下载导入NGUI)

4.UI基础框架相关(UGUI)

5.UGUI框架的使用--制作一个简易的提示管理器


(打码比较快,如果有小错误请指正,可能是误写,感谢!)

1.UGUI的普通按钮相关

代码控制相关的按钮参数

cs 复制代码
Button btn=this.GetComponent<Button>();
//按钮相关的参数可以被点出来使用
btn.interactable=true;

通过点击事件拖拽脚本检测按钮,在脚本中写上代码,然后把按钮事件拖拽到相应的按钮之下

cs 复制代码
public void ClickBtn()
{
//中间写上按钮逻辑
}

通过代码直接添加(通过代码添加的方式是我最经常使用的,你可以在场景中直接拖拽代码,也可以脚本控制查找对应的按钮)

1.拖拽结合lambda表达式的形式

cs 复制代码
//直接拖拽按钮
public Button btnClose;
//一般在Start函数之中添加
btnClose.onClick.AddListener(()=>
{
//结合lambda表达式的代码逻辑
});

2.拖拽

cs 复制代码
//以下代码在Start函数之中写入
btn.onClick.AddListener(ClickBtn);

//以下写入按钮逻辑
private void ClickBtn()
{
//写入按钮点击逻辑
}

3.代码识别

代码识别就可以直接使用private,然后代码查找按钮,按钮不能是未被显示的

GameObject.Find("btnClose");

其他的如上图所示。

4.按钮代码移出委托

cs 复制代码
btn.onClick.RemoveListener(ClickBtn);
//移出全部的
btn.onClick.RemoveAllListener();

2.UGUI的异型按钮相关

异形按钮就不是方方正正的按钮,是各种各样形状的。

方法一:拼凑法

通过多个透明图片拼凑出一个异形按钮用于射线检测。

方式二:代码相关

第一步:修改图片参数,开启Read/Write Enabled开关

第二步:通过代码修改图片的相应阙值(当alpha值小于该值就不会被射线检测了)

img.alphaHitTestMinimumThreshold=0.1f;(外部关联image)

3.NGUI按钮相关(需要下载导入NGUI)

制作NGUI按钮,一个Sprite(需要文字的话就再添加一个label子对象),为其添加Button脚本,添加碰撞器。

代码获取对象

cs 复制代码
public UIButton btn;
btn.onClick.Add(new EventDelegate(Click1));
//使用lambda表达式做处理
btn.onClick.Add(new EventDelegate(()=>
{
//中间写上逻辑
}));

4.UI基础框架相关(UGUI)

1.基本的面板框架,可以实现面板预设体的淡入淡出

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

/// <summary>
/// 面板基类
/// </summary>
public class BasePanel : MonoBehaviour
{
    //整体控制淡入淡出的画布组件
    private CanvasGroup canvasGroup;
    //淡入淡出的速度
    public float alphaSpeed = 8;
    //是否一开始要显示
    private bool isShow;
    private Dictionary<string,List<UIBehaviour>> controlDic= new Dictionary<string,List<UIBehaviour>>();
    // Start is called before the first frame update
    protected virtual void Awake()
    {
        FindChildrenControl<Button>();
        FindChildrenControl<Text>();
        FindChildrenControl<Image>();
        FindChildrenControl<Toggle>();
        FindChildrenControl<Slider>();
        FindChildrenControl<ScrollRect>();
        FindChildrenControl<InputField>();

        canvasGroup = this.GetComponent<CanvasGroup>();
        if (canvasGroup == null)
            canvasGroup = this.gameObject.AddComponent<CanvasGroup>();
    }

    /// <summary>
    /// 显示自己
    /// </summary>
    public virtual void ShowMe(object[] o = null)
    {
        isShow = true;
        canvasGroup.alpha = 0;
    }

    /// <summary>
    /// 隐藏自己
    /// </summary>
    public virtual void HideMe()
    {
        isShow = false;
        canvasGroup.alpha = 1;
    }

    /// <summary>
    /// 按钮点击
    /// </summary>
    /// <param name="btnName"></param>
    protected virtual void OnClick(string btnName)
    {

    }

    /// <summary>
    /// 勾选框触发
    /// </summary>
    /// <param name="toggleName"></param>
    /// <param name="value"></param>
    protected virtual void OnValueChanged(string toggleName,bool value)
    {

    }

    // Update is called once per frame
    public virtual void Update()
    {
        if ((canvasGroup == null))
        {
            return;
        }
        //淡入
        if (isShow && canvasGroup.alpha != 1)
        {
            canvasGroup.alpha += alphaSpeed * Time.deltaTime;
            if (canvasGroup.alpha >= 1)
                canvasGroup.alpha = 1;
        }
        //淡出
        else if (!isShow)
        {
            canvasGroup.alpha -= alphaSpeed * Time.deltaTime;
            if (canvasGroup.alpha <= 0)
            {
                canvasGroup.alpha = 0;
                //  hideCallBack?.Invoke();
            }
        }
    }

    /// <summary>
    /// 得到对应名字的对应控件脚本
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="controlName"></param>
    /// <returns></returns>
    protected T GetControl<T>(string controlName)where T:UIBehaviour
    {
        if(controlDic.ContainsKey(controlName))
        {
            for(int i = 0; i < controlDic[controlName].Count;++i)
            {
                if (controlDic[controlName][i] is T)
                    return controlDic[controlName][i] as T;
            }
        }
        return null;
    }
  
    private void FindChildrenControl<T>() where T:UIBehaviour
    {
        T[] controls= this.GetComponentsInChildren<T>();
        for(int i=0;i<controls.Length;++i)
        {
            string objName = controls[i].gameObject.name;
            if (controlDic.ContainsKey(objName))
                controlDic[objName].Add(controls[i]);
            else
                controlDic.Add(objName, new List<UIBehaviour>() { controls[i] });
            //如果是按钮控件
            if (controls[i] is Button)
            {
                (controls[i] as Button).onClick.AddListener(() =>
                {
                    OnClick(objName);
                });
            }
            //如果是单选框或者多选框
            else if (controls[i] is Toggle)
            {
                (controls[i] as Toggle).onValueChanged.AddListener((value) =>
                {
                    OnValueChanged(objName, value);
                });
            }
        }
    }
}

2.UIManager

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

/// <summary>
/// UI层级
/// </summary>
public enum E_UI_Layer
{
    Bot,
    Mid,
    Top,
    System,
}

/// <summary>
/// UI管理器
/// 1.管理所有显示的面板
/// 2.提供给外部 显示和隐藏等等接口
/// </summary>
public class UIManager : BaseManager<UIManager>
{
    public Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();

    private Transform bot;
    private Transform mid;
    private Transform top;
    private Transform system;

    //记录我们UI的Canvas父对象 方便以后外部可能会使用它
    public RectTransform canvas;

    public UIManager()
    {
        //创建Canvas 让其过场景的时候 不被移除
        GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");
        canvas = obj.transform as RectTransform;
        GameObject.DontDestroyOnLoad(obj);

        //找到各层
        bot = canvas.Find("Bot");
        mid = canvas.Find("Mid");
        top = canvas.Find("Top");
        system = canvas.Find("System");

        //创建EventSystem 让其过场景的时候 不被移除
        obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");
        GameObject.DontDestroyOnLoad(obj);
    }

    /// <summary>
    /// 通过层级枚举 得到对应层级的父对象
    /// </summary>
    /// <param name="layer"></param>
    /// <returns></returns>
    public Transform GetLayerFather(E_UI_Layer layer)
    {
        switch(layer)
        {
            case E_UI_Layer.Bot:
                return this.bot;
            case E_UI_Layer.Mid:
                return this.mid;
            case E_UI_Layer.Top:
                return this.top;
            case E_UI_Layer.System:
                return this.system;
        }
        return null;
    }

    /// <summary>
    /// 显示面板
    /// </summary>
    /// <typeparam name="T">面板脚本类型</typeparam>
    /// <param name="panelName">面板名</param>
    /// <param name="layer">显示在哪一层</param>
    /// <param name="callBack">当面板预设体创建成功后 你想做的事</param>
    public void ShowPanel<T>(string panelName, E_UI_Layer layer = E_UI_Layer.Mid, UnityAction<T> callBack = null) where T:BasePanel
    {
        if (panelDic.ContainsKey(panelName))
        {
            panelDic[panelName].ShowMe();
            // 处理面板创建完成后的逻辑
            if (callBack != null)
                callBack(panelDic[panelName] as T);
            //避免面板重复加载 如果存在该面板 即直接显示 调用回调函数后  直接return 不再处理后面的异步加载逻辑
            return;
        }

        ResMgr.GetInstance().LoadAsync<GameObject>("UI/" + panelName, (obj) =>
        {
            //把他作为 Canvas的子对象
            //并且 要设置它的相对位置
            //找到父对象 你到底显示在哪一层
            Transform father = bot;
            switch(layer)
            {
                case E_UI_Layer.Mid:
                    father = mid;
                    break;
                case E_UI_Layer.Top:
                    father = top;
                    break;
                case E_UI_Layer.System:
                    father = system;
                    break;
            }
            //设置父对象  设置相对位置和大小
            obj.transform.SetParent(father);

            obj.transform.localPosition = Vector3.zero;
            obj.transform.localScale = Vector3.one;

            (obj.transform as RectTransform).offsetMax = Vector2.zero;
            (obj.transform as RectTransform).offsetMin = Vector2.zero;

            //得到预设体身上的面板脚本
            T panel = obj.GetComponent<T>();
            // 处理面板创建完成后的逻辑
            if (callBack != null)
                callBack(panel);

            panel.ShowMe();
            if (!panelDic.ContainsKey(panelName))
            {
               //把面板存起来
               panelDic.Add(panelName, panel);
            }
            
        });
    }

    /// <summary>
    /// 隐藏面板
    /// </summary>
    /// <param name="panelName"></param>
    public void HidePanel(string panelName)
    {
        if(panelDic.ContainsKey(panelName))
        {
            panelDic[panelName].HideMe();
            GameObject.Destroy(panelDic[panelName].gameObject);
            panelDic.Remove(panelName);
        }
    }

    /// <summary>
    /// 得到某一个已经显示的面板 方便外部使用
    /// </summary>
    public T GetPanel<T>(string name) where T:BasePanel
    {
        if (panelDic.ContainsKey(name))
            return panelDic[name] as T;
        return null;
    }

    /// <summary>
    /// 给控件添加自定义事件监听
    /// </summary>
    /// <param name="control">控件对象</param>
    /// <param name="type">事件类型</param>
    /// <param name="callBack">事件的响应函数</param>
    public static void AddCustomEventListener(UIBehaviour control, EventTriggerType type, UnityAction<BaseEventData> callBack)
    {
        EventTrigger trigger = control.GetComponent<EventTrigger>();
        if (trigger == null)
            trigger = control.gameObject.AddComponent<EventTrigger>();

        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.eventID = type;
        entry.callback.AddListener(callBack);

        trigger.triggers.Add(entry);
    }

}

3.单例模式基类:

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 单例模式基类
/// </summary>
public class BaseManager<T> where T:new()
{
    private static T instance;
    public static T GetInstance()
    {
        if (instance == null)
            instance = new T();
        return instance;
    }
}

5.UGUI框架的使用--制作一个简易的提示管理器

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class TipMgr : BaseManager<TipMgr>
{
    public TipMgr()
    {
        
    }
    /// <summary>
    /// 用于提供给外界修改标签具体内容以及触发条件的方法
    /// </summary>
    /// <param name="ifShowChoose">是否存在选项</param>
    /// <param name="testContent">标签的显示信息</param>
    /// <param name="tipState">标签状态</param>
    public void ChangeTest(bool ifShowChoose, string testContent,TipState tipState)
    {
        ProtectHide("BigTip","TipPanel");
        UIManager.GetInstance().ShowPanel<TipPanel>("TipPanel",E_UI_Layer.System, (panel) =>
        {
            panel.ChangeTest(ifShowChoose,testContent,tipState);
        });
    }
    /// <summary>
    /// 提供给外界轻松触发气泡并且修改单条气泡内容的方法
    /// </summary>
    /// <param name="testContent">气泡内容</param>
    /// <param name="transPos">气泡触发位置</param>
    public void ChangeBubbleTest(string testContent, Transform transPos)
    {
        ProtectHide("TipPao","BubbleTip");
        UIManager.GetInstance().ShowPanel<BubbleTip>("BubbleTip",E_UI_Layer.Mid, (item) =>
        {
            item.ChangeBubble(testContent,transPos);
        });
    }
    /// <summary>
    /// 提供给外界轻松触发多条气泡内容修改的方法
    /// </summary>
    /// <param name="transPos"></param>
    /// <param name="testContent"></param>
    public void AddChangeBubbleTest( Transform transPos,params string[] testContent)
    {
        ProtectHide("TipPao","BubbleTip");
       
        UIManager.GetInstance().ShowPanel<BubbleTip>("BubbleTip",E_UI_Layer.Mid, (item) =>
        { 
            item.AddChangeBubble(transPos,testContent);
        });
    }
    /// <summary>
    /// 提供给外界用于修改提示内容的方法
    /// </summary>
    /// <param name="TipName"></param>
    public void ChangeTipPic(string TipName)
    {
        ProtectHide("TipPic","PicTipPanel");
        UIManager.GetInstance().ShowPanel<PicTipPanel>("PicTipPanel",E_UI_Layer.Mid, (panel) =>
        {
            panel.picName = TipName;
        });
    }
   
    public void ProtectHide(string panelTag,string panelName)
    {
        if(GameObject.FindGameObjectWithTag(panelTag))
            UIManager.GetInstance().HidePanel(panelName);
    }

}

(里面的名字是我随便起的,请不要介意,你可以自行修改,因为打小比赛几乎只有我个人写程序所以就随意起名了)

对于提示面板:

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;

public enum TipState
{
    None,//默认,无提示
    CompassInteraction,//罗盘交互提示
    SmallHoles,//小洞附近提示
    Clock,//钟表附近,找到齿轮
}
public class TipPanel : BasePanel
{
    public bool IsShowChoose = true;
    public TipState TipStates = TipState.None;
   
   /// <summary>
   /// 用于修改提示内容
   /// </summary>
   /// <param name="isShowChoose">是否存在提示选项</param>
   /// <param name="txtTip">修改提示内容</param>
   /// <param name="tipState">提示触发的状态</param>
    public void ChangeTest(bool isShowChoose, string txtTip,TipState tipState)
    {
        if (!isShowChoose)
        {
            GetControl<Button>("BtnYes").gameObject.SetActive(false);
            GetControl<Button>("BtnNo").gameObject.SetActive(false);
            IsShowChoose = false;
            Invoke("HideMe",5f);
        }
        GetControl<Text>("txtTip").text = txtTip;
        TipStates = tipState;
       
    }

    private void Start()
    {
        if (IsShowChoose)
        {
            //点击是
            GetControl<Button>("BtnYes").onClick.AddListener(() =>
            {
                switch (TipStates)
                {
                    case TipState.None:
                        break;
                    case TipState.CompassInteraction:
                        //播放献祭动画
                        break;
                }
                //隐藏自己
                UIManager.GetInstance().HidePanel("TipPanel");
            });
            //点击不
            GetControl<Button>("BtnNo").onClick.AddListener(() =>
            {
                switch (TipStates)
                {
                    case TipState.None:
                        break;
                    case TipState.CompassInteraction:
                        TipMgr.GetInstance().ChangeBubbleTest("我知道,你是我最正确的选择",PlayerController.GetInstance().transformPos.transform);
                        break;
                      
                }
                //隐藏自己
                UIManager.GetInstance().HidePanel("TipPanel");
            });
        }
      
    }
}

对于小气泡组件:

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;


/// <summary>
/// 人物对话气泡
/// </summary>
public class BubbleTip : BasePanel
{
    [SerializeField] public string[] content;
    [SerializeField]private int _num = 1;
    
     /// <summary>
    /// 提供给外界用于修改单个气泡内容的方法
    /// </summary>
    /// <param name="testBubble">气泡内容</param>
    /// <param name="bubbletransform">气泡位置</param>
    public void ChangeBubble(string testBubble,Transform bubbletransform)
    {
        transform.position = Camera.main.WorldToScreenPoint(bubbletransform.position);
        GetControl<Text>("txtBubble").text = testBubble;
        Invoke("HideMe",2);
    }
    /// <summary>
    /// 提供给外界用于修改多个气泡内容的方法
    /// </summary>
    /// <param name="bubbletransform">气泡出现的位置</param>
    /// <param name="testContent">多条内容</param>
    public void AddChangeBubble(Transform bubbletransform,params string[] testContent)
    {
        this.transform.position = Camera.main.WorldToScreenPoint(bubbletransform.position);
        content = testContent;
        GetControl<Text>("txtBubble").text = testContent[0];
        
        Invoke("InvokeP",2);
       
        Invoke("HideMe",(testContent.Length+1)*2);
    }

    public void InvokeP()
    {
        GetControl<Text>("txtBubble").text = content[_num ];
        _num += 1;
        if (_num<content.Length)
            Invoke("InvokeP",2);
    }
    public override void HideMe()
    {
        base.HideMe();
        _num = 0;
    }
}

以上使用了Json管理器,源码未提供。以上UI部分是比赛的项目源码所以夹杂一些东西。通过了多次测试,几乎没有问题,可以放心使用。气泡位置不是实时更新所以不会跟随,如果你有需要可以大致修改一下代码。代码主要介绍UGUI的框架使用,源码也不完整因为需求被砍了一大半。

以上就是UI按钮代码相关的常见代码了,喜欢就请点赞收藏。感谢!

相关推荐
指尖流烟1 分钟前
C#调用图表的使用方法
开发语言·c#
friklogff2 小时前
【无标题】云端之C#:全面解析6种云服务提供商的SDK
开发语言·flask·c#
c#上位机3 小时前
C#事件的用法
java·javascript·c#
chnyi6_ya3 小时前
一些写leetcode的笔记
笔记·leetcode·c#
IT规划师3 小时前
C#|.net core 基础 - 扩展数组添加删除性能最好的方法
c#·.netcore·数组
时光追逐者4 小时前
分享6个.NET开源的AI和LLM相关项目框架
人工智能·microsoft·ai·c#·.net·.netcore
小兮风4 小时前
RockTrack:A 3D Robust Multi-Camera-Ken Multi-Object Tracking Framework
3d
friklogff4 小时前
【C#生态园】提升C#开发效率:深入了解自然语言处理库与工具
开发语言·c#·区块链
仙魁XAN4 小时前
Unity 设计模式 之 创造型模式-【工厂方法模式】【抽象工厂模式】
unity·设计模式·工厂方法模式·抽象工厂模式
__water13 小时前
『功能项目』回调函数处理死亡【54】
c#·回调函数·unity引擎