unity RTS游戏中建筑摆放的一种思路

       一直想做一款类似红警的游戏,最近所系unity,所以搜集相关的代码,偶然的机会看到了youtube上的一段视频,做的挺不错的,虽然是几年前的,但是放到现在依然适用。

经过一方研究,才发现代码在assert store有售,看了下价格也不贵,10美元,折合人民币71.5,没办法,现在就这个汇率

最后买了下来,研究了一番,总算懂了,特此记录一下

有两点需要注意的,一是摆放的时候进行碰撞检测,而是,从摆放物体的四角和边的中间各发射一条向下的射线,然后求射线和地形交点的法线与向上方向的夹角,如果有某一个角大于0,说明不在平地上,则不能摆放,如果所有角都为0,说明在平地上,可以摆放,射线发射点的分析图如下

检测代码如下:

void Update()
    {
        Bounds bounds = goCollider.bounds;
        
        /******************************************************************************************* 
         *  Eight rays are used to detect gradient angle.
         *  the rays depend on the bounding box of the building box collider
         *  four on the corners of the bound and another four on the middle between each two corners
         *******************************************************************************************/

        // bounds corners
        p1.x = bounds.min.x - 1f;
        p1.y = bounds.max.y;
        p1.z = bounds.min.z - 1f;

        p2.x = bounds.max.x + 1f;
        p2.y = bounds.max.y;
        p2.z = bounds.min.z - 1f;

        p3.x = bounds.min.x - 1f;
        p3.y = bounds.max.y;
        p3.z = bounds.max.z + 1f;

        p4.x = bounds.max.x + 1f;
        p4.y = bounds.max.y;
        p4.z = bounds.max.z + 1;
            
        // middle corners
        p5.x = transform.position.x;
        p5.y = bounds.max.y;
        p5.z = bounds.min.z - 1f;

        p6.x = transform.position.x;
        p6.y = bounds.max.y;
        p6.z = bounds.max.z + 1f;

        p7.x = bounds.min.x - 1f;
        p7.y = bounds.max.y;
        p7.z = transform.position.z;

        p8.x = bounds.max.x + 1f;
        p8.y = bounds.max.y;
        p8.z = transform.position.z;

        // Rays positions
        r1.origin = p1;
        r1.direction = Vector3.down;

        r2.origin = p2;
        r2.direction = Vector3.down;

        r3.origin = p3;
        r3.direction = Vector3.down;

        r4.origin = p4;
        r4.direction = Vector3.down;
        
        r5.origin = p5;
        r5.direction = Vector3.down;

        r6.origin = p6;
        r6.direction = Vector3.down;

        r7.origin = p7;
        r7.direction = Vector3.down;

        r8.origin = p8;
        r8.direction = Vector3.down;


        /*******************************************************************************************
         * Dot product of two unit vectors yield the cosine of the angle between them
         * use the inverse function to get the angle and convert to degree
         *******************************************************************************************/
         
        if (Physics.Raycast(r1, out hit1, 100.0f))
            angle1 = Mathf.Acos(Vector3.Dot(hit1.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r2, out hit2, 100.0f))
            angle2 = Mathf.Acos(Vector3.Dot(hit2.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r3, out hit3, 100.0f))
            angle3 = Mathf.Acos(Vector3.Dot(hit3.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r4, out hit4, 100.0f))
            angle4 = Mathf.Acos(Vector3.Dot(hit4.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r5, out hit5, 100.0f))
            angle5 = Mathf.Acos(Vector3.Dot(hit5.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r6, out hit6, 100.0f))
            angle6 = Mathf.Acos(Vector3.Dot(hit6.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r7, out hit7, 100.0f))
            angle7 = Mathf.Acos(Vector3.Dot(hit7.normal, Vector3.up)) * ToDegree;

        if (Physics.Raycast(r8, out hit8, 100.0f))
            angle8 = Mathf.Acos(Vector3.Dot(hit8.normal, Vector3.up)) * ToDegree;
        Debug.Log("bounds.min is:"+bounds.min);
        Debug.Log("bounds.max is:"+bounds.max);
        Debug.Log("position is:"+transform.position);

        if (angle1 > maxGradient ||
            angle2 > maxGradient ||
            angle3 > maxGradient ||
            angle4 > maxGradient ||
            angle5 > maxGradient ||
            angle6 > maxGradient ||
            angle7 > maxGradient ||
            angle8 > maxGradient)
        {
            _legalSlope = false;
        }
        else
        {
            _legalSlope = true;
        }
        
    } // Update end

 

运行截图如下:

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值