How to smooth camera when falling in unity? - unity3d

I am working on an endless jumper that turns into a faller type game. The camera on the way up is SUPER smooth, but on the way down it is extremely jerky.
I am not sure how to make it just follow the player with script and not jerk.
Camera going up:
float newHeightOfCamera = Mathf.Lerp(currentCameraHeight, playerHeightY, Time.deltaTime * 10);
transform.position = new Vector3(transform.position.x, newHeightOfCamera, transform.position.z);
Camera going down:
float newHeightOfCamera = Mathf.Lerp(currentCameraHeight, playerHeightY - fallCamera, Time.deltaTime);
transform.position = new Vector3(transform.position.x, newHeightOfCamera - cameraFallLocation, transform.position.z);
On the way down the player goes to the top of the screen and is set to a fixed speed.
pc.GetComponent<Rigidbody2D>().velocity = new Vector2(0, fallSpeed); //changes falling speed

I am still waiting for response to my comments, but for 90% your problem can be solved very easy with just moving all your code samples from Update to LateUpdate (or even from FixedUpdate to LateUpdate). In most cases that is enough. But still, we would need to know more details to be sure it is the solution.

Sorry I took a break from this game as it was frustrating. Here is what I came up with
This was for the falling. I didn't end up need the camera to catch up I just wanted it to be still.
float newHeightOfCamera = playerHeightY - fallCamera;
transform.position = new Vector3(transform.position.x, newHeightOfCamera - cameraFallLocation, transform.position.z);
fallCamera was the location of the camera. I wanted the character to be at the bottom of the screen when going up and at the top of the screen when going down.

Related

Unity 2D, rotate Vector2 to NEW Vector2 in animation

My game is 2D from a top down-ish perspective, my character movement vector2 being fed into the animator blend to determine which direction my sprite faces: (example sprite)
Vector2 movement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
anim.SetFloat("hor", movement.x);
anim.SetFloat("ver", movement.y);
However, I would like my sprite to rotate to it's new target vector2 rather than instantly switch to it. So if I was facing right, and I pushed left, the movement vector2 would travel over time to a new movementTarget vector2, the sprite changing from facing right, to up, to left.
I cannot figure or find a way to do this and have been on it many hours. I've tried things like Vector3.RotateTowards and angles, but each approach I can't get what I'm looking for as this aspect of math just confuses me.
Could someone point me in the right direction?
Vector2 targetMovement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
if (targetMovement != movement) coroutine?????
I don't want to rotate the sprite image, or the object transform, just the movement Vector2 variable over time. So if I am facing right (1,0) and press left, I want the Vector to travel through (0,1 - up) then finally to (-1,0 - left) but gradually.
Managed to do it like this. Unsure if best way?
float currAngle, targAngle;
Vector2 movement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
if (movement != Vector2.zero)
targAngle = Mathf.Atan2(movement.y, movement.x) * Mathf.Rad2Deg;
if (Mathf.Abs(currAngle - targAngle) > 1f) {
currAngle = Mathf.LerpAngle(currAngle, targAngle, 10f * Time.deltaTime);
Vector2 newVec = new Vector2(Mathf.Cos(currAngle * Mathf.Deg2Rad),
Mathf.Sin(currAngle * Mathf.Deg2Rad));
anim.SetFloat("hor", newVec.x);
anim.SetFloat("ver", newVec.y);
}

Jittery motion when interpolating movement in unity3d

Basically, I have two gun objects on my fps player. The real gun and the gun that the player sees. I have a script on the gun that the player sees to follow the position and rotation of the real gun which is a child of the camera via interpolation.
Rotation is fine, but I get jittery movement with the position of the gun. Here is my smooth move script on the gun that the player sees:
public Transform target; //The gun that the player doesn't see
public float moveSpeed = 0.125f;
public float rotateSpeed = 0.125f;
void LateUpdate()
{
//this is causing the jittery motion
transform.position = Vector3.Lerp(transform.position, target.position, moveSpeed);
//this is very smooth
transform.rotation = Quaternion.Lerp(transform.rotation, target.rotation, rotateSpeed);
}
Does anybody know why?
Edit:
Otherwise, I would go with a more sensible Unit for your moveSpeed, something that makes sense in your world e.g. 1 meter, then I would use Time.deltaTime to smooth the movement. If it's too slow or too fast you can tweak the speed unit.
[SerializeField] private float moveSpeed = 1f;
void LateUpdate()
{
var t = moveSpeed * Time.deltaTime; //< just to highlight
transform.position = Vector3.Lerp(transform.position, target.position, t);
}
The practical reason for using Time.deltaTime is to help smooth depending on your frame rate, if you get a lower frame the Lerp will then adjust. This common method is also explained in this answer by Eric5h5 from Unity forum.
Hmm, I wonder if you really need a Lerp to update the Gun position, if you want to sync both I would just update your transform.position = target.position since it's done every frame, they would be in sync.
Adding a lerp would just delay that sync.
The fact that you see a difference between the Quaternion and the Lerp is just that you cannot compare those two speed, I believe the speed you set on a rotation is much faster than the one for the lerp.

How to make a model appear in front of AR Camera after the session starts using ARFoundation?

