美文网首页
Unity中,2D扇形区域的范围检测和显示

Unity中,2D扇形区域的范围检测和显示

作者: 全新的饭 | 来源:发表于2023-10-29 11:20 被阅读0次

说明

具体需实现

  1. 显示扇形区域
  2. 检测目标点是否在该区域内

使用示意

用SectorArea表示扇形,用SectorAreaView来显示。


扇形区域.gif

实现

核心

显示:创建扇形Sprite,设置为spriteRenderer的sprite

    public void CreateSprite(float radius, float angle, Color color)
    {
        var size = (int)(radius * 2 * 100);
        var actualRadius = size / 2;
        var halfAngle = angle / 2;
        Texture2D texture2D = new Texture2D(size, size);
        Vector2 centerPixel = Vector2.one * size / 2;

        // 绘制
        var emptyColor = Color.clear;
        Vector2 tempPixel;
        float tempAngle;
        float tempDisSqr;
        for (int x = 0; x < size; x++)
        {
            for (int y = 0; y < size; y++)
            {
                tempPixel.x = x - centerPixel.x;
                tempPixel.y = y - centerPixel.y;

                tempDisSqr = tempPixel.sqrMagnitude;
                if (tempDisSqr <= actualRadius * actualRadius)
                {
                    tempAngle = Vector2.Angle(Vector2.right, tempPixel);
                    if (tempAngle < halfAngle || tempAngle > 360 - halfAngle)
                    {
                        //设置像素色值
                        texture2D.SetPixel(x, y, color);
                        continue;
                    }
                }
                texture2D.SetPixel(x, y, emptyColor);
            }
        }

        texture2D.Apply();
        _renderer.sprite = Sprite.Create(texture2D, new Rect(0, 0, size, size), Vector2.one * 0.5f);
    }

检测目标点是否在扇形区域内

    public bool IsInArea(Vector2 pos)
    {
        var ret = false;
        if (Vector2.Distance(CenterPos, pos) < _radius)
        {
            var halfAngle = _angles / 2;
            var dir = (pos - CenterPos).normalized;
            var curAngle = Vector2.Angle(Dir, dir);
            if (curAngle < halfAngle || curAngle > 360 - halfAngle)
            {
                ret = true;
            }
        }
        return ret;
    }

    // 在范围内是否能找到指定层的对象
    public bool CanFindTarget(LayerMask targetLayer, out Transform target)
    {
        var ret = CanFindTargets(targetLayer, out Transform[] targets);
        target = ret ? targets[0] : null;
        return ret;
    }
    public bool CanFindTargets(LayerMask targetLayer, out Transform[] targets)
    {
        var ret = false;
        var targetList = new List<Transform>();
        var cols = Physics2D.OverlapCircleAll(CenterPos, _radius, targetLayer);
        if (cols != null)
        {
            foreach (var col in cols)
            {
                Vector2 pos = col.transform.position;
                if (IsInArea(pos))
                {
                    targetList.Add(col.transform);
                }
            }
        }

        ret = targetList.Count > 0;
        targets = targetList.ToArray();

        return ret;
    }

完整代码

SectorArea.cs

using System.Collections.Generic;
using UnityEngine;
public class SectorArea : MonoBehaviour
{
    [SerializeField]
    private Transform _centerTrans;
    public Vector2 CenterPos { get { return _centerTrans.position; } }
    [SerializeField]
    private Transform _dirTrans;
    public Vector2 Dir { get { return _dirTrans.right; } }
    [SerializeField, Range(1, 359)]
    private float _angles;
    [SerializeField, Range(0.1f, 15)]
    private float _radius;

    [SerializeField]
    private SectorAreaView _view;
    [SerializeField]
    private Color _viewColor = Color.red;

    public void Init()
    {
        RefreshView();
    }
    public void MyDestroy()
    {

    }

    public bool IsInArea(Vector2 pos)
    {
        var ret = false;
        if (Vector2.Distance(CenterPos, pos) < _radius)
        {
            var halfAngle = _angles / 2;
            var dir = (pos - CenterPos).normalized;
            var curAngle = Vector2.Angle(Dir, dir);
            if (curAngle < halfAngle || curAngle > 360 - halfAngle)
            {
                ret = true;
            }
        }
        return ret;
    }

