首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >放大照相机,使它能看到所有物体

放大照相机,使它能看到所有物体
EN

Stack Overflow用户
提问于 2022-11-05 09:07:20
回答 2查看 43关注 0票数 1

我有一个对象列表,这些都是视频上的蓝色贴纸,我需要让相机自己移动,所有的物体(蓝色贴纸)总是适合它的,你需要考虑到每次都会有越来越多的物体,所以相机应该是动态的,并且适应所有的物体。

https://youtube.com/shorts/x3uSO2L22Kc?feature=share

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-05 15:43:48

任意摄像机角度和物体位置的实用解

这里的想法很简单.

在每一步中,我们检查每个物体是在摄像机视图中还是相机太远,然后我们简单地调整相机的位置,使之更好。

一步一步,我们的相机将动态跟踪目标对象,当稳定后,所有目标对象都将被摄像机捕获。

代码语言:javascript
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraAutoFitSmooth : MonoBehaviour
{
    public int maxNumberOfObjs = 100;
    public GameObject objPrefab;
    public float maxInitRange = 10f;

    public float minCameraHeight = 1f;
    public float maxCameraMoveSpeed = 9f;
    public float marginalPos = 0.1f;

    [HideInInspector]
    public List<Transform> objs = new List<Transform>();
    Camera cam;

    void Start()
    {
        cam = Camera.main;
    }

    void Update() 
    {
        if (Input.GetKeyDown(KeyCode.Space))
            RandomObjs();
    }

    // Randomly regenerate objects
    void RandomObjs()
    {
        int nowNumberOfObjs = Random.Range(0, maxNumberOfObjs);
        for (int i = objs.Count - 1; i > nowNumberOfObjs; i--)
        {
            Destroy(objs[i].gameObject);
            objs.RemoveAt(i);
        }

        for (int i = objs.Count; i <= nowNumberOfObjs; i++)
            objs.Add(Instantiate(objPrefab).transform);
            
        foreach (var obj in objs)
            obj.position = Random.insideUnitSphere * maxInitRange;
    }

    void LateUpdate()
    {
        SetCameraFitPosition(Time.deltaTime);
    }

    void SetCameraFitPosition(float deltaTime)
    {
        Vector3 targetCamPos = cam.transform.position;
        if (objs.Count == 1)
        {
            targetCamPos = objs[0].position - minCameraHeight * cam.transform.forward;
        }
        else if (objs.Count > 1)
        {
            float minInsideDiff = 1f, maxOutsideDiff = 0f;
            Vector3 center = Vector3.zero;
            foreach (var obj in objs)
            {
                Vector3 screenPos = GetScreenPos(obj.position);

                if (IsInsideView(screenPos))
                    minInsideDiff = Mathf.Min(minInsideDiff, CalculateInsideDiff(screenPos.x), CalculateInsideDiff(screenPos.y), CalculateInsideDiff(screenPos.z));
                else
                    maxOutsideDiff = Mathf.Max(maxOutsideDiff, CalculateOutsideDiff(screenPos.x), CalculateOutsideDiff(screenPos.y), CalculateOutsideDiff(screenPos.z));

                center += obj.position;
            }
            center /= objs.Count;

            float nowHeight = Vector3.Project(cam.transform.position - center, cam.transform.forward).magnitude;
            float maxDiff = maxOutsideDiff > 0f ? maxOutsideDiff : -minInsideDiff;
            float finalHeight = Mathf.Max(nowHeight + maxDiff * maxCameraMoveSpeed, minCameraHeight);

            targetCamPos = center - finalHeight * cam.transform.forward;
        }

        cam.transform.position = Vector3.MoveTowards(cam.transform.position, targetCamPos, maxCameraMoveSpeed * deltaTime);
    }

    Vector3 GetScreenPos(Vector3 pos)
    {
        return cam.WorldToViewportPoint(pos);
    }
    float CalculateOutsideDiff(float pos)
    {
        float diff = 0f;
        if (pos > 1f + marginalPos)
            diff = pos - 1f;
        else if (pos < -marginalPos)
            diff = -pos;
        return diff;
    }
    float CalculateInsideDiff(float pos)
    {
        float diff = 0f;
        if (pos < 1f - marginalPos && pos > marginalPos)
            diff = Mathf.Min(1f - pos, pos);
        return diff;
    }
    bool IsInsideView(Vector3 screenPoint)
    {
        return screenPoint.z > 0f && screenPoint.x > 0f && screenPoint.x < 1 && screenPoint.y > 0f && screenPoint.y < 1;
    }
}

