说明
具体需实现
- 显示扇形区域
- 检测目标点是否在该区域内
使用示意
用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);
}
}
网友评论