U3D游戏开发按钮相关

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

目录

1.UGUI的普通按钮相关

2.UGUI的异型按钮相关

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

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

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


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

1.UGUI的普通按钮相关

代码控制相关的按钮参数

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

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

public void ClickBtn()
{
//中间写上按钮逻辑
}

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

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

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

2.拖拽

//以下代码在Start函数之中写入
btn.onClick.AddListener(ClickBtn);//以下写入按钮逻辑
private void ClickBtn()
{
//写入按钮点击逻辑
}

3.代码识别

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

GameObject.Find("btnClose");

其他的如上图所示。

4.按钮代码移出委托

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脚本,添加碰撞器。

代码获取对象

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

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

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

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 updateprotected 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 framepublic 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]);elsecontrolDic.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

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.单例模式基类:

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框架的使用--制作一个简易的提示管理器

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);}}

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

对于提示面板:

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");});}}
}

对于小气泡组件:

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按钮代码相关的常见代码了,喜欢就请点赞收藏。感谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/832407.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT的真实能力如何?七大NLP任务一探究竟!

文章链接&#xff1a;https://arxiv.org/pdf/2405.00704 ChatGPT已经改变了人工智能社区&#xff0c;一个活跃的研究方向是ChatGPT的性能评估。评估的一个关键挑战是ChatGPT仍然是闭源的&#xff0c;传统的基准数据集可能已被ChatGPT用作训练数据。在本文中: 调查了最近的研究…

MySQL-基础篇

MySQL基础篇 MySQL概述 MySQL安装与启动 配置MySQL环境变量 MySQL数据库 SQL DDL 数据库操作 表操作 表操作-修改 注意&#xff1a;在删除表时&#xff0c;表中的全部数据也会被删除。 datagrip DML DQL DQL-基本查询 在实际开发过程中&#xff0c;尽量不要写se…

利用matplotlib和networkx绘制有向图[显示边的权重]

使用Python中的matplotlib和networkx库来绘制一个有向图&#xff0c;并显示边的权重标签。 1. 定义了节点和边&#xff1a;节点是一个包含5个节点的列表&#xff0c;边是一个包含各个边以及它们的权重的列表。 2. 创建了一个有向图对象 G。 3. 向图中添加节点和边。 4. 设置了…

vue3中标签的ref属性

组合API-ref属性 在vue2.x中&#xff0c;可以通过给元素添加refxxx属性&#xff0c;然后在代码中通过this.$refs.xxx获取到对应的元素 然而在vue3中时没有$refs这个东西的&#xff0c;因此vue3中通过ref属性获取元素就不能按照vue2的方式来获取。 目标&#xff1a;掌握使用re…

ModuleNotFoundError: No module named ‘pkg_resources‘ 问题如何解决?

ModuleNotFoundError: No module named pkg_resources 通常是因为 Python 环境中缺少 setuptools 模块。pkg_resources 是 setuptools 包的一部分&#xff0c;用于处理 Python 包的发行和资源。 为解决这个问题&#xff0c;请按照以下步骤操作&#xff1a; 确保 setuptools 已…

压缩png图片大小怎么操作?试试这招一键压缩图片体积

png图片是一种无损压缩格式&#xff0c;体积也会比其他格式的图片要大。但是&#xff0c;我们在使用的过程中遇到需要给png图片压缩体积的情况时要怎么办呢&#xff1f;很简单&#xff0c;只需要使用png压缩大小&#xff08;https://www.yasuotu.com/png&#xff09;网站-压缩图…

UE5 体积云

写好的体积材质放这里面 效果如上 Begin Object Class/Script/UnrealEd.MaterialGraphNode Name"MaterialGraphNode_4"Begin Object Class/Script/Engine.MaterialExpressionVectorParameter Name"MaterialExpressionVectorParameter_0"End ObjectBegin O…

欢乐钓鱼大师脚本,游戏托管一键操作!

欢迎来到《钓鱼大师乐趣无穷》&#xff01;这里是一片充满了乐趣和挑战的钓鱼天地。不论你是刚刚入门的小白&#xff0c;还是已经成为老手的大神&#xff0c;本攻略将为你揭示如何在游戏中获得成功&#xff0c;并针对稀有鱼类的钓鱼技巧进行详细介绍。 一、初探钓鱼的乐趣 在《…

低功耗UPF设计的经典案列分享

案例1 分享个例子&#xff0c;景芯A72低功耗设计&#xff0c;DBG domain的isolation为何用VDDS_maia_noncpu供电而不是TOP的VDD&#xff1f; 答&#xff1a;因为dbg的上一级是noncpu&#xff0c;noncpu下面分成dbg和两个tbnk。 案例2 景芯A72的低功耗&#xff0c;请问&#…

