Unity 常用函数整理【一】

本文介绍了Unity开发中的一些高级技巧和实用函数,包括UGUI鼠标穿透检测、射线检测最近物体、场景跳转、自动滚动效果等,适合Unity开发者深入学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、unity 之UGUI 屏蔽鼠标(射线)穿透

方法一

  /// <summary>
  /// 检测是否点击在UI上
  /// </summary>
  /// <returns></returns>

  private bool IsClickUI()
  {
      if (EventSystem.current != null)
      {
          PointerEventData eventData = new PointerEventData(EventSystem.current);
          eventData.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
          List<RaycastResult> results = new List<RaycastResult>();
          EventSystem.current.RaycastAll(eventData, results);
          return results.Count > 0;
      }
      return false;
  }

方法二


        private void OnMouseDown()
        {
            // 如果点击的是 UI 元素,不执行后续逻辑
            if (IsPointerUI())
            {
                // 点击的是 UI 元素,不做处理
                return;
            }
            //下面执行对应点击逻辑
           
        }

        private bool IsPointerUI()
        {
            // 创建 pointerEventData
            PointerEventData pointerEventData = new PointerEventData(EventSystem.current)
            {
                position = Input.mousePosition // 获取鼠标位置
            };

            // 存储所有 UI 元素的射线结果
            var results = new List<RaycastResult>();

            // 检查与 UI 的交互
            EventSystem.current.RaycastAll(pointerEventData, results);
       
            // 如果有结果证明鼠标在 UI 上
            return results.Count > 0;
        }

方法三


    List<RaycastResult> RaycastResults = new List<RaycastResult>();
    private bool IsMouseUI(Vector3 mousePos)
    {
        var ray = Camera.main.ScreenPointToRay(mousePos);


        var ColliderDistance = float.MaxValue;

        Transform raycastTarget = null;
        if (Physics.Raycast(ray, out var raycastResult, 10000))
        {
            raycastTarget = raycastResult.transform;
            ColliderDistance = raycastResult.distance;
        }

        if (EventSystem.current != null)
        {
            PointerData.position = Input.mousePosition;

            if (RaycastResults.Count > 0)
                RaycastResults.Clear();

            EventSystem.current.RaycastAll(PointerData, RaycastResults);

            for (int i = 0; i < RaycastResults.Count; i++)
            {
                if (RaycastResults[i].distance < ColliderDistance)
                {
                    return true;
                }
            }
        }
        return false;
    }

2、射线交互多个物体  Physics.RaycastNonAlloc

    private RaycastHit[] Raycasts = new RaycastHit[10];

    private void RayObject()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        for (int i = 0; i < Raycasts.Length; i++)
        {
            Raycasts[i].distance = 999;
        };
        int count = Physics.RaycastNonAlloc(ray, Raycasts);
        if (count > 0)
        {
            //for (int i = 0; i < count; i++)
            //{
            //    var hit = Raycasts[i];
            //    OnRayClick(hit.transform);
            //}
            var hit = Raycasts[0];
            OnRayClick(hit.transform);
        }
    }

3、射线点击的最近物体

比较射线击中物体的距离并返回最近的物体,可以在使用 Physics.RaycastNonAlloc 方法后,遍历返回的 RaycastHit 数组,获取最小距离的物体。

方法一

using UnityEngine;  

public class RaycastNearestObject : MonoBehaviour  
{  
    private RaycastHit[] Raycasts = new RaycastHit[10]; // 可以调整数组大小以支持更多物体  

