在Unity中将相机平移与触摸控制结合起来

5

我被要求探索使用Unity创建一个简单的迭代应用程序,涉及到相机的两个主要功能。

  1. 将相机Lerp(线性插值)到一个目标对象上。
  2. 一旦移动,就放弃对相机的控制权,允许用户绕着对象旋转和缩放。

虽然我是新手,但我已经成功地创建了两个独立实现这些目标的脚本。现在我正在努力把它们合在一起。

首先是用户交互的相关代码。

首先,在Start中我使用TouchKit在每个帧上设置增量值。

// set the delta on each frame for horizontal and vertical rotation
var oneTouch = new TKPanRecognizer();
oneTouch.gestureRecognizedEvent += (r) =>
{
    HorizontalDelta += r.deltaTranslation.x * rotateSpeed * Time.deltaTime;
    VerticalDelta -= r.deltaTranslation.y * rotateSpeed * Time.deltaTime;
};

// do the same for pinch
var pinch = new TKPinchRecognizer();
pinch.gestureRecognizedEvent += (r) =>
{
    rotateDistance -= r.deltaScale * 200.0f * Time.deltaTime;
};

TouchKit.addGestureRecognizer(oneTouch);
TouchKit.addGestureRecognizer(pinch);

关于 更新

VerticalDelta = Mathf.Clamp(VerticalDelta, verticalPivotMin, verticalPivotMax);

var direction = GetDirection(HorizontalDelta, VerticalDelta);

var currentTarget = targetsSwitched ? target2 : target;

transform.position = currentTarget.position - direction * rotateDistance;
transform.LookAt(currentTarget.position);

// ...

private Vector3 GetDirection(float x, float y)
{
    Quaternion q = Quaternion.Euler(y, x, 0);
    return q * Vector3.forward;
}

这个代码非常好用,能够完美地实现我的要求。但是当我尝试将这段代码与我的相机移动脚本整合时,问题就出现了。下面的代码展示了我想添加 Update 代码的位置。

void Update ()
{
    if (currentlyMoving)
    {
        FocusTarget(currentTarget);
    }
    else
    {
        // accept user input if not moving
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SetMoveToTarget(mainTargetObject);
        }

        if (Input.GetKeyDown(KeyCode.Q))
        {
            SetMoveToTarget(subTargetObject1);
        }

        if (Input.GetKeyDown(KeyCode.E))
        {
            SetMoveToTarget(subTargetObject2);
        }
    }
}

这些是实际移动相机的功能:

void SetMoveToTarget(GameObject target)
{
    if (currentlyMoving == false)
    {
        currentlyMoving = true;
        fromRotation = currentTarget.transform.rotation;
        currentTarget = target;
        toRotation = currentTarget.transform.rotation;

        timeStartedLerping = Time.time;
    }
}

void FocusTarget(GameObject target)
{

    float timeSinceStarted = Time.time - timeStartedLerping;
    float percentageComplete = timeSinceStarted / (lerpSpeed);

    transform.position = Vector3.MoveTowards(transform.position, target.transform.position, moveSpeed * Time.deltaTime);
    transform.rotation = Quaternion.Lerp(fromRotation, toRotation, Mathf.Pow(percentageComplete, (float)1.2));

    if (Vector3.Distance(transform.position, target.transform.position) < 0.1 && percentageComplete > 0.99)
    {
        transform.position = target.transform.position;
        transform.rotation = target.transform.rotation;
        currentlyMoving = false;
    }
}

我认为我需要做的事情是(可能我错了),将 rotateDistance 设置为第二个脚本中的 currentTarget 和第一个脚本中的 currentTarget 之间的差异。

非常感谢,这对我来说很棘手。

1个回答

2

最终我不得不改变我处理移动相机的方式。问题在于移动到一个设定的游戏对象可以工作并且易于设置,但是如果你实际计算相机下一个位置应该在哪里并移动到那里,那么它将更容易与外观脚本集成。

我将在此处粘贴工作产品以备后用,它缺少一些结束游戏的东西,但相机正在工作。

using UnityEngine;
using UnityEngine.UI;

public class NewCamera : MonoBehaviour {

    // targets
    public GameObject target;
    public GameObject target2;

    // settings
    public float RotateSpeed = 50.0f;
    public float RotateDistance = 3;
    public float CameraMoveSpeed = 20f;

    public float VerticalPivotMin = 5;
    public float VerticalPivotMax = 65;

    public float MinZoomIn = 1.7f;
    public float MaxZoomIn = 4f;

    // private
    private GameObject lookTarget;

    private bool currentlyMoving = false;
    private Vector3 targetVector;
    private float timeStartedLerping;

    private float HorizontalDelta;
    private float VerticalDelta;

    void Start ()
    {
        lookTarget = target;

        var oneTouch = new TKPanRecognizer();
        oneTouch.gestureRecognizedEvent += (r) =>
        {
            if (currentlyMoving == false)
            {
                HorizontalDelta += r.deltaTranslation.x * RotateSpeed * Time.deltaTime;
                VerticalDelta -= r.deltaTranslation.y * RotateSpeed * Time.deltaTime;

                VerticalDelta = Mathf.Clamp(VerticalDelta, VerticalPivotMin, VerticalPivotMax);
            }
        };

        var pinch = new TKPinchRecognizer();
        pinch.gestureRecognizedEvent += (r) =>
        {
            if (currentlyMoving == false)
            {
                RotateDistance -= r.deltaScale * 200.0f * Time.deltaTime;
                RotateDistance = Mathf.Clamp(RotateDistance, MinZoomIn, MaxZoomIn);
            }
        };

        TouchKit.addGestureRecognizer(oneTouch);
        TouchKit.addGestureRecognizer(pinch);
    }

    void Update ()
    {
        if (currentlyMoving)
        {
            FocusTarget();
        }
        else
        {
            var direction = GetDirection(HorizontalDelta, VerticalDelta);

            transform.position = lookTarget.transform.position - direction * RotateDistance;
            transform.LookAt(lookTarget.transform.position);
        }
    }

    public void OnButtonClick()
    {
        var currentTarget = target.GetInstanceID() == lookTarget.GetInstanceID() ? target : target2;
        var nextTarget = currentTarget.GetInstanceID() == target.GetInstanceID() ? target2 : target;

        var cameraPosition = transform.position;
        var targetPosition = currentTarget.transform.position;

        SetMoveToTarget(nextTarget, cameraPosition - targetPosition);
    }

    void SetMoveToTarget(GameObject moveTo, Vector3 offset)
    {
        currentlyMoving = true;
        targetVector = moveTo.transform.position + offset;
        lookTarget = moveTo;
    }

    void FocusTarget()
    {
        transform.position = Vector3.Lerp(transform.position, targetVector, CameraMoveSpeed * Time.deltaTime);

        if (Vector3.Distance(transform.position, targetVector) < 0.01)
        {
            transform.position = targetVector;
            currentlyMoving = false;
        }
    }

    private Vector3 GetDirection(float x, float y)
    {
        Quaternion q = Quaternion.Euler(y, x, 0);
        return q * Vector3.forward;
    }
}

如果你想出于任何原因使用它,请将此脚本添加到相机并设置两个目标。我需要制作一个更健壮的版本,使您可以轻松添加新目标,但现在这样做就够了。
祝愉快的黑客活动!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接