【问题标题】:how to check whether a not-rendered object is in camera如何检查未渲染的对象是否在相机中
【发布时间】:2022-10-04 16:00:25
【问题描述】:

我刚开始学习Unity,遇到了一些问题。

在这里,我有一个预制对象ParticleAlly,其父对象ParticleAllies。父对象自己旋转,ParticleAlly 也旋转,就像行星和卫星一样。

此外,我还想在每个ParticleAlly 离开相机后立即重新生成它。然后它们在不同的轨道上,只有相同的角速度,但在不同的位置。当它进入然后离开相机时,再做一次。

问题是,一些ParticleAlly在重新生成后直接出现在相机中间。我试图让他们在他们从外面进入相机之前不被渲染。但似乎SpriteRenderer.isvisible 只有在SpriteRenderer.enabled 为真时才为真,所以我不知道何时再次渲染它们。然后我尝试通过位置来判断,但我不知道为什么它根本不起作用。

我完全糊涂了,为此浪费了整个上午。很抱歉我的描述和术语使用不准确。

如果您能为我提供解决方案并告诉我有关Update()、渲染、旋转中的位置/本地位置等的信息,我们将不胜感激。

// in ParticleAlly
void Update() {
        //Debug.Log(trans.localPosition.y);
        if(trans.position.y <= globalSettings.RotationLocationY) {
            Debug.Log("Under");
            if(!isRefreshed) {
                refresh();
            }
            sRender.enabled = true;
        }
        else {
            if(sRender.isVisible) {
                isRefreshed = false;
            }
        }
}

/// <summary>
/// Regenerate the particle
/// </summary>
void refresh() {
        isRefreshed = true;

        float height = Random.value * 3;
        trans.localPosition = (new Vector3(0f, globalSettings.RotationLocationY - height, 0f));
        //trans.RotateAround(trans.parent.localPosition, new Vector3(0f, 0f, 1f), globalSettings.getDegree() * Random.value);
        trans.localRotation = Quaternion.Euler(new Vector3(0f, 0f, globalSettings.getDegree() * Random.value));

        //sRender.enabled = false;
}

// in ParticleAllies
void Update() {
       trans.localRotation = Quaternion.Euler(new Vector3(0f, 0f, globalSettings.getDegree()));
}

这是我第一次在这里问,标签在代码中以某种方式被破坏了?

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    Renderer.isVisible 的问题在于

    • 正如您已经指出的,如果启用了渲染器,它只能是 true
    • 即使对象本身不可见但对渲染有一些视觉影响(例如阴影),它也可以保持true

    如果位置足够,您可以简单地使用例如

    public static class Extensions
    {
        pulic static bool IsInFrustum(this Camera camera, Vector3 worldPoint)
        {
            var screenPos = camera.WoldToscreenPoint(worldPoint);
            return screenPos.z >= camera.nearClipPlane
                   && screenPos.z <= camera.farClipPlane
                   && screenPos.x >= 0
                   && screenPos.x <= Screen.width
                   && screenPos.y >= 0
                   && screenPos.y <= Screen.height;
        }
    
        public static bool sInFrustum(this Vector3 worldPoint, Camera camera)
        {
            return camera.IsInFrustum(worldPoint);
        }
    }
    

    并且会做例如

    someRenderer.enabled = yourCamera.IsInFrustum(someRenderer.transform.position);
    

    或者也

    someRenderer.enabled = someRenderer.transform.position.IsInFrustum(yourCamera);
    

    如果单个位置不够,您可以使用GeometryUtility.CalculateFrustumPlanes 获取相机平截头体平面,然后检查是否有一些Bounds,例如Renderer.bounds 属于使用 GeometryUtility.TestPlanesAABB 的人。

    当然,边界并不总是完全准确,但可能是您可以获得的最佳近似值。

    public static class Extensions
    {
        public static bool IsInFrustum(this Renderer renderer, Camera camera)
        {
            var planes = GeometryUtility.CalculateFrustumPlanes(camera);
            return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
        }
    
        public static bool IsInFrustum(this Camera camera, Renderer renderer)
        {
            return renderer.IsVisibleFrom(camera);
        }
    }
    

    您现在可以在相机上使用,例如

    someRenderer.enabled = yourCamera.IsInFrustum(someRenderer);
    

    或者也

    someRenderer.enabled = someRenderer.IsInFrustum(yourCamera);
    

    【讨论】:

      猜你喜欢
      • 2014-04-14
      • 1970-01-01
      • 2013-10-17
      • 2015-01-12
      • 2019-07-13
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 1970-01-01
      相关资源
      最近更新 更多