,如果您需要更多信息,请随时与我联系:)干杯!

票数 1
EN

Stack Overflow用户

发布于 2022-11-05 12:35:04

下面的脚本将在自顶向下的视图中放置一个透视摄像机,以便所有跟踪的GameObjects (objs)都是可见的。

假设物体在零xz平面上,是点,因此不考虑它们的实际尺寸。必须至少有一个跟踪对象。物体的间距不可能要求照相机的高度超过最大浮点值。

代码语言:javascript
复制
public GameObject[] objs;//objects that must be fitted
private Camera cam;
float recXmin, recXmax, recYmin, recYmax;
Vector3 center;

void Start()
{
  cam = Camera.main;
  cam.transform.rotation = Quaternion.Euler(90, 0, 0);
}

void LateUpdate()
{
  recXmin = objs[0].transform.position.x;
  recXmax = objs[0].transform.position.x;
  recYmin = objs[0].transform.position.z;
  recYmax = objs[0].transform.position.z;
  center = Vector3.zero;

  foreach (GameObject obj in objs)
  {
    if (obj.transform.position.x < recXmin)
    {
    recXmin = obj.transform.position.x;
    }
    if (obj.transform.position.x > recXmax)
    {
    recXmax = obj.transform.position.x;
    }
    if (obj.transform.position.z < recYmin)
    {
    recYmin = obj.transform.position.z;
    }
    if (obj.transform.position.z > recYmax)
    {
    recYmax = obj.transform.position.z;
    }
  }

  float horizontalHeight = (recYmax - recYmin) / 2 / Mathf.Tan(Mathf.Deg2Rad * cam.fieldOfView / 2);
  float verticalHeight = (recXmax - recXmin) / 2 / Mathf.Tan(Mathf.Deg2Rad * Camera.VerticalToHorizontalFieldOfView(cam.fieldOfView, cam.aspect) / 2);
  float finalHeight = horizontalHeight > verticalHeight ? horizontalHeight : verticalHeight;
  center = new Vector3(recXmin + (recXmax - recXmin) / 2, finalHeight, recYmin + (recYmax - recYmin) / 2);
  cam.transform.position = center;
}

void OnDrawGizmos()
{
  Gizmos.color = Color.red;
  Gizmos.DrawLine(new Vector3(recXmin, 0, recYmin), new Vector3(recXmin, 0, recYmax));
  Gizmos.DrawLine(new Vector3(recXmax, 0, recYmin), new Vector3(recXmax, 0, recYmax));

  Gizmos.color = Color.green;
  Gizmos.DrawLine(new Vector3(recXmin, 0, recYmin), new Vector3(recXmax, 0, recYmin));
  Gizmos.DrawLine(new Vector3(recXmin, 0, recYmax), new Vector3(recXmax, 0, recYmax));

  Gizmos.color = Color.blue;
  Gizmos.DrawSphere(center, 0.5f);
}

selected

  • lastly
  • 脚本确定由所有跟踪物体(
  • )形成的“包围方”。边界平方被假定为金字塔的基础,摄像机在其峰值
  • 上使用三角函数来计算相机的高度,考虑到金字塔底部已知的长度和摄像机视场的
  • ,对摄像机的水平和垂直视场

H 111进行了两次计算,这两个值越大,相机就会被定位到金字塔底部的中间和确定的高度,所以它最终到达了金字塔的顶峰

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74326457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档