判断游戏对象是否在摄像机视口的一个方法
本人菜鸟,用了笨方法实现。大家有更好的方法不吝赐教。
就是对游戏对象绘制一个长方体包围盒,然后用Camera.WorldToViewportPoint()处理。
将附件代码拖到场景中的要检测的游戏对象即可。比较简单的代码。
using UnityEngine; using System.Collections; /// <summary> /// 脚本挂到需要检测是否在摄像机视口内的游戏对象上。 /// By Braith /// 2014-09-24 /// </summary> public class CameraViewCheck : MonoBehaviour { private Transform _target; public Camera _camera; private bool _gameObjectView = true; private float _targetSize_width; //对象宽度,X private float _targetSize_height;//对象高度,Y private float _targetSize_depth; //对象深度,Z private Vector3 _vector01; private Vector3 _vector02; private Vector3 _vector03; private Vector3 _vector04; private Vector3 _vector05; private Vector3 _vector06; private Vector3 _vector07; private Vector3 _vector08; private Vector3 _viewPos01; private Vector3 _viewPos02; private Vector3 _viewPos03; private Vector3 _viewPos04; private Vector3 _viewPos05; private Vector3 _viewPos06; private Vector3 _viewPos07; private Vector3 _viewPos08; // Use this for initialization void Start () { _target = this.transform; _camera = Camera.main; _targetSize_width = _target.renderer.bounds.size.x; _targetSize_height = _target.renderer.bounds.size.y; _targetSize_depth = _target.renderer.bounds.size.z; } // Update is called once per frame void Update () { _vector01 = new Vector3(_target.position.x - _targetSize_width * 0.5f, _target.position.y + _targetSize_height * 0.5f, _target.position.z - _targetSize_depth * 0.5f);//摄像机视口左上角点1。 _vector02 = new Vector3(_target.position.x + _targetSize_width * 0.5f, _target.position.y + _targetSize_height * 0.5f, _target.position.z - _targetSize_depth * 0.5f);//摄像机视口右上角点1。 _vector03 = new Vector3(_target.position.x - _targetSize_width * 0.5f, _target.position.y - _targetSize_height * 0.5f, _target.position.z - _targetSize_depth * 0.5f);//摄像机视口左下角点1。 _vector04 = new Vector3(_target.position.x + _targetSize_width * 0.5f, _target.position.y - _targetSize_height * 0.5f, _target.position.z - _targetSize_depth * 0.5f);//摄像机视口右下角点1。 _vector05 = new Vector3(_target.position.x - _targetSize_width * 0.5f, _target.position.y + _targetSize_height * 0.5f, _target.position.z + _targetSize_depth * 0.5f);//摄像机视口左上角点2。 _vector06 = new Vector3(_target.position.x + _targetSize_width * 0.5f, _target.position.y + _targetSize_height * 0.5f, _target.position.z + _targetSize_depth * 0.5f);//摄像机视口右上角点2。 _vector07 = new Vector3(_target.position.x - _targetSize_width * 0.5f, _target.position.y - _targetSize_height * 0.5f, _target.position.z + _targetSize_depth * 0.5f);//摄像机视口左下角点2。 _vector08 = new Vector3(_target.position.x + _targetSize_width * 0.5f, _target.position.y - _targetSize_height * 0.5f, _target.position.z + _targetSize_depth * 0.5f);//摄像机视口右下角点2。 //Camera.WorldToViewportPoint 世界转视窗位置 _viewPos01 = _camera.WorldToViewportPoint(_vector01); _viewPos02 = _camera.WorldToViewportPoint(_vector02); _viewPos03 = _camera.WorldToViewportPoint(_vector03); _viewPos04 = _camera.WorldToViewportPoint(_vector04); _viewPos05 = _camera.WorldToViewportPoint(_vector05); _viewPos06 = _camera.WorldToViewportPoint(_vector06); _viewPos07 = _camera.WorldToViewportPoint(_vector07); _viewPos08 = _camera.WorldToViewportPoint(_vector08); BoundsDrawRay();//绘制游戏对象包围轮廓 if ( (_viewPos01.x > 1 || _viewPos01.x < 0 || _viewPos01.y > 1 || _viewPos01.y < 0) && (_viewPos02.x > 1 || _viewPos02.x < 0 || _viewPos02.y > 1 || _viewPos02.y < 0) && (_viewPos03.x > 1 || _viewPos03.x < 0 || _viewPos03.y > 1 || _viewPos03.y < 0) && (_viewPos04.x > 1 || _viewPos04.x < 0 || _viewPos04.y > 1 || _viewPos04.y < 0) && (_viewPos05.x > 1 || _viewPos05.x < 0 || _viewPos05.y > 1 || _viewPos05.y < 0) && (_viewPos06.x > 1 || _viewPos06.x < 0 || _viewPos06.y > 1 || _viewPos06.y < 0) && (_viewPos07.x > 1 || _viewPos07.x < 0 || _viewPos07.y > 1 || _viewPos07.y < 0) && (_viewPos08.x > 1 || _viewPos08.x < 0 || _viewPos08.y > 1 || _viewPos08.y < 0) ) { _gameObjectView = false; } else if ( _viewPos01.z < 0 && _viewPos02.z < 0 && _viewPos03.z < 0 && _viewPos04.z < 0 && _viewPos05.z < 0 && _viewPos06.z < 0 && _viewPos07.z < 0 && _viewPos08.z < 0 ) { _gameObjectView = false; } else { _gameObjectView = true; } if (!_gameObjectView)//游戏对象不在摄像机视口内 { _target.renderer.material.color = Color.red; Debug.Log("对象移出了摄像机视口"); } else//游戏对象在摄像机视口内 { Debug.Log("对象在摄像机视口内"); _target.renderer.material.color = Color.white; } } void BoundsDrawRay() { Debug.DrawRay(_vector01, _vector02 - _vector01, Color.red); Debug.DrawRay(_vector02, _vector04 - _vector02, Color.red); Debug.DrawRay(_vector03, _vector01 - _vector03, Color.red); Debug.DrawRay(_vector04, _vector03 - _vector04, Color.red); Debug.DrawRay(_vector05, _vector06 - _vector05, Color.red); Debug.DrawRay(_vector06, _vector08 - _vector06, Color.red); Debug.DrawRay(_vector07, _vector05 - _vector07, Color.red); Debug.DrawRay(_vector08, _vector07 - _vector08, Color.red); Debug.DrawRay(_vector01, _vector05 - _vector01, Color.red); Debug.DrawRay(_vector02, _vector06 - _vector02, Color.red); Debug.DrawRay(_vector03, _vector07 - _vector03, Color.red); Debug.DrawRay(_vector04, _vector08 - _vector04, Color.red); } }
---------------------------------------------------------------------------------------------------------
楼主实现的方法,可以直接调用Unity自带的。
//物体在摄像机视口的6个面内,包括部分位于 public bool IsVisibleFrom(Renderer renderer, Camera camera) { Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera); return GeometryUtility.TestPlanesAABB(planes, renderer.bounds); }
不过如果是要求全部位于视口内的话,可以借鉴楼主的方法去稍作修改。