一直想做一款类似红警的游戏,最近所系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
运行截图如下: