unity中一种实现大量目标(1万个以上)图标跟随的解决方案

需求:

在使用Unity进行Gis开发时,希望一些目标以图标的形式显示,显示效果和UI图标跟随一致,并且当目标移动时,图标也需要继续跟随。

解决方案1:

以UI跟随的方式进行开发。将目标的三维空间坐标转为屏幕坐标赋值给UI。

这种方案效果满足,但是因为UI图标的贴图不一致,导致无法触发合批,一旦UI数量一多,就会极大的影响性能。最终,该方案不可行。

解决方案2:

使用Mesh代替UI图标,采用GPUInstance来生成图标,使用Job进行图标位置计算,开发脚本,将Mesh图标放置到相机裁面中。最终完美解决。

即有了和UI相同的效果显示,又有了高性能。

效果截图如下:

红色为UI图标,彩色为mesh图标。

核心脚本:

using System;
using UnityEngine;

public class MeshCanvas : MonoBehaviour
{
    /// <summary>
    /// 计算逻辑
    /// canvas scale基于高度变化进行计算
    /// base = 1.15936f 
    /// 公式:scale = base/(screen height/100)*(canvas distance/100)
    /// </summary>
    public static float CanvasScale = 1.0f;

    /// <summary>
    /// 当分辨率变换时,触发的回调
    /// </summary>
    public static Action onMeshCanvasChanged;

    /// <summary>
    /// 固定缩放常数
    /// </summary>
    public static float BaseScale = 1.15936f;
    public static float UIDistance = 100.0f;

    public float StartUIDistance = 100;


    private void Start()
    {
        onMeshCanvasChanged += OnMeshCanvasChanged;
    }

  
    private void Update()
    {
        //实时计算
        float _caS = BaseScale / (Screen.height / 100.0f) * (UIDistance / 100.0f) ;
        if(_caS != CanvasScale)
        {
            CanvasScale = _caS;
            onMeshCanvasChanged?.Invoke();
        }
        UIDistance = StartUIDistance;
    }

    /// <summary>
    /// 获取Mesh UI元素在此Canvas下的缩放比例
    /// </summary>
    /// <param name="uiWidth"></param>
    /// <param name="uiHeight"></param>
    /// <returns></returns>
    public static Vector3 GetUIItemScaleV3(float uiWidth,float uiHeight)
    {
        return new Vector3(uiWidth * CanvasScale/(CanvasScale * Screen.width)*(Screen.height/1080.0f), uiHeight * CanvasScale/(CanvasScale * Screen.height) * (Screen.height / 1080.0f), 1) ;
    }

    /// <summary>
    /// 传入计算后的屏幕坐标,返回对象在此Canvas下的坐标
    /// UI坐标和Canvas下的坐标都是采用锚点在左下角的规则进行计算,如果锚点在其他地方,需要自己更改计算方式
    /// </summary>
    /// <param name="screenPos"></param>
    /// <returns></returns>
    public static Vector3 GetUIItemPosV3(Vector2 screenPos)
    {
        return  new Vector3((screenPos.x * (Screen.height / 1080.0f) / Screen.width - 0.5f), (screenPos.y * (Screen.height / 1080.0f) / Screen.height - 0.5f), 0);
    }



    private void OnMeshCanvasChanged()
    {
        transform.localScale = new Vector3(CanvasScale * Screen.width, CanvasScale * Screen.height, 1);
        transform.localPosition = new Vector3(0, 0, UIDistance);
    }

    private void OnDestroy()
    {
        onMeshCanvasChanged -= OnMeshCanvasChanged;
    }





}

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值