    // 在范围内是否能找到指定层的对象
    public bool CanFindTarget(LayerMask targetLayer, out Transform target)
    {
        var ret = CanFindTargets(targetLayer, out Transform[] targets);
        target = ret ? targets[0] : null;
        return ret;
    }
    public bool CanFindTargets(LayerMask targetLayer, out Transform[] targets)
    {
        var ret = false;
        var targetList = new List<Transform>();
        var cols = Physics2D.OverlapCircleAll(CenterPos, _radius, targetLayer);
        if (cols != null)
        {
            foreach (var col in cols)
            {
                Vector2 pos = col.transform.position;
                if (IsInArea(pos))
                {
                    targetList.Add(col.transform);
                }
            }
        }

        ret = targetList.Count > 0;
        targets = targetList.ToArray();

        return ret;
    }


    [ContextMenu("刷新扇形面积的展示")]
    private void RefreshView()
    {
        _view.CreateSprite(_radius, _angles, _viewColor);
    }
}

SectorAreaView.cs

using UnityEngine;

public class SectorAreaView : MonoBehaviour
{
    [SerializeField]
    private SpriteRenderer _renderer;
    public void CreateSprite(float radius, float angle, Color color)
    {
        var size = (int)(radius * 2 * 100);
        var actualRadius = size / 2;
        var halfAngle = angle / 2;
        Texture2D texture2D = new Texture2D(size, size);
        Vector2 centerPixel = Vector2.one * size / 2;

        // 绘制
        var emptyColor = Color.clear;
        Vector2 tempPixel;
        float tempAngle;
        float tempDisSqr;
        for (int x = 0; x < size; x++)
        {
            for (int y = 0; y < size; y++)
            {
                tempPixel.x = x - centerPixel.x;
                tempPixel.y = y - centerPixel.y;

                tempDisSqr = tempPixel.sqrMagnitude;
                if (tempDisSqr <= actualRadius * actualRadius)
                {
                    tempAngle = Vector2.Angle(Vector2.right, tempPixel);
                    if (tempAngle < halfAngle || tempAngle > 360 - halfAngle)
                    {
                        //设置像素色值
                        texture2D.SetPixel(x, y, color);
                        continue;
                    }
                }
                texture2D.SetPixel(x, y, emptyColor);
            }
        }

        texture2D.Apply();
        _renderer.sprite = Sprite.Create(texture2D, new Rect(0, 0, size, size), Vector2.one * 0.5f);
    }
}

相关文章

  • 【Unity技巧】调整贴图质量

    Babybus-u3d技术交流-【Unity技巧】调整贴图质量 写在前面当我们在Unity中,使用图片进行2D显示...

  • Android百度地图画扇形

    先上图: 首先我们只单说画扇形的需求需求:把最佳123位置点显示在扇形区域内,(这里分两种情况:1扇形不跟随移动,...

  • Unity3D 调整画质及贴图质量 (转)

    当我们在Unity中,使用图片进行2D显示时,会发现显示出来的画面有明显的模糊或者锯齿,但是美术给的原图却十分清晰...

  • [Unity优化] 调整画质(贴图)质量

    当我们在Unity中,使用图片进行2D显示时,会发现显示出来的画面有明显的模糊或者锯齿,但是美术给的原图却十分清晰...

  • [Unity插件] 2D Toolkit

    2D Toolkit插件在2D中的地位,犹如UI中NGUI对Unity GUI一样:虽然官方原生的2D还不错,但这...

  • Unity 2D Animation——1.骨骼绑定

    1. Unity 2D Animation 的安装 Unity 2D Animation是作为插件包安装到unit...

  • Unity笔记

    Unity3D 官方文档 2D游戏的起始2 2D物理 全局设置与刚体 Unity5.6 2D物理引擎Effecto...

  • 配色

    同母异父:扇形区域 同父异母:环形区域

  • 乌鲁木齐市环境检测公司优秀企业推荐

    环境检测是利用GIS技术对环境检测网络进行设计,环境检测收集的信息又能通过GIS适时储存和显示,并对所选评价区域进...

  • 简单实现扇形图表

    Demo地址 主要代码 1、遍历所有扇形的比例,计算出每个扇形区域的开始和结束角度,然后绘制FanShapeLay...

网友评论

      本文标题:Unity中,2D扇形区域的范围检测和显示

      本文链接:https://www.haomeiwen.com/subject/zfhvidtx.html