Unity 常用函数整理【一】

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;
        }

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++)  
            {  
                Raycasts[i].distance = float.MaxValue; // 或用999  
            }  

            // 使用射线投射获取击中的物体  
            int count = Physics.RaycastNonAlloc(ray, Raycasts);  

            // 找到最近的物体  
            RaycastHit nearestHit = new RaycastHit();  
            float closestDistance = float.MaxValue;  

            for (int i = 0; i < count; i++)  
            {  
                if (Raycasts[i].distance < closestDistance)  
                {  
                    closestDistance = Raycasts[i].distance;  
                    nearestHit = Raycasts[i]; // 更新最近的击中信息  
                }  
            }  

            if (closestDistance < float.MaxValue) // 如果找到有效的击中  
            {  
                Debug.Log("最近的物体: " + nearestHit.collider.gameObject.name);  
                // 你可以在这里对最近的物体执行其它逻辑  
            }  
            else  
            {  
                Debug.Log("没有击中任何物体");  
            }  
        }  
    }  
}

方法二

private static int CompareDistance(RaycastHit r1, RaycastHit r2)  
{  
    // 获取 r1 和 r2 的 Collider 组件  
    var r1Collider = r1.transform != null ? r1.transform.GetComponent<Collider>() : null;  
    var r2Collider = r2.transform != null ? r2.transform.GetComponent<Collider>() : null;  

    // 检查 r1 是否有 Collider,而 r2 没有  
    if (r1Collider != null && r2Collider == null)  
    {  
        return -1; // r1 优先  
    }  
    // 检查 r2 是否有 Collider,而 r1 没有  
    else if (r1Collider == null && r2Collider != null)  
    {  
        return 1; // r2 优先  
    }  

    // 如果两个都有 Collider,或者都没有,比较距离  
    return r1.distance.CompareTo(r2.distance);  
}

4、跳转场景


    private bool isLoading = false;
    IEnumerator GotoScene(string sceneName)
    {
        if (isLoading) yield break;

        isLoading = true;

        yield return null;

        var asyncOp = SceneManager.LoadSceneAsync(sceneName);
        asyncOp.allowSceneActivation = false;

        while (!asyncOp.isDone)
        {
            if (!asyncOp.allowSceneActivation && asyncOp.progress >= 0.9f)
            {
                asyncOp.allowSceneActivation = true;
                break;
            }

            yield return null;
        }

        isLoading = false;
    }

5、RectTransformUtility.RectangleContainsScreenPoint的应用

RectTransform.RectangleContainsScreenPoint 方法顾名思义,判断矩阵范围是否包含屏幕点,参数:位置矩阵、屏幕点、使用的Camera 三个。

if(RectTransformUtility.RectangleContainsScreenPoint(transform.GetComponent<RectTransform>(),Input.mousePosition, Cameras.UI))
{    
     Debug.Log("在遮挡范围内");
}

两个参数:

RectTransformUtility.RectangleContainsScreenPoint(rect,position,camera)

判断第二个参数代表的位置是否在第一个参数rect的范围内,

注意:两个参数的只能在Canvas为Screen Space -Overlay时的情况用,三个参数的重载是正确用法。(Canvas为Screen Space -Camera)


    IEnumerator Check()
    {
        yield return null;
        //判断第二个参数代表的位置是否在第一个参数rect的范围内,
        var inRect = RectTransformUtility.RectangleContainsScreenPoint(DetailRect, Input.mousePosition);

        if (!inRect)
            CloseDetail();
    }

6、模拟打气球效果

使用SkinnedMeshRenderer.SetBlendShapeWeight设置此渲染器的 BlendShape 的权重。

int[] val = new int[] { 0, 50, 70, 80, 90, 95, 100 };
int currentNum = 0;



