Mega-man 2 Camera help (Unity) - c#

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.

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;

Related

How Can I Gradually Add More Force To An Object To Increase It's Speed Regardless of It's Direction?

I'm new in Unity. I am trying to make a 2D game similar to Pong. However, I want to increase more speed to Ball over time to make it harder. I set the gravity scale of the Ball to zero so that it doesn't fall down.
I added a force and bouncy Physics element to the ball. So it bounces back from walls and it goes to different directions.
Here is a screenshot of Game I'm working on:
MY QUESTION IS:
How can I add more force to the ball regardless of which direction it
bounces back?
<Note: I tried putting it inside FixedUpdate () method but the ball goes crazy because of constantly executing same function every frame. I was thinking of adding more force to the ball over time by using InvokeRepeating ( ) method later on to set time interval. If there is better idea of using other techniques, giving me a little advice will help me a lot>
Thank you !
I would recommend using a Coroutine or an InvokeRepeating. I would also recommend changing your code a bit.
rbBall.AddForce(rbBall.transform.right * ballForce)
The above snippet will add the ballForce in the direction the rbBall is moving.
Now for the two example snippets.
Coroutine
private float timeBeforeAddForce = 5f;
private void Start()
{
StartCoroutine(GradualAddForceToBall());
}
private IEnumerator GradualAddForceToBall()
{
// wait for 5 seconds
yield return new WaitForSeconds(timeBeforeAddForce);
// add the speed
rbBall.AddForce(rbBall.transform.right * ballForce)
// call the coroutine again
StartCoroutine(GradualAddForceToBall());
}
InvokeRepeating
private void Start()
{
InvokeRepeating("GradualAddForceToBall", 0.0f, timeBeforeAddForce);
}
private void GradualAddForceToBall()
{
rbBall.AddForce(rbBall.transform.right * ballForce)
}
If you want to change the current time of how long the speed is applied, I would go with the Coroutine as you can gradually decrease the timeBeforeAddingForce every time it enters the Coroutine.
I found the answer. You can force an object to be a specific speed while keeping its same movement direction - normalize the velocity (which sets the value to have a mangitude of 1) and then multiply it by your desired speed:
Here is the code:
public float currentSpeed = 5f;
void FixedUpdate()
{
//This will let you adjust the speed of ball using normalization
rbBall.velocity = rbBall.velocity.normalized * currentSpeed;
}
Adjust the currentSpeed variable to change it's speed.
""

Unity2D: implementing a running effect to my character

I'm trying to achieve the same effect done Knuckles does in the new game Sonic mania, the effect can be seen here (2:18 - 2:25). So far I duplicated my main player and lowered the duplicated players alpha so that it looks a bit transparent, I also added the script below on the duplicated player to give the duplicated player some distance to the original player; however I wasn't quite sure how I can make the duplicated players slowly return the original player when the player isn't moving! I attempt using animation but it didn't look as good as what was shown in the video, I also tired to shorten the distance over Time.deltaTime however it still didn't look effective! Is there a better way of attempting the same effect shown in the video?? Thank you :)
public GameObject Player;
public float distance = 0.75f;
// Use this for initialization
void Start () {
distance = 0.42f;
}
// Update is called once per frame
void Update () {
transform.position = (transform.position - Player.transform.position).normalized * distance + Player.transform.position;
}
You can try using TrailRenderer.
Here's the documentation: https://docs.unity3d.com/Manual/class-TrailRenderer.html
You can activate it during the run effect and deactivate it otherwise.

Choppy camera movement with smooth follow

