1

want to know that how mathf.movetowards works, i tried to play around it and have some issues. i want to make the camera moves from player to target places along with zooming upon triggered and vise versa, while smooth follow(camera changes target) works, smooth zooming doesn't work. i place the movetowards code to ontriggerenter/exit, but it doesn't work as intended as it only zoom for frames. However, if i place it at update side, the zooming doesn't work at al.

code provided for more infomation.

public class Disable : MonoBehaviour {
GameObject player;
GameObject Camera;
public Transform placeHolder;
public float smoothTime = 2f;
public float adjustSize;
public float originalSize = 6.5f;
public float targetOrtho;


public Vector3 velocity;


void Awake()
{
    player = GameObject.FindGameObjectWithTag("Player");
    Camera = GameObject.FindGameObjectWithTag("MainCamera");



}
private void Start()
{
    targetOrtho = originalSize;
}

void Update()
{
    Camera.GetComponent<Camera>().orthographicSize = Mathf.MoveTowards(Camera.GetComponent<Camera>().orthographicSize, targetOrtho, smoothTime * Time.deltaTime); //doesn't work

}

void OnTriggerEnter2D(Collider2D other)
{
    if (other.gameObject == player)
    {

        Camera.GetComponent<Camera2DFollow>().target = placeHolder;
       targetOrtho = adjustSize;
       //Camera.GetComponent<Camera>().orthographicSize = adjustSize; //works but only changes the size without smooth
       //Camera.GetComponent<Camera>().orthographicSize = Mathf.MoveTowards(Camera.GetComponent<Camera>().orthographicSize, adjustSize, smoothTime * Time.deltaTime); //works but only did for a few frames( not completely)


    }
}


void OnTriggerExit2D(Collider2D other)
{

    Camera.GetComponent<Camera2DFollow>().target = null;
    targetOrtho = originalSize;
    //Camera.GetComponent<Camera>().orthographicSize = originalSize; //works but only changes the size without smooth
    //Camera.GetComponent<Camera>().orthographicSize = Mathf.MoveTowards(Camera.GetComponent<Camera>().orthographicSize, originalSize, smoothTime * Time.deltaTime); //works but only did for a few frames (not completely)
}
Chan Ming
  • 41
  • 4

1 Answers1

1

want to know that how mathf.movetowards works

Anytime you want to know how part of Unity's C# API works, you can look it up in the published source code:

// Moves a value /current/ towards /target/.
static public float MoveTowards(float current, float target, float maxDelta)
{
    if (Mathf.Abs(target - current) <= maxDelta)
        return target;
    return current + Mathf.Sign(target - current) * maxDelta;
}

As you can see, MoveTowards is just a math function: it takes in some numbers, and returns a computed number.

It does not have any knowledge about what you want to do with that number. It doesn't receive a reference to any object that you want it to update, which is why you have to assign the return value yourself:

Camera.GetComponent<Camera>().orthographicSize = Mathf.MoveTowards(...

This assignment happens exactly once: the frame when this line of code is run. It does not kick off a background process that will keep updating the object frame over frame. If that's the behaviour you want, then it's your job to write that code:

Coroutine zoomTween;

IEnumerator ZoomCoroutine(Camera camera, float targetSize, float duration) {
    float startSize = camera.orthographicSize;

    for(float t = 0f; t < duration; t += Time.deltaTime) {
        float blend = t/duration;
        // A SmoothStep rather than a Lerp might look good here too.
        camera.orthographicSize = Mathf.Lerp(startSize, targetSize, blend); 

        // Wait one frame, then resume.
        yield return null;
    }

    // Finish up our transition, and mark our work done.
    camera.orthographicSize = targetSize;
    zoomTween = null;
}

void ZoomTo(Camera camera, float targetSize, float duration) {
    // Check if we're already in a zoom transition, and stop it to ensure we don't double-up.
    if(zoomTween != null)
        StopCoroutine(zoomTween);

    // Kick off a new zoom transition that can keep going on future frames.
    zoomTween = StartCoroutine(ZoomCoroutine(camera, targetSize, duration));
}

Then when you want to change zoom, you just call ZoomTo() with your desired parameters.

DMGregory
  • 134,153
  • 22
  • 242
  • 357
  • some changes were made for my own preference. `float startSize = targetOrtho;
        for (float t = 0f; t < duration; t += Time.deltaTime)
        {
            float blend = t / duration;
            // A SmoothStep rather than a Lerp might look good here too.
            camera.orthographicSize = Mathf.Lerp(targetOrtho, targetSize, blend);`
    

    it's quite wierd that i have to set the targetOrtho to the size before the camera enters/exit the trigger to make the couroutine works. also it's quite interesting as you dont need to use update for this.

    – Chan Ming Mar 29 '19 at 12:06
  • It sounds like you have another script modifying the camera's orthographic size before the Coroutine gets at it to save it in startSize, necessitating that targetOrtho workaround. You should be able to eliminate that. As for why you don't have to use an Update method: coroutines get "pumped" by the engine each frame as part of its various update loops. See the script lifecycle for a map of where each one happens in the flow. – DMGregory Mar 29 '19 at 12:14