int Progress = val[currentNum];
int EndValue = val[currentNum + 1];
if (DOTween.IsTweening(Progress))
{
    DOTween.Kill(Progress);
}
Tweener tweener = DOTween.To(() => Progress, x => Progress = x, EndValue, 0.5f).OnUpdate(() =>
{
    balloonCQ.GetComponent<SkinnedMeshRenderer>().SetBlendShapeWeight(0, Progress);
});
currentNum++;

注意:需要动画设计师制作带有blendShapes控制的气球模型

7、代码控制相机打开后处理

 if(Camera.main != null)
 {
     var cameraData = Camera.main.GetUniversalAdditionalCameraData();

     if (cameraData != null)
         cameraData.renderPostProcessing = true; // 启用后处理
 }

8、Scroll View 自动滚动效果



    public void OpenEndPanel(string content, AudioClip clip = null, Action callback = null)
    {
        EndPanel.GetChild(0).DOKill();
        EndPanel.gameObject.SetActive(true);
        AudioSource source = EndPanel.GetComponent<AudioSource>();

        //先重置 ScrollRect 的位置
        EndPanelScroll.verticalNormalizedPosition = 1f; // 默认为顶部

        // 初始位置
        EndPanelContent.DOAnchorPos3DY(0, 0).SetDelay(0.1f);// 延迟动画

        // 设置内容文本
        EndPanelTxt.text = "\u3000\u3000" + content + "。";

        // 确保在位置重置后再创建动画
        EndPanel.GetChild(0).DOScale(Vector3.one, 0.5f).OnComplete(() =>
        {
            if (clip)
            {
                source.Stop();
                source.clip = clip;
                source.Play();
            }
            callback?.Invoke();
            //确保 Scroll 视图在动画调用前完成处理
            AutoScrollView(EndPanelScroll, clip);
        });

        Invoke("CalEndPanel", 0.1f);
    }

    /// <summary>
    /// 根据音频长度自动滚动视图
    /// </summary>
    /// <param name="clip"></param>
    private void AutoScrollView(ScrollRect scrollRect, AudioClip clip)
    {
        var duration = clip != null ? clip.length : 3f;
        CommonFunc.Delay(0.1f, delegate
        {
            scrollRect.DOKill();
            scrollRect.verticalNormalizedPosition = 1f;
            scrollRect.DONormalizedPos(Vector2.zero, duration).SetEase(Ease.Linear);
        }, this);
    }

    private void CalEndPanel()
    {
        EndPanelContent.sizeDelta = new Vector2(550, EndPanelTxt.GetComponent<RectTransform>().sizeDelta.y);
        EndPanelScroll.vertical = EndPanelContent.sizeDelta.y > 230;
    }

    public void CloseEndPanel()
    {
        EndPanel.GetChild(0).DOKill();
        EndPanel.GetChild(0).DOScale(Vector3.zero, 0.5f).OnComplete(() =>
        {
            EndPanel.gameObject.SetActive(false);
            EndPanelTxt.text = "";
        });

        // 重置 ScrollRect 的位置到顶部
        EndPanelScroll.DOKill();
        EndPanelScroll.verticalNormalizedPosition = 1f; // 滚动条置顶
        EndPanelContent.anchoredPosition = new Vector2(0, 0); // 也可以直接设置锚点位置

        AudioSource source = EndPanel.GetComponent<AudioSource>();
        source.Stop();
        source.clip = null;
    }

9、unity中设置鼠标状态


        /// <summary>
        /// 设置鼠标状态
        /// </summary>
        /// <param name="_cursorState">状态:true显示,false隐藏</param>
        public void SetCursor(bool _cursorState)
        {
            //隐藏鼠标
            Cursor.visible = _cursorState;
            Cursor.lockState = _cursorState ? CursorLockMode.Confined : CursorLockMode.Locked;
        }

10、unity编辑器模式下运行(按下Play键)后的启动指定场景, 启动场景需要添加到BuildSetting中

/// <summary>
/// c
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
    if (SceneManager.GetActiveScene().path.StartsWith("Assets/Scenes/"))
    {
        SceneManager.LoadScene("Main");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值