繁体   English   中英

Unity 2D - 放大= ok,缩小= borked

[英]Unity 2D - zoom in =ok, zoom out = borked

我希望有人能帮帮忙。 我试图创建一个小脚本,放大到我的播放器并退出 - 切换。 放大工作正常,但当我尝试缩小它不起作用时,它会卡住。 我创建了一个bool,以确保它只在需要时运行代码,我想知道这是否是导致错误的原因。

using UnityEngine;
using System.Collections;

public class CameraZoom : MonoBehaviour
{

public float zoom = 10f;
public float normal = 3.471398f;
public float smooth = 5f;
private bool isZoomed = false;

public Camera cam;
public GameObject player;

// lock the camera settings
public float LockedX = 0f;
public float LockedY = 0f;
public float LockedZ = 0f;
private bool hasBeenZoomed =  false;

Vector3 targetPos;

private Transform playerTransform;

// Use this for initialization
void Start()
{
    targetPos = transform.position;
    playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
}

// Update is called once per frame
void Update()
{
    if (Input.GetKeyDown("z")) { isZoomed = !isZoomed; }
    if (isZoomed == true)
    {
        ZoomInToPlayer();
        hasBeenZoomed = true;
    }
    else
    {
        if (hasBeenZoomed)
        {
            ZoomOutFromPlayer();
            hasBeenZoomed = false;
        }
    }
}

void ZoomInToPlayer()
{
    // By default the target x and y coordinates of the camera are it's current x and y coordinates.
    float targetX = transform.position.x;
    float targetY = transform.position.y;

    // ... the target x coordinate should be a Lerp between the camera's current x position and the player's current x position.
    targetX = Mathf.Lerp(transform.position.x, playerTransform.position.x, smooth * Time.deltaTime);
    //Debug.Log("player x is " + playerTransform.position.x + " and TargetX is " + targetX);

    // ... the target y coordinate should be a Lerp between the camera's current y position and the player's current y position.
    targetY = Mathf.Lerp(transform.position.y, playerTransform.position.y, smooth * Time.deltaTime);
    //Debug.Log("player y is " + playerTransform.position.y+ " and TargetY is " + targetY);


    // Set the camera's position to the target position with the same z component.
    cam.transform.position = new Vector3(targetX, targetY, transform.position.z);

    // Change the size of the camera viewport
    cam.orthographicSize = Mathf.Lerp(cam.orthographicSize, zoom, Time.deltaTime * smooth);
}

void ZoomOutFromPlayer()
{
    // By default the target x and y coordinates of the camera are it's current x and y coordinates.
    float targetX;
    float targetY;

    // Change the size of the camera viewport
    cam.orthographicSize = Mathf.Lerp(cam.orthographicSize, normal, Time.deltaTime * smooth);

    // ... the target x coordinate should be a Lerp between the camera's current x position and the original x position.
    targetX = Mathf.Lerp(transform.position.x, LockedX, smooth * Time.deltaTime);
    // ... the target y coordinate should be a Lerp between the camera's current y position and the original y position.
    targetY = Mathf.Lerp(transform.position.y, LockedY, smooth * Time.deltaTime);
    // Set the camera's position to the target position with the same z component.
    cam.transform.position = new Vector3(targetX, targetY, transform.position.z);

}
}

您的方法ZoomInToPlayerZoomOutFromPlayer的编写方式表明,在放大/缩小动画期间,每帧应调用一次。 然而, ZoomOutFromPlayer才会被调用一次,因为Update ,当ZoomOutFromPlayer被调用时, hasBeenZoomed立即设置为false。

你在这里尝试做的基本上是一个简单的有限状态机 我建议稍微研究一下这个设计模式 - 它会帮助你注意到这些问题的根源,并以更好的方式构建你的代码。

在这种特殊情况下,在设计代码时防止出现此问题的一种好方法是在编写方法时为自己编写类似于“API文档”的内容。 对于ZoomOutFromPlayer ,它将读取如下内容:

想要执行缩小动画时调用每一帧,直到动画完成。

在你写完(并阅读)这样的描述后,你应该立即注意到一个红旗 - “直到动画完成”? 那么,在一个单独的机制中,调用此方法的代码应该以某种方式跟踪动画是否完整? 难道不能错误地使用这种方法吗? 嗯,这就是这里发生的事情。

相反,你可以做的是创建两个不同的方法, ZoomInUpdateZoomOutUpdate ,其描述可以是这样的:

在相机应缩小/放大时调用每一帧。

这样,使用这种方法就容易多了,你可以安全地抛弃hasBeenZoomed额外逻辑。 只需每帧调用这些方法,并确保(在这些方法中)他们以一定的速度更改相机设置,如果需要更改这些设置,或者不执行任何操作。

尝试这个

using UnityEngine;
using System.Collections;

public class CameraZoom : MonoBehaviour
{

public float zoom = 10f;
public float normal = 3.471398f;
public float smooth = 5f;
private bool isZoomed = false;
private bool isZoomFinished = true; // the animation zoom is over ?

public Camera cam;
public GameObject player;

public float LockedX = 0f;
public float LockedY = 0f;
public float LockedZ = 0f;
private bool hasBeenZoomed =  false;

Vector3 targetPos;

private Transform playerTransform;

void Start()
{
    targetPos = transform.position;
    playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
}

void Update()
{
    if (Input.GetKeyDown("z") && isZoomFinished) { 
        isZoomed = !isZoomed; 
        isZoomFinished = false;
    }

    if (isZoomed && !isZoomFinished)
    {
        ZoomInToPlayer();

    }
    else if (!isZoomed && !isZoomFinished)
    {
       ZoomOutFromPlayer()
    }
}

float delta = 0;

void ZoomInToPlayer()
{
    delta += smooth * Time.deltaTime;


    //Cam size
    cam.orthographicSize = Mathf.Lerp(cam.orthographicSize, zoom, delta);

    //Cam pos
    float targetX = transform.position.x;
    float targetY = transform.position.y;
    targetX = Mathf.Lerp(transform.position.x, playerTransform.position.x, delta);
    targetY = Mathf.Lerp(transform.position.y, playerTransform.position.y, delta);
    cam.transform.position = new Vector3(targetX, targetY, transform.position.z);



    // is animation over ?
    if(delta >= 1) {
        isZoomFinished = true;
        delta = 0;
    }
}

void ZoomOutFromPlayer()
{

    delta += smooth * Time.deltaTime;

    //Cam size
    cam.orthographicSize = Mathf.Lerp(cam.orthographicSize, normal, delta);

    //Cam pos
    float targetX;
    float targetY;
    targetX = Mathf.Lerp(transform.position.x, LockedX, delta);
    targetY = Mathf.Lerp(transform.position.y, LockedY, delta);
    cam.transform.position = new Vector3(targetX, targetY, transform.position.z);

    // is animation over ?
    if(delta >= 1) {
        isZoomFinished = true;
        delta = 0;
    }

}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM