一、铲子的组成
铲子包含很多部件组成,当拾取铲子的时候,只要点击铲子的任意一个部件就可以。
如图,点击【木柄】、【螺母】、【铁铲】都可以拾取该物体。
(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);
};