Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mega-man 2 Camera help (Unity)

So I have tried several ways to fix a Mega-man 2 camera without actually figuring out a good way of doing it. So I would love if someone could give me some tips for I could solve this issue.

The problem: As I have written I want a Mega-man 2 camera (2D). The thing from it that I have not been able to solve is how to move it in Y like they do in Mega-man 2. What happens is that the camera does not move at all in Y, unless you go outside "camera bounds" and then it "freezes" the player and moves the camera down, see this video: https://youtu.be/NP697v8WtkU?t=5m2s (Hopefully it starts where the camera does this, otherwise go to 5:02).

But I can't get this to work in any good ways for me. What I have tried so far is, I have triggers at the top and bottom of the camera and when the player hit's one of them I start a coroutine where the camera should Lerp, however, it moves too much, so if I need to move it twice in the Y it would be all messed up. (My code is at the bottom but as I said, I need some help how I can fix it)

So please, if anyone have any idea how I can solve this, please let me know. I've been trying for several days without getting it to work perfectly.

    public void ChangeY()
 {
     StartCoroutine(MoveCameraDown());
 }

 IEnumerator MoveCameraDown()
 {
     Vector3 CurrentCameraPos = Camera.main.transform.position;
     Vector3 NewCameraPos = new Vector3(Camera.main.transform.position.x, Camera.main.transform.position.y - 5.6f, Camera.main.transform.position.z);

     for (float t = 0.0f; t < 1; t += Time.deltaTime / 1.5f /* TIME IT SHOULD TAKE TO MOVE THE CAMERA DOWN */)
     {
         Camera.main.transform.position = Vector3.Lerp(CurrentCameraPos, NewCameraPos, t);
         yield return null;
     }
 }

And as I have already written, I call the ChangeY() when I hit one of the triggers. This is just my testing case if you are wondering why some numbers are hardcoded and all that. But as I said, I have not been able to fix this so if anyone can help me I would really appreciate it.

like image 442
Tobias Johansson Avatar asked Nov 27 '25 23:11

Tobias Johansson


1 Answers

It is actually easy to do. You asked for some tips and I will give you one. Assuming you have already built your 2D world just like in the video you posted. There are many ways to solve this problem but I show you the way I consider to be the easiest. I have 5 steps for you to follow.

You need a value you can use each time to move down. Based on your code, you used -5.6f each time. The go down value should never be the same each time when the player touches the bottom trigger. It should be generated during run time. This will be addressed in step 3.

1) If the player triggers the camera bottom trigger, first thing you should do is to stop the player, by disabling gravity then setting the rigidbody velocity and torque to zero. For example inside your OnTriggerEnter function attched to the camera:

 void OnTriggerEnter(Collider other) {
    Rigidbody rgbd;
    rgbd= other.gameObject.GetComponent<Rigidbody> ();
    rgbd.useGravity = false;
    rgbd.velocity = Vector3.zero;
    rgbd.angularVelocity = Vector3.zero;
    }

2) Immediately throw Ray cast downward(-y) using Physics.Raycast. The origin position of the raycast should be the position of the player. For example,

    GameObject gameOBjectHitFromRaycast;//Store Game Object detected from the raycast
    RaycastHit hit;
    if (Physics.Raycast(player.transform.position, Vector3.down, out hit)){
           gameOBjectHitFromRaycast = hit.collider.gameObject;     
    }

The information of the object below the player will be stored in RaycastHit. Use RaycastHit to get the information about the object that the player is about to land on.

3) After getting the information of that object the player is about to land on, get the y-axis position of that object then get the y-axis position of the player. Add them together then divide the result by 2. That is your new y position. The new position you need to move the camera to. For example,

Vector3 cameraNewPos = new Vector3(player.transform.position.x,(gameOBjectHitFromRaycast.transform.position.y+
camera.transform.position.y)/2,player.transform.position.z);

Basically, what we did here is to find the middle of the player's current position and the the landing position so that we can position the camera right in the middle of it. That should be do it but you can also subtract another number from the y-xis if that is not enough.

4) Use a coroutine function to move the camera smoothly to the new y axis position. Inside the corutine function, there should be public bool variable that will be used to determine if this function is done running(if camera is done moving). Replace this function with the current camera move function you have

bool cameraMoving = false; //This variable can be used to determine when the camera is done moving

private IEnumerator MoveCameraDown (Vector3 toLocationPos, float timeToFinish)
{
    float runTime = 0; //Dont change
    float timer = 0;  //Dont change
    float tempDeltaTime;

    cameraMoving = true;

    //Will keep looping until camera is done moving
    while (timer<timeToFinish) {
        //Translate camera
        Camera.main.transform.position = Vector3.Lerp (Camera.main.transform.position, toLocationPos, runTime);

        tempDeltaTime = Time.deltaTime; //Get delta time once to be used multiple times to improve performance
        runTime += tempDeltaTime / timeToFinish;
        timer += tempDeltaTime; //Increement To exit loop
        yield return null;
    }

    //Camera is done moving
    cameraMoving = false;
}

Finally, to move the camera, you can just start the coroutine and pass in the new position calcluation in step 3 and also how much time you want it to take to do the moving. For example, we can pass in the cameraNewPos from step 3 and 2 for seconds it will take to move the camera.

StartCoroutine (MoveCameraDown (cameraNewPos , 2f));

5) When the camera is done moving, enable rigidbody gravity of the player with

Rigidbody rgbd;
rgbd= player.GetComponent<Rigidbody> ();
rgbd.useGravity = true;
like image 157
Programmer Avatar answered Nov 30 '25 11:11

Programmer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!