I am seeing a camera stutter when using smooth follow to lerp after my player with my camera in my multiplayer browser game. The player position is received from the server, the player lerps to that position, and my goal is for the camera to smoothly follow the player with its own, extra smoothing.
You can find my game at http://orn.io to see the current state, without smooth follow camera lerping, which is better but causes choppy movement and creates a headache. The current code for camera follow is:
void LateUpdate ()
{
if (Target == null) {
return;
}
currentScale = Mathf.Lerp(currentScale, -GameManager.TotalMass, Mathf.Clamp01 (Time.deltaTime * heightDamping));
Vector3 h = currentScale * 2f * Target.up;
Vector3 f = currentScale * 3f * Target.forward;
// tried lerping to this value but it causes choppy stutters
Vector3 wantedPosition = new Vector3(Target.position.x, Target.position.y, currentScale * 2) + h + f;
myTransform.position = wantedPosition;
myTransform.LookAt (Target, -Vector3.forward); // world up
}
and I have tried for days to tinker with the values, use fixed timestamps, put the camera movement in FixedUpdate/Update, use MoveTowards, and other changes, but am still experiencing issues.
Part of my problem that that the player position changes mid lerp, which causes a stutter since the target position changes in the middle of the lerp. This causes the camera to jump/sutter due to the target position of the lerp being changed in the middle of the lerp, and shakes due to the LookAt.
I would appreciate it if anyone could suggest a way to improve the camera following code as it stands now.
Is there any particular reason you need to use the Mathf.Lerp function?
Unity has a function, Vector3.SmoothDamp that is specifically designed for movement lerping:
void FixedUpdate() {
// Code for your desired position
transform.position = Vector3.SmoothDamp(transform.position, wantedPosition, ref moveVelocity, dampTime);
}
The above will smoothly follow the player by giving the SmoothDamp method control of the velocity variable. This is assuming that you supply it with a ref to store the current velocity and the damp time.
You can also adjust the damp time to change how smooth your transition is. This function will also automatically account for player movement mid-lerp.
To clarify, quoting from the documentation, dampTime in the above is:
Approximately the time it will take to reach the target. A smaller value will reach the target faster.
Also consider using Quaternion.slerp to smoothly rotate between the two rotations.

Unity 3D. How do I move the object up when the another object gets on it

I have the object "ball" that can roll on the surface. There is also the object "platform". So, I need to platform up a certain distance, only when the ball will stop on the platform.
Script on C#.
Honsetly - I don't know about Unity API anything :), but I know that it must have available property "position". So one of the ways to solve you problem - check position of ball in every Update(in comparison with previous position), and when it's position become stable(the same) for a while(some time) - move the platform.
something like:
private Vector3 lastPosition;
private stableTime = 0;
public float distThreshold = 0.1;
public float timeThreshold = 0.1;
void FixedUpdate() {
if (lastPoistion == null || Vector3.Distance(ball.position, lastPoistion) > distThreshold) {
lastPosition = ball.position;
stableTime = 0;
}
else
stableTime += Time.deltaTime;
if (stableTime > timeThreshold)
platform.MovePoistion()
}
You need to identify 2 things here.
Is the ball stopped?
is the ball on the platform
To identify if the ball is stopped simply keep track of it's current speed (using a speed property assigned to the ball object). I'm assuming you probably already have this as the player will be controlling the ball? If so, just check that speed == 0.
To check whether the ball is on the platform you will need to use colliders. Take a look under 2d or 3d physics (you haven't specified which you are using) and apply some appropriate colliders to both the platform and the ball. You can now programmatically check for collision between the 2 objects. There are plenty of tutorials on object collision so I won't go into it here but this may be a good place to start.

Unity-Character Continues Moving when Locked onto enemy

Ok so here's my issue, I have a script that allows me to lock on to and orbit an enemy target. The problem is if my character is moving when pressing the lock on button the character will continue moving in whatever direction it was going before the button was pressed regardless of any more button presses save for the opposite direction.
This doesn't happen when I'm stationary, if my character stands still and I press the lock on button everything works fine. It's only when I'm moving.
I'm not sure if this is enough information, or what else someone might need to better understand but here is my script:
if (GetComponent<DetectedEnemies>().locked)//checks bool to see if lockOn button was pressed
{
mainCam.SetActive(false);//turns off main cam
lockCam.SetActive(true);//turns on lockOn cam
movesetting.tarObject = GetComponent<DetectedEnemies>().Closest;//target object will be the closest enemy to player
this.transform.LookAt(movesetting.tarObject.transform.position);//player will look at the target object at all times
if (currXRot.x > maxXRot.x)//if the current x rot of this object exceeds the maxXRot it can go...
currXRot.x = maxXRot.x;//it gets reset
transform.Translate(Vector3.right * movesetting.speed * Time.deltaTime * turnInput);//orbits around the target object
transform.Translate(Vector3.forward * movesetting.speed * Time.deltaTime * forwardInput);//in control of moving towards and away from target
}
Any and all help is greatly appreaciated, thank you in advance. If you need more info or if something isn't clear please let me know.
Try creating a second speed variable which you use for the orbiting speed. Then if the player is locked set the first speed variable to 0 and when the player isn't locked set the orbiting speed variable to 0. Something like this: (I use 5 as an example)
if(GetComponent.<DetectedEnemies>().locked) {
speed = 5;
orbitSpeed = 5;
} else {
speed = 5;
orbitSpeed = 0;
}

Categories

Resources