目录
关于事件的一些零碎知识
- 在Unity中如按钮和Toggle等UI组件,事件中添加的方法会含有一些参数,这些参数在点击时会传递到事件所绑定的方法中作为形参。
// 不使用匿名函数的写法: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; public class UITest : MonoBehaviour { public Toggle toggle; UnityAction<bool> action; private void Start() { action += work; toggle.onValueChanged.AddListener(action); } void work(bool para) { Debug.LogFormat("toggle = {0} selected = {1}", toggle.name, para); } } // 使用匿名函数写法: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; public class UITest : MonoBehaviour { public Toggle toggle; private void Start() { toggle.onValueChanged.AddListener((selected) => { Debug.LogFormat("toggle = {0} selected = {1}", toggle.name, selected); }); } }
- 自定义UI及3D物体等的事件管理。
// 当某个物体需要监听事件时, // 添加该脚本。 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { private void Awake() { // 获取物体EventListener组件中的UnityAction, // 并添加需要监听的方法。 EventListener.Get(gameObject).onClick = Work; } // 函数需要符合UnityAction格式,这里就是UnityAction<GameObject>格式 // GameObject类型参数。 // 被监听的方法,可以自定义。 void Work(GameObject go) { if(go == gameObject) { Debug.Log($"{gameObject.name}被点击"); } } } // 工具代码,用于辅助上面的脚本。 // 这个可以另外创建一个脚本,存放下面代码。 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; public class EventListener : EventTrigger { public UnityAction<GameObject> onClick; // 重写父类的方法,当UnityAction<GameObject>不为空时, // 进行调用其中的回调函数。 public override void OnPointerClick(PointerEventData eventData) { base.OnPointerClick(eventData); if(onClick != null) { onClick(gameObject); } } // 返回go物体的EventListener组件引用,如果没有,就给go物体添加一个 static public EventListener Get(GameObject go) { EventListener listener = go.GetComponent<EventListener>(); if(listener == null) { listener = go.AddComponent<EventListener>(); } return listener; } }
UI组件小知识
- 当Image的Anchors选择为全屏拉伸时,由于game界面的拉伸缩放,就会影响到Image的显示,通过添加Aspect Ratio Fitter组件,可以大程度解决问题。下面是Aspect Mode:
- Width Controls Height:通过宽度来控制高度。
- Height Controls Width:通过高度来控制宽度。
- Fit In Parent:始终保持在屏幕上。它会在宽度失去比例后缩小贴图,始终保持贴图全部显示出现在屏幕上,代价就是两侧可能会漏出黑边。
- Envelope Parent:通过裁剪方式保证两侧不漏出黑边,但是会裁剪额外的贴图信息。
- 配置URP渲染管线下的UI摄像机。
- 在Unity中,Windows->PackageManager中下载Universal RP资源包。
- 在Unity中,Project面板下右键Create->Rendering->URP Asset,创建URP配置文件。
- Edit->Project Settings->Graphics中,在Scriptable Render Pipeline Settings中选择配置的URP配置文件。
- 在Hierarchy面板中创建Camera,将UICamera的Culling Mask选择为UI,表示这个摄像机只看UI层,Render Type选择为Overlay表示它需要叠在一个Base(基础)摄像机上。
- 将MainCamera的Calling Mask设置为除UI层均可见,并且Render Type设置为Base,将UICamera添加到MainCamera的Stack中。
- 再将Canvas组件的Render Mode设置为Screen Space-Camera表示使用屏幕空间的摄像机,在Render Camera中拖入刚创建的UI摄像机即可。
- 在全局添加一个含有EventSystem组件的对象,运行后,就可以在面板中查看详细信息。便于调试。
UnityAction和UnityEvent
- UnityAction是Unity自己实现的事件传递系统,就像C#里的委托和事件一样,它属于函数指针,可以把方法传递到另一个类中去执行。
- UnityEvent则负责管理UnityAction,它提供了AddListener()、RemoveListener()和RemoveAllListeners()方法。
- UnityAction只能调用自己,但是UnityEvent可以同时调用多个UnityAction。
-
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; // 创建带两个参数(int,string)的事件类型 public class MyEvent : UnityEvent<int, string> { } public class Test : MonoBehaviour { public UnityAction<int, string> action; // 相当于创建函数指针,理解为委托也行 public MyEvent myEvent = new MyEvent(); public void RunMyEvent(int a, string b) { Debug.LogFormat($"RunMyEvent{0}, {1}", a, b); } private void Start() { // 可以使用+= // 添加需要执行的方法 action = RunMyEvent; // myEvent事件监听action myEvent.AddListener(action); } private void Update() { if (Input.GetKeyDown(KeyCode.A)) { // 调用这个UnityAction中添加的方法 action.Invoke(0, "按下A键"); } if (Input.GetKeyDown(KeyCode.B)) { // 会调用myEvent中监听的所有UnityAction myEvent.Invoke(100, "按下B键"); } } }