RabbitMQ是怎么做消息分发的?——Java全栈知识(14)

RabbitMQ是怎么做消息分发的&#xff1f; RabbitMQ 的消息分发分为五种模式&#xff1a;分别是简单模式、工作队列模式、发布订阅模式、路由模式、主题模式。 1、简单模式 publisher 直接发送消息到队列消费者监听并处理队列中的消息 简单模式是最基本的工作模式&#xff0c;…

数据仓库基础理论(学习笔记)

数据仓库基础理论 1.数据仓库概念 2.数据仓库为何而来 3.数据仓库主要特征 4.OLTP、OLAP系统 5.数据仓库与数据库的区别 6.数据仓库与数据集市的区别 7.数据仓库分层架构 7.1为什么要分层&#xff1f; 8.ETL、ELT

爱普生S2D13V52快速实现车载显示屏高分辨率显示系统

随着时代的发展&#xff0c;汽车驾驶位前中央的显示屏承担的功能也越来越多&#xff0c;从一开始仅仅是显示仪表盘的信息&#xff0c;再到作为显示屏辅助倒车&#xff0c;再到如今和一块平板一样可公认娱乐&#xff0c;显示屏的大小有些时候成为了一辆车够不够好的体现。随着汽…

【网络安全】记一场完整实战SRC漏洞挖掘(超详细)全过程

前言 记录一次完整的某SRC漏洞挖掘实战&#xff0c;为期一个多星期。文章有点长&#xff0c;请耐心看完&#xff0c;记录了完整的SRC漏洞挖掘实战 渗透过程 因为选择的幸运儿没有对测试范围进行规划&#xff0c;所以此次范围就是没有范围。 先上主域名看一眼&#xff0c;看…

Error: error:0308010C:digital envelope routines::unsupported 问题如何解决

Error: error:0308010C:digital envelope routines::unsupported 通常与 Node.js 的加密库中对某些加密算法的支持有关。这个错误可能是因为 Node.js 的版本与某些依赖库不兼容导致的。特别是在 Node.js 17 版本中&#xff0c;默认使用 OpenSSL 3&#xff0c;而一些旧的加密方式…

银行卡实名认证API接口快速对接

银行卡实名认证API接口又叫银行卡核验类API接口、银行卡验证类API接口、银联核验类API接口,根据入参字段不同&#xff0c;分银行卡二要素验证API接口&#xff0c;银行卡三要素验证API接口&#xff0c;银行卡四要素验证API接口。其中&#xff0c;银行卡二要素验证API接口是验证开…

BEV下统一的多传感器融合框架 - FUTR3D

BEV下统一的多传感器融合框架 - FUTR3D 引言 在自动驾驶汽车或者移动机器人上&#xff0c;通常会配备许多种传感器&#xff0c;比如&#xff1a;光学相机、激光雷达、毫米波雷达等。由于不同传感器的数据形式不同&#xff0c;如RGB图像&#xff0c;点云等&#xff0c;不同模态…

TypeError报错处理

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、Python中的TypeError简介 这个错误通常表示在方法调用时&#xff0c;参数类型不正确&#xff0c;或者在对字符串进行格式化操作时&#xff0c;提供的变量与预期不符。 二、错误的源头&#xff1a;字符串格式化…

动力电池热管理方案介绍与发展方向

摘要 随着电动汽车的快速发展&#xff0c;高性能的动力电池系统成为推动电动汽车产业发展的重要因素。然而&#xff0c;伴随着能量密度提高和放电深度增加&#xff0c;电池热管理问题逐渐凸显。良好的热管理方案能够提高电池的寿命&#xff0c;保障电池性能&#xff0c;延长电…

【C语言刷题系列】移除元素

目录 一、问题描述 二、解题思路 三、源代码 个人主页&#xff1a; 倔强的石头的博客 系列专栏 &#xff1a;C语言指南 C语言刷题系列 一、问题描述 二、解题思路 在C语言中&#xff0c;原地移除数组中所有等于特定值的元素并返回新长度的问题可以通过双指针法…

Linux:进程信号(一)信号的产生

目录 一、信号是什么&#xff1f; 二、Linux信号 三、信号处理方式 四、信号的产生 1、 通过终端按键产生信号 2、调用系统函数向进程发信号 3、 硬件异常产生信号 一、信号是什么&#xff1f; 在生活中&#xff0c;有许多信号&#xff0c;比如红绿灯&#xff0c;下课铃声…