I was looking to update the ARcamera position.I am doing ImageTracking project.It detects an image and a corresponding prefab is shown in front of the camera.It starts playing an animation.After the animation I want the prefab to come really close towards the camera.When I give the code prefab.position=ARcamera.position; after animation code,I think the prefab goes to the initial position where the ARCamera was when the app had started that is (0,0,0).
How to make the prefab come really close towards the front camera.
speed = 10f;
float step = speed * Time.deltaTime;
Showprefabs.transform.GetChild(0).position = Vector3.MoveTowards(Showprefabs.transform.GetChild(0).position,
new Vector3(Arcam.transform.position.x, Arcam.transform.position.y + 0.2f,
Arcam.transform.position.z + 6.3f), step);
//The values 0.2f and 6.3f I added using the Editor to make the prefab come near the camera(But in world position it is different.)
First of all I hope by "prefab" you mean already Instantiated GameObject. It makes no sense to move a prefab ;)
You tried to calculate the target position but did it with World-Space coordinates.
You probably want to do something like
var targetObject = Showprefabs.transform.GetChild(0);
var currentPosition = targetObject.position;
var targetPosition = Arcam.transform.position
// Place it 60cm in front of the camera
+ Arcam.transform.forward * 0.6f
// additionally move it "up" 20cm perpendicular to the view direction
+ Arcam.transform.up * 0.2f;
targetObject.position = Vector3.MoveTowards(currentPosition, targetPosition, step * Time.deltaTime);
If you want that movement a bit smoother so it moves slower if already close and faster if further away you might be interested in rather using Vector3.Lerp here
public float smoothFactor = 0.5f;
targetObject.position = Vector3.Lerp(currentPosition, targetPosition, smoothFactor);
Where a smoothFactor of 0.5 reads: Every frame set the object to a position in the center of the currentPosition and targetPosition. A value closer to 0 results in slower movement, closer to 1 in faster reaching the targetPosition.
Note that actually this approach will never really fully arrive at the targetPosition but only come very very close but usually this doesn't matter in AR where the Camera constantly moves a bit anyway.

Rotating a projectile sprite to face an angled camera and the target it is flying at. 2D top down

Results that im getting, and result that I want. Descriptive image.
I know that this question has been asked before not quite in this way, believe me I have been looking all over this forum and unity answers for a solution.
I am making a 2d top down game where monsters can shoot projectile at my character. I have solved that by making it do that they instantiate a projectile prefab from a specific point in their animation at the location of an empty gameobject and it looks fine. I have made the projectile find the player and make it dodgable by aiming at where he was originally and not where he constantly is. so the movement of the projectile at the moment is perfect and im oh so proud of myself!, yes semi new to this. here is the code I used:
public void OnCastComplete()
{
var projectile = Instantiate(fireball, projectileInitialLocation.transform.position, transform.rotation);
projectile.transform.LookAt(currentTarget.transform.position);
projectile.velocity = projectile.transform.forward * projectileSpeed;
Vector2 dir = currentTarget.transform.position - projectile.transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
projectile.transform.rotation = Quaternion.AngleAxis(angle, Vector2.up);
}
This would also work perfectly If my main camera where not at an angle. The look and feel that I need is that the camera is at an angle to make 3D elements in my game come to life while still have 2d sprites running around. This means that all sprites, including the projectile need to have a script on them to face the camera.
here is that script:
public Transform target;
void Start () {
target = GameObject.Find("MainCamera").GetComponent<Transform>();
}
void Update () {
if (target != null)
this.transform.rotation = Camera.main.transform.rotation;
}
Now I am confident that these two scripts are the culprits here as I can see one does a bang up job of making sure things face the camera and the other makes sure to rotate the sprite correctly. but they cannot work together. Removing the latter script from the projectile means it sometimes is not visible or rotated at an angle whereby the viewer can hardly notice it. attaching it means its faces the camera, but gives me the result in the picture I posted above.
I cannot get them to play nice with each other and the problem is so specific I am afraid I need to post a question here =(
hope someone can help!
thank you!
Of course I manage to fix this issue 10 minutes after posting the question.
the way I fixed it was to change the remove the script to face the camera on projectiles. The compensate for it when instantiating a projectile as so:
public void OnCastComplete()
{
var projectile = Instantiate(fireball, projectileInitialLocation.transform.position, transform.rotation);
projectile.transform.LookAt(currentTarget.transform.position);
projectile.velocity = projectile.transform.forward * projectileSpeed;
Vector2 dir = currentTarget.transform.position - projectile.transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
//projectile.transform.rotation = Quaternion.AngleAxis(angle, Vector2.up);
projectile.transform.rotation = Quaternion.Euler(-25, 0, angle);
}
the line I have commented out was the previous one, the line under it fixes the issue. Camera is compensated for by adding the -25 on the x and rotating of the sprite is compensated for by adding the "angle" to the z euler angle.
Hope this helps someone.

Unity - Stay Within Screen Bounds

I have been making a top down 2d game and have come across a small issue. I need the player to stay within the screen bounds at all times. I have seen people with this problem before and have tried their solutions however none of them have worked with my game. This is because my player character uses physics to move around. This is what I have inside my FixedUpdate function:
minScreenBounds = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 0));
maxScreenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 0));
transform.position = new Vector3(Mathf.Clamp(transform.position.x, minScreenBounds.x + 1, maxScreenBounds.x - 1), Mathf.Clamp(transform.position.y, minScreenBounds.y + 1, maxScreenBounds.y - 1), transform.position.z);
If anyone knows how to fix this I would much appreciate it if you could tell me how.
Many Thanks,
Tommy
Make 4 kinematic Rigidbody2D to the screen edges, like below (green colliders), and manage their scale / position for your need.