【问题标题】:Unity3D multiple UI Buttons change main camera position NOT SCENEUnity3D 多个 UI 按钮更改主摄像机位置 NOT SCENE
【发布时间】:2023-03-04 13:47:02
【问题描述】:

使用多个 UI 按钮尝试将主摄像头位置更改为不同的视图。我不想换场景。我正在看一个物体,比如说一辆车,我想看到前照灯,我想单击一个按钮来移动主摄像头以查看前照灯,并有一个显示文本“前照灯”的弹出窗口。然后我想移动到BrakeLights,我点击刹车灯按钮,然后主相机移动到刹车灯区域,并弹出另一个文本说“刹车灯”。每个汽车部件都有多个按钮,我被困住了,不熟悉统一并寻求帮助。

【问题讨论】:

  • 试试cinemamachine包。如果您寻找轻量级选项,有一个名为 Fungus 的免费资产,具有简单的相机位置切换功能。
  • 我会检查的。我确实导入了它,但我将不得不使用它来看看发生了什么。谢谢!

标签: unity3d camera uibutton lerp


【解决方案1】:

作为练习,我尝试编写一个简单的 C# 脚本来执行您在上面描述的操作。我希望这可以作为您自己的起点:

using UnityEngine;

public class CamSwitcher : MonoBehaviour {

    public CamSpotInfo[] spots;
    [Range(0.1f, 3.0f)] public float anim_speed = 0.3f;
    protected int idx = 0;
    protected float t_accum = 0.0f;

    void Update() {
        Transform cam = Camera.main.transform;
        cam.position = Vector3.Lerp(cam.position, spots[idx].transform.position, t_accum);
        cam.LookAt(spots[idx].target); /* TODO: interpolate target positions */
        t_accum += Time.deltaTime * anim_speed;
    }

    void OnGUI() {
        if (GUI.Button(new Rect(10, 70, 200, 30), "next spot: " + spots[idx].name)) {
            if (++idx >= spots.Length)
                idx = 0;
            t_accum = 0.0f;
        }
    }
}

[System.Serializable]
public class CamSpotInfo {
    public Transform transform;
    public Transform target;
    public string name;
}

为了给数组分配新的“相机点”,首先在 Unity 检查器中手动设置“大小”,然后将新的 GameObjects/transforms 从场景层次结构窗口拖动到检查器中数组的各个元素(例如,这些可以只是空的游戏对象,指示每个“相机点”的相机位置)。然后将相机目标分配给数组中的每个元素,您希望主相机查看每个“相机点”(例如轮子)。最后,为将显示在 GUI 按钮上的每个元素输入一个名称。

在本例中,在播放模式中将仅显示一个 GUI 按钮,用于切换到阵列中的下一个“点”。但你可以轻松修改脚本,让相机直接切换到特定元素...

(不确定这对于本网站是否真的是一个好问题,因为它是非常开放的,因为有很多不同的方法可以为此类功能提出可能的解决方案(涉及许多不同的领域,例如相机运动控制器、路径插值、GUI 等))。


编辑:多个 GUI 按钮

这是上面脚本的修改版本,它使用多个 GUI 按钮,每个相机点一个。每个都可以通过“显示 GUI”复选框在检查器中启用/禁用:

using UnityEngine;

public class CamSwitcher : MonoBehaviour {

    public CamSpotInfo[] spots;
    [Range(0.1f, 3.0f)] public float animSpeed = 0.3f;
    protected uint idx = 0;
    protected float t = 0.0f;

    void Update() {
        Transform cam = Camera.main.transform;
        Vector3 dir_target = spots[idx].target.position - cam.position;
        Quaternion roti = Quaternion.LookRotation(dir_target);
        cam.position = Vector3.Lerp(cam.position, spots[idx].transform.position, t);
        cam.rotation = Quaternion.Slerp(cam.rotation, roti, t);
        t += Time.deltaTime * animSpeed;
    }
    void OnGUI() {
        Rect rect = new Rect(10, 70, 200, 30);
        for (uint i=0; i<spots.Length; ++i) {
            if (spots[i].showGUI) {
                if (GUI.Button(rect, "switch to " + spots[i].name)) {
                    idx = i;
                    t = 0.0f;
                }
                rect.y += rect.height + 5;
            }
        }
    }
}

[System.Serializable]
public class CamSpotInfo {
    public Transform transform;
    public Transform target;
    public string name;
    public bool showGUI = true;
}

