怎么样使用Unity相机确定AI代理的视线范围,求大伙帮忙

在线求帮请教一下,怎么样使用Unity相机确定AI代理的视线范围,求大伙帮忙
最新回答
自在安然

2024-07-02 01:58:43

我的想法是为每一个智能代理,viewsensor绑定一个camera。相机的设置有一定的视野,和远平面。Unity有两个用于相机测试的很方便的方法,第一个返回6个截面来定义的摄像头截(camera frustum),第二个告诉一个边界对象是在摄像头截的内部还是外部。

现在我们可以知道一个gameobjet是否在我们的观图内,但不是我们是否可以看到它,因为它可能会被另一个更接近摄影机位置的对象遮挡。所以我使用linecasts告知我们是否可以看到这个对象。但我应该转换哪个位置?对象的中心位置是一个很好的选择,但不一定足够准确。我使用对象网格边界,并遍历了所有的边界位置,当linecast不经过任何东西时停止,然后我知道是否可以看到对象。

最完美的方式是为网格的每个顶点之间做一个linecast,但它将花费太多的时间。

获取所有GameObjects

现在我们有一个函数告诉我们一个特定的对象是否在人工智能的视线内,我只是测试每个对象,由一个相机位置为原点,以相机远平面的距离为半径进行重叠范围检查。我为每个对象调用之前的SeeGameObject函数并将在视线内的对象保存在一个数组中。
public bool SeeGameObject(GameObject go)

{

// if object has a renderer and visible by any camera and is in this camera frustum

if(go.renderer != null && go.renderer.isVisible && GeometryUtility.TestPlanesAABB(GeometryUtility.CalculateFrustumPlanes(_camera), go.renderer.bounds))

{

RaycastHit hitInfo;

// by default we use the rough renderer bounds

Vector3 center = go.renderer.bounds.center;

Vector3 extents = go.renderer.bounds.extents;

float coefreduc = 0.8f;

Vector3[] gobounds; // points to check for linecast from camera

MeshFilter meshfilter = go.GetComponent<MeshFilter>();

if(meshfilter != null) // Almost every interesting game object that is render has a mesh

{

center = go.transform.position;

extents = meshfilter.mesh.bounds.extents;

extents.Scale(go.transform.lossyScale);

gobounds = new Vector3[33]{ // We can add more or remove some, it increase precision for not too much time or memory cost

Vector3.zero,

go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.9f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.5f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.75f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.25f),

go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.25f)

};

}

else // Only if gameobject has no mesh (= almost never) (Very approximately checking points using the renderer bounds and not the mesh bounds)

{

gobounds = new Vector3[9]{

Vector3.zero,

new Vector3(extents.x,extents.y,extents.z)*coefreduc,

new Vector3(extents.x,extents.y,-extents.z)*coefreduc,

new Vector3(extents.x,-extents.y,extents.z)*coefreduc,

new Vector3(extents.x,-extents.y,-extents.z)*coefreduc,

new Vector3(-extents.x,extents.y,extents.z)*coefreduc,

new Vector3(-extents.x,extents.y,-extents.z)*coefreduc,

new Vector3(-extents.x,-extents.y,extents.z)*coefreduc,

new Vector3(-extents.x,-extents.y,-extents.z)*coefreduc

};

}

foreach(Vector3 v in gobounds)

{

// test if it can see gameobject

if(GeometryUtility.TestPlanesAABB(GeometryUtility.CalculateFrustumPlanes(_camera), new Bounds(v+center, Vector3.zero)) // if point in viewing frustrum

&& (!Physics.Linecast(transform.position, v+center, out hitInfo) || hitInfo.collider.gameObject == go )) // if nothing between viewing position and point

{

if(graphicalDebug)

{

Debug.DrawLine(transform.position, v+center,Color.red, 0.01f, false);

}

return true;

}

}

}

return false;

}
如果你还有什么不懂的,可以百度搜下:编程回忆录,他们现在正在录制这方面的教程,都是零基础开始,由浅入深。