一、铲子的组成
铲子包含很多部件组成,当拾取铲子的时候,只要点击铲子的任意一个部件就可以。
如图,点击【木柄】、【螺母】、【铁铲】都可以拾取该物体。
(1)打开高亮
(2)等待土铲被点击:任一部件被点击即可
(3)关闭高亮,取走土铲
二、实现的思路
用异步实现:等待任意一个部件被点击
- 1、whenAny的关键代码:等待任意一个子部件被点击
注意如何用select来包装一个任务列表
var allTasks = mamoty.GetComponentsInChildren<Transform>().Select(t => t.gameObject.OnClickAsync());
await UniTask.WhenAny(allTasks);
- 2、物体被点击的异步实现
(1)配合Collider碰撞体使用
(2)注意组件和委托的清理
/// <summary>/// 3D物体的异步点击方法/// </summary>/// <param name="gameObject"></param>/// <returns></returns>public static async UniTask OnClickAsync(this GameObject gameObject, EventTriggerType eventType = EventTriggerType.PointerClick){//碰撞体判断if (!gameObject.GetComponent<Collider>()) Debug.LogWarning($"{gameObject}建议加上相应形状的collider组件");//添加组件var hasEventTrigger = gameObject.GetComponent<EventTrigger>() != null;if (!hasEventTrigger) gameObject.AddComponent<EventTrigger>();bool triggered = false;//委托及实例方法Action myAction = null;Action fn = () =>{triggered = true;};//委托绑定myAction += fn;//事件触发gameObject.GetComponent<EventTrigger>().AddListener(eventType, (PointerEventData eventData) =>{if (myAction != null){myAction.Invoke();}});//等待事件触发await UniTask.WaitUntil(() => triggered == true);Debug.Log("");//取消绑定myAction -= fn;//资源清理:如果代码是并发执行,可能会把别人动态添加的eventTrigger销毁掉,所以建议不销毁//if (!hasEventTrigger) GameObject.DestroyImmediate(gameObject.GetComponent<EventTrigger>());return;}
三、土铲拾取的主要流程
//取土铲FlowGetMamoty = async () =>{//打开高亮if (mamoty.GetComponent<Highlighter>() == null) mamoty.AddComponent<Highlighter>();mamoty.GetComponent<Highlighter>().tween = true;//等待土铲被点击:任一部件被点击var allTasks = mamoty.GetComponentsInChildren<Transform>().Select(t => t.gameObject.OnClickAsync());await UniTask.WhenAny(allTasks);//关闭高亮,取走土铲 mamoty.GetComponent<Highlighter>().tween = false;await mamoty.DoMove(openedPos, closedPos, closeDuration);};