有一天一个小伙伴跟我说,对于按钮相关网络某些教程并不全面,我大致看了,几乎差不多,接下来就大致补充一点代码相关的知识点了,还有我日常开发常用的一些按钮相关代码知识。
目录
(打码比较快,如果有小错误请指正,可能是误写,感谢!)
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 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
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按钮代码相关的常见代码了,喜欢就请点赞收藏。感谢!