鏡頭圍繞目標旋轉

© 2025 魔力結構 未經授權,請勿任意轉載、改作或商業使用,僅供個人學習參考用途

using UnityEngine;

public class GarageOrbitCamera : MonoBehaviour
{
    public Transform target;
    public float distance = 15f;
    public float zoomSpeed = 2f;
    public float minDistance = 5f;
    public float maxDistance = 25f;

    public float rotationSpeed = 5f;
    public float verticalLimit = 80f;

    [Header("自動旋轉設定")]
    public float idleTimeThreshold = 5f;
    public float autoYawSpeed = 10f;
    public float autoPitchAmplitude = 5f;
    public float autoPitchMin = 10f;
    public float autoPitchMax = 25f;
    public float autoPitchSpeed = 0.5f; // sin 波速度

    private float yaw = 90f;
    private float pitch = 20f;

    private float targetPitch;
    private float targetDistance;

    private float idleTimer = 0f;
    private float autoPitchTimer = 0f;

    private Vector3 currentPos;

    private Vector2 lastMousePos;
    private bool isDragging = false;

    void Start()
    {
        targetPitch = pitch;
        targetDistance = distance;
        currentPos = transform.position;
    }

    void LateUpdate()
    {
        if (target == null) return;

        bool isUserInput = false;

        // 玩家控制:滑鼠左鍵旋轉
        if (Input.GetMouseButton(0))
        {
            if (Input.GetMouseButtonDown(0))
            {
                targetPitch = pitch;
                idleTimer = 0f;
                autoPitchTimer = 0f;

                // 記錄滑鼠起點
                lastMousePos = Input.mousePosition;
                isDragging = true;
            }
            else if (Input.GetMouseButtonUp(0))
            {
                isDragging = false;
            }

            if (isDragging)
            {
                Vector2 currentMousePos = Input.mousePosition;
                Vector2 delta = currentMousePos - lastMousePos;
                lastMousePos = currentMousePos;

                yaw += delta.x * 0.2f; // 可以調整旋轉速度
                targetPitch -= delta.y * 0.2f;
                targetPitch = Mathf.Clamp(targetPitch, 5f, verticalLimit);

                isUserInput = true;
            }

        }

        // 玩家控制:滾輪縮放
        float scroll = Input.GetAxis("Mouse ScrollWheel");
        if (Mathf.Abs(scroll) > 0.001f)
        {
            targetDistance -= scroll * zoomSpeed;
            targetDistance = Mathf.Clamp(targetDistance, minDistance, maxDistance);
            isUserInput = true;
        }

        // 使用者操作 → 重置 idle timer
        if (isUserInput)
        {
            idleTimer = 0f;
            autoPitchTimer = 0f;
        }
        else
        {
            idleTimer += Time.deltaTime;

            // 閒置一段時間 → 啟動自轉
            if (idleTimer > idleTimeThreshold)
            {
                yaw += autoYawSpeed * Time.deltaTime;

                // 使用 sin 波進行 pitch 起伏
                autoPitchTimer += Time.deltaTime * autoPitchSpeed;
                float sinOffset = Mathf.Sin(autoPitchTimer) * autoPitchAmplitude;
                if (!Input.GetMouseButton(0)) // 如果滑鼠沒按下才自動改 pitch
                {
                    float autoPitch = Mathf.Clamp(17.5f + sinOffset, autoPitchMin, autoPitchMax);
                    targetPitch = autoPitch;
                }
            }
        }

        // 平滑 pitch & zoom
        pitch = Mathf.Lerp(pitch, targetPitch, Time.deltaTime * 4f);
        distance = Mathf.Lerp(distance, targetDistance, Time.deltaTime * 6f);

        // 平滑移動攝影機位置
        Quaternion rotation = Quaternion.Euler(pitch, yaw, 0);
        Vector3 desiredPos = rotation * new Vector3(0, 0, -distance) + target.position;
        currentPos = Vector3.Lerp(currentPos, desiredPos, Time.deltaTime * 6f);
        transform.position = currentPos;

        // 保持 yaw 在 0~360 區間(避免無限增長)
        if (yaw < 0f) yaw += 360f;
        yaw %= 360f;


        // 永遠鎖定展示中心
        transform.LookAt(target.position);
    }
}

此網誌的熱門文章

哥利亞遙控炸彈 (Leichter Ladungsträger Goliath)

O-I(試製120t超重戰車「オイ」)