    void Update()  
    {  
        if (Input.GetMouseButtonDown(0)) // 监听鼠标左键点击  
        {  
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);  
            
            // 重置所有射线击中的距离到一个非常大的值  
            for (int i = 0; i < Raycasts.Length; i++)  
          
<think>好的,我现在需要帮助用户了解在Unity中如何使用和实现回调函数。首先,我得回忆下用户提供的引用内容,里面有提到StateMachineBehaviour、动画回调函数以及使用async/await来处理回调。用户可能对回调函数的概念不太熟悉,需要先解释清楚,再分情况说明不同的实现方法。 首先,回调函数是什么?简单来说,就是在某个事件发生时被调用的函数。在Unity中,常见的回调比如动画播放到某帧触发某个方法,或者异步操作完成后执行某些代码。根据引用内容,用户可能接触到的是动画回调和异步任务回调两种场景。 接下来,我需要整理实现回调的几种方式。第种是Unity内置的事件回调,比如Animator的事件绑定,这在引用1和2中提到过。这里可能需要举例说明如何在动画剪辑中添加事件,然后在脚本中定义对应的方法。第二种是使用委托和事件系统,这在C#中是基础,可以结合Unity的Event类来创建自定义事件。第三种是StateMachineBehaviour,这是针对动画状态机的回调接口,允许在状态进入、退出等时机执行代码,如引用1所述。第四种是使用async/await来简化异步回调,如引用3提到的,避免回调地狱,使代码更清晰。 然后,我需要考虑用户可能的疑问,比如不同方法的适用场景,或者具体实现的步骤。比如,动画事件适合在特定时间点触发动作,而委托和事件更适合自定义游戏逻辑的事件驱动。StateMachineBehaviour更适合在动画状态变化时处理逻辑,而async/await适合处理异步操作如资源加载。 在编写示例代码时,要注意语法正确,比如动画事件需要在Inspector中绑定,而使用委托时需要用UnityEvent或者C#的Action。StateMachineBehaviour需要继承自StateMachineBehaviour并重写相关方法。async/await的例子需要展示如何用异步方法替代传统回调。 最后,要确保回答结构清晰,分点说明每种方法,并附上代码示例。同时,根据用户的要求生成相关问题,可能涉及性能优化、不同回调方式的比较,或者具体应用场景的问题。</think>### Unity中回调函数的使用与实现方法 在Unity中,回调函数的核心作用是通过事件驱动机制实现代码逻辑的灵活控制。以下是四种常用实现方式及具体操作步骤: #### 1. 内置事件系统(动画事件) **实现步骤**: 1. 在动画剪辑时间轴右键添加事件标记 2. 绑定脚本方法: ```csharp public class AnimationCallback : MonoBehaviour { public void OnAnimationEvent(string message) { Debug.Log($"动画事件触发: {message}"); } } ``` 3. 在动画事件配置窗口选择对应方法 *适用场景*:精确控制动画关键帧逻辑,如攻击动作命中判定[^2] #### 2. 委托与UnityEvent **实现方案**: ```csharp // 自定义事件类 public class GameEvent : MonoBehaviour { public UnityEvent OnInteraction; void Update() { if(Input.GetKeyDown(KeyCode.E)) { OnInteraction.Invoke(); } } } // 监听类 public class DoorController : MonoBehaviour { void Start() { GetComponent<GameEvent>().OnInteraction.AddListener(OpenDoor); } void OpenDoor() { Debug.Log("门已开启"); } } ``` *优势*:实现组件间解耦,支持多对象监听[^3] #### 3. StateMachineBehaviour状态机回调 **动画状态机专用接口**: ```csharp public class CustomStateBehaviour : StateMachineBehaviour { override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { Debug.Log("进入动画状态"); } override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { Debug.Log("退出动画状态"); } } ``` *应用场景*:角色动画状态切换时播放音效/特效[^1] #### 4. 异步编程模式(async/await) **现代回调处理方式**: ```csharp async void LoadResourcesAsync() { var request = Resources.LoadAsync<Texture>("Textures/Background"); await request; if(request.isDone) { GetComponent<Renderer>().material.mainTexture = request.asset as Texture; Debug.Log("资源加载完成"); } } ``` *优势*:避免回调嵌套,提升代码可读性[^3] ### 技术选型建议 | 方法类型 | 适用场景 | 执行精度 | 复杂度 | |---------|---------|---------|--------| | 动画事件 | 帧级别控制 | 0.1秒级 | ★☆☆☆ | | UnityEvent | 游戏逻辑交互 | 事件驱动 | ★★☆☆ | | 状态机回调 | 动画状态管理 | 状态切换时 | ★★★☆ | | async/await | 异步资源加载 | 任务完成时 | ★★☆☆ | 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值