【讨论】:

  • 是的,这是我在模糊问题上的错误。我有一些类似于空对象的东西,该对象具有我最初想要的相机位置,并使用 if、else if、else 作为元素索引,但在更大范围内思考我试图找到其他解决方案。基本上这个想法是,拥有一个带有许多孩子(组成车辆的各个部分)的预制件的游戏对象。我想也许可以使用带有预制按钮并为每个孩子自动填充的滚动侧边栏。单击按钮时,主摄像头会摆动以查看零件和显示信息。谢谢你的帮助。
  • 嗨!我添加了一个带有多个按钮的版本(但没有滚动或任何其他高级 UI 内容)。希望有帮助! - 如果您的汽车对象是预制件,您仍然可以将子对象拖到阵列中作为相机目标。 - 要自动填充“凸轮点阵列”,您可以使用统一标签来标记应使用(其他)脚本添加到阵列的重要部分。或者,您可以将特殊的“标记脚本”添加到模型的重要部分,其中还包含标题、指向相应相机变换的链接等(请参阅:文档中的 Component.GetComponentsInChildren)。
【解决方案2】:

如果您愿意,您可以为每个位置创建两个Vector3,一个用于您希望摄像头所处的位置,另一个用于您希望摄像头面对的位置。

public Vector3 cameraPos;
public Vector3 cameraLootAkPos;

public void ChangeCameraTransform()
{
    Camera.main.transform.position = cameraPos;
    Camera.main.transform.LookAt(cameraLootAkPos);
}

如果你想使用它,我做了我自己的版本。上面的版本是一个即时转换,下面的版本在运行时转换更平滑。你可以考虑使用Mathf.Lerp

之类的东西更进一步
public class ChangeCamera : MonoBehaviour
{
    // You can populate each list with the appropriate positions. Making sure they are in order from 0 upward
    public List<Vector3> CameraPositions;
    public List<Vector3> CameraLookAtPositions;

    public Vector3 LookAtTarget;

    // to see which camera configuration we should use.
    public int CamConfig;

    float moveSpeed = .5f;
    float rotSpeed = .5f;

    public Transform MainCamera;

    void Update()
    {
        if (MainCamera.position != CameraPositions[CamConfig])
        {
            MainCamera.position = Vector3.MoveTowards(MainCamera.position, CameraPositions[CamConfig], moveSpeed);
        }
        LookAtTarget = Vector3.MoveTowards(LookAtTarget, CameraLookAtPositions[CamConfig], rotSpeed);
        MainCamera.LookAt(LookAtTarget);
    }

    public void ChangeCameraConfig(int ConfigNo)
    {
        CamConfig = ConfigNo;
    }
}

【讨论】:

  • 我确实试过这个,它有帮助。我很感激它,并会看看我是否可以在它的基础上进一步发展。再次感谢。
  • 嗨,我包含了我自己的工作实现的更新,也许它可以帮助你获得你想要的更流畅的结果;D
【解决方案3】:

如果我的理解正确,您有多个按钮,单击每个按钮会将您的主摄像头移动到与该按钮对应的位置。你应该做的是:

  1. 创建一个脚本来存储您要显示的文本以及相机的位置和旋转。将其附加到每个按钮的游戏对象。

  2. 然后,在该脚本中创建一个函数来设置文本和相机位置/旋转。脚本应如下所示:


using UnityEngine;
using UnityEngine.UI;

public class CameraSwitch : MonoBehaviour
{
    public Text UILabel;
    public string text;
    public Vector3 cameraPos;
    public Vector3 cameraRot;

    public void SwitchToHere()
    {
        Camera.main.transform.position = cameraPos;
        Camera.main.transform.rotation = Quaternion.Euler(cameraRot);
        UILabel.text = text;
    }
}

  1. 返回 Unity。在每个按钮的 OnClick 事件中,订阅(添加)您刚刚创建的函数。 (请务必从附加到该按钮的脚本中添加功能)

  2. 将文本更改为您想要的任何内容,并将 cameraPos 和 cameraRot 设置为您希望按下此按钮时相机切换到的位置。


这是我做整个事情的视频:https://youtu.be/L621IcEBAtU

这肯定会奏效,但每个点之间的过渡是即时的。如果你想要一个平滑的过渡,你可以使用电影机包或更改脚本。

【讨论】:

  • 感谢您的帮助。我试过这个,效果很好。我还将尝试提到的其他人,看看还有什么可以添加或改进的。我的问题不是很具体,这是我的错误,但你的回答确实有帮助。
猜你喜欢
  • 2017-03-09
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多