greyhh

记录学习中的点点滴滴
随笔 - 37, 文章 - 0, 评论 - 2, 阅读 - 76024

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

线性规划解决图片内不规则多边形的碰撞体问题

Posted on   greyhh  阅读(1031)  评论(0编辑  收藏  举报

首先,我们先来看一个问题,如下图演示

 

当鼠标点击图片里正六边形内某个点时,我们需要取到该点的颜色值并进行一些操作。而点击正六边形外的透明区域时,我们不需要对该区域进行取值,但是Unity没有正六边形碰撞体,用其他碰撞体代替总会有一些问题。

于是,我首先想到了用多个小碰撞体来拼接一下,好了,问题完美解决了。

不过。。。如果是这样的呢?

   

 

要想完美拼接起来,那得需要多少boxcollider啊!

 

于是我又想到了另外一种方法:线性规划。

通过线性规划将所需区域围起来,点击时判断鼠标位置是否在规划区域里,从而解决不规则多边形的事件检测。

 

简单的做了一个Demo,部分代码如下:

直线类(相应的可以扩展各种曲线)

复制代码
public class Line
{
    public Vector2 StartPos { get; set; }
    public Vector2 EndPos { get; set; }
    public Line(Vector2 start, Vector2 end)
    {
        StartPos = start;
        EndPos = end;
    }
     /// <summary>
     ///计算点是否在该直线上
     /// </summary>
     /// <param name="point"></param>
     /// <returns>0:点在直线上;1:点在直线上方;-1:点在直线下方</returns>
    public int IsOnLine(Vector2 point)
    {
        float yOnLine = CalcYByX(point.x);
        if (Math.Abs(yOnLine - point.y) <= 0.001f) return 0;
        else
        {
            if ((yOnLine - point.y) > 0) return -1;
            else return 1;
        }
    }
    public float CalcYByX(float x)
    {
        if (StartPos.x == EndPos.x) throw new Exception("X1=X2");
        if (StartPos.y == EndPos.y) return StartPos.y;
        return (EndPos.y - StartPos.y) / (EndPos.x - StartPos.x) * (x - StartPos.x) + StartPos.y;
    }
}
复制代码

 

正六边形线性规划代码:

复制代码
 //线性规划解决点是否在正六边形内部
    bool IsInRegularHexagon(Vector2 center,float edge,Vector2 point)
    {
        Vector2 pUp=new Vector2(center.x,center.y+edge);
        Vector2 pDown = new Vector2(center.x, center.y - edge);
        Vector2 pLeft1 = new Vector2(center.x-1.732f/2*edge, center.y + edge/2); 
        Vector2 pLeft2=new Vector2(center.x-1.732f/2*edge, center.y - edge/2); 
        Vector2 pRight1=new Vector2(center.x+1.732f/2*edge, center.y + edge/2); 
        Vector2 pRight2=new Vector2(center.x+1.732f/2*edge, center.y - edge/2);
        Line line1 = new Line(pUp,pLeft1);
        Line line2 = new Line(pUp,pRight1);
        Line line3 = new Line(pDown,pLeft2);
        Line line4 = new Line(pDown,pRight2);
      
        if (point.x > (center.x - 1.732f / 2 * edge) && point.x < center.x + 1.732f / 2 * edge)
        {
            if (line1.IsOnLine(point)==-1&&
                line2.IsOnLine(point)==-1&&
                line3.IsOnLine(point)==1&&
                line4.IsOnLine(point)==1)
            {
                return true;
            }
        }
        return false;
    }
复制代码

 

编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示