判断游戏对象是否在摄像机视口的一个方法

本人菜鸟,用了笨方法实现。大家有更好的方法不吝赐教。
就是对游戏对象绘制一个长方体包围盒,然后用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);
}

不过如果是要求全部位于视口内的话,可以借鉴楼主的方法去稍作修改。

 

posted on 2017-04-19 16:34  jiahuafu  阅读(715)  评论(1编辑  收藏  举报

导航