I recently posted a problem with a jittering Camera Follow in my 2D Game made in Unity, which was solved here.
However after some time I noticed, that I am still getting jumps. I now know, that the problem lies in the lerp method of my camera follow. Time.deltaTime varies as described in my prior question and thus makes the player move different distances each frame. But because the camera reacts with a delay, you can see the jump on screen (on device even more than in Unity Editor).
A solution would be to detect those Time.DeltaTime jumps and in these cases make the camera imitate that jump somehow, am I correct? What would be a Workaround here?
These are my scripts:
public class Player: MonoBehaviour
{
float speed = 5f;
void Update()
{
transform.Translate(0,speed*Time.deltaTime,0);
}
}
public class CamFollow : MonoBehaviour
{
public Transform Player;
private Vector3 FollowVector;
float transition = 0.05f;
void LateUpdate()
{
FollowVector = Player.position - new Vector3(0, -4.0f, 10);
transform.position = Vector3.Lerp(transform.position, FollowVector, transition);
}
}
Try using Time.fixedDeltaTime. This is like deltatime but it's fixed and so it doesn't very as you said. It does reduce the jittering, but I would recommend using Cinemachine, as it's very performant and you would have a lot of control over it.
Related
hi everyone so basically I was wondering how I could change this movement script to be with rigidbody. It works the way I want it to with wasd to change look direction and then space to move forward from that direction kinda but I want to convert it all to be done with rigidbody so I can do collisions. Thanks!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fly : MonoBehaviour
{
public float moveSpeed;
void Start()
{
}
void Update()
{
if (Input.GetKey(KeyCode.Space))
{
transform.Translate(new Vector3(0,0,moveSpeed) * Time.deltaTime, Space.Self);
}
float rotatex = Input.GetAxis("Vertical");
float rotatey = Input.GetAxis("Horizontal");
transform.Rotate(0, rotatey, 0, Space.World);
transform.Rotate(-rotatex * 0.5f, 0, 0);
}
}
There are quite a few errors with your code as written. No problem, but you'll probably need to fix all of these before your code starts working as intended. This answer is meant to give you a springboard to google up on some of these errors and wrap your head around the Update() method and how it works in Unity.
First, you'll need to ensure the RigidBody2d component is on your Game Object. That's easy enough to do, right click in the inspector and add the component. Google: "How do I add components to game objects in Unity"
Next, you're going to want to understand how often Update() is called and how it works. Spoiler alert - it's called as fast as your computer can. What that means is that changing the rotation with transform.Rotate every call is likely going to lead to an object that's spinning extremely rapidly. Perhaps rapidly enough that it's spinning more than 360 degrees each frame and just appears to be "twitching" randomly. You'll need to scale your rotation, so Google up "delta time in Unity Update".
Lastly, you're going to want to collect your inputs, which you're doing correctly with Input.GetKey(), although there are lots of ways to skin this cat. Perhaps the most straightforward would be to collect your inputs in one method called GetAllInputs(), set some booleans in that method to things like IsMovingRight or IsJumping and then operate on them in your Update method. This is only one approach, there are literally dozens, and many ways that they can be improved. Google up "Unity Input System", "Unity 2D Physics", and "Finite State Machines" (since you're eventually going to want to have "states" like crouching, jumping, running, hanging on to a wall, etc). It seems like you're writing a platformer, so I'd also watch some of the youtube tutorials on that, and google phrases like "Creating a Unity Platformer Tutorial".
Assuming it works the way you want here is the code using rigidbody (Make Sure Rigid Body is attached to object) This code must be written in Fixed Update as RigidBody based calculation must be done in Fixed Update:
public class Fly : MonoBehaviour
{
public float moveSpeed;
[SerializeField] private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if (Input.GetKey(KeyCode.Space))
{
//transform.Translate(new Vector3(0,0,moveSpeed) *
//Time.deltaTime, Space.Self);
if (rb)
{
rb.MovePosition(new Vector3(0,0,moveSpeed) *
Time.deltaTime);
}
}
float rotatex = Input.GetAxis("Vertical");
float rotatey = Input.GetAxis("Horizontal");
// transform.Rotate(0, rotatey, 0, Space.World);
// transform.Rotate(-rotatex * 0.5f, 0, 0);
if (rb)
{
rb.MoveRotation(Quaternion.Euler(rotatex , rotatey , 0));
}
}
}
I made an 2D endless runner game using Unity, where the Player Object moves upwards, but for the Viewer he remains on the same spot because the Camera is following him. The Following works pretty well, but the problem is that it is making small jumps every few seconds. The jumps are small and thus are not affecting the gameplay in general but they are big enough to make it seem like the game is not running smoothly.
I can't even tell whether it is the Camera that is making the jumps or the Player Object. But I think it is the Camera, because the spawning obstacles are also making jumps. What may be the issue? Am I using the right method for the Camera?
public class Player
{
float speed = 5f;
void Update()
{
transform.Translate(0, speed*Time.deltaTime, 0);
}
}
And this is the Script which is attached to the Camera:
public class CameraFollow
{
private Vector3 FollowVector;
public Transform Player;
void LadeUpdate()
{
FollowVector = Player.position - new Vector3(0, -4f, 10);
transform.position = Vector3.Lerp(transform.position, FollowVector, Time.deltaTime * 4f);
}
}
Does the jump happen every 4 seconds? I think the problem might be in your Vector3.Lerp function. It's basically a loose camera-follow, that takes 4 seconds (Time.deltaTime * 4f) to smoothly go from Point A to point B. Every 4 seconds it resets its path, hence the hop. At least that's my theory.
If you don't mind the camera rigidly following the player, I would just remove the Lerp and just set the transform.position to be the FollowVector value like so:
void LadeUpdate()
{
transform.position = Player.position - new Vector3(0, -4f, 10);
}
Try to use Vector3.MoveTowards
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, Player.position - new Vector3(0, -4f, 10f), step);
I'm creating a game with Unity and I'm learning C#. I needed some help with a bullet firing mechanism for my game so I found the below script on Unity Answers. It works great, but fires the bullet backwards (which would land anyone in the game in a bad situation). Could anyone help? Thank you!
using UnityEngine;
using System.Collections;
public class ShootDemo : MonoBehaviour
{
public Rigidbody projectile;
public float speed = 20;
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Rigidbody instantiatedProjectile = Instantiate(projectile, transform.position,
transform.rotation) as Rigidbody;
instantiatedProjectile.velocity = transform.TransformDirection(new Vector3(0, 0, speed));
}
}
}
What you have would work if you had the forward (blue axis) of the gameobject of ShootDemo pointing in the direction you'd want to shoot.
The fact that does that shoots it in the opposite direction means the forward is pointing is actually pointing in the opposite direction.
Taking that into account by negating speed will reverse the velocity to create the desired effect:
instantiatedProjectile.velocity = transform.forward * -speed;
Or in the format you've already used
instantiatedProjectile.velocity = transform.TransformDirection(new Vector3(0, 0, -speed));
When reading this, keep in mind I'm new to both programming and Unity, so I might be missing some terms or tools Unity offer. Please elaborate your answers in an ELI5 manner. Thanks in advance!
I am currently working on some game-physics for a small personal project. Currently I've created a platform, a character and what should be, a following companion.
However, since I'm still not on a level, where I can create perfect code on own hand, I found an "enemy" script and tried to modify it a bit.
It Works to an extend, but it needs some tweaks which I hope I can help aquire with you guys.
This is how it looks now (the orange square is the companion)
It follows the player, and I can tweak the speed to fit as a companion, and not a player. However, as the Picture presents, the companion runs for the center of the player. What I want to create is a companion which follows the player, but still keeps a small gap from the player.
My first thoughts was to create some kind of permanent offset, but I fail to figure out how to do this without messing up the follow function.
I hope you can help me, it will be much appreciated!
Here's the code for reference.
Code attached to Player:
using UnityEngine;
using System.Collections;
public class PlayerCompanion : MonoBehaviour
{
//In the editor, add your wayPoint gameobject to the script.
public GameObject wayPoint;
//This is how often your waypoint's position will update to the player's position
private float timer = 0.5f;
void Update ()
{
if (timer > 0) {
timer -= Time.deltaTime;
}
if (timer <= 0) {
//The position of the waypoint will update to the player's position
UpdatePosition ();
timer = 0.5f;
}
}
void UpdatePosition ()
{
//The wayPoint's position will now be the player's current position.
wayPoint.transform.position = transform.position;
}
}
Code attached to companion:
using UnityEngine;
using System.Collections;
public class FollowerOffset : MonoBehaviour {
//You may consider adding a rigid body to the zombie for accurate physics simulation
private GameObject wayPoint;
private Vector3 wayPointPos;
//This will be the zombie's speed. Adjust as necessary.
private float speed = 10.0f;
void Start ()
{
//At the start of the game, the zombies will find the gameobject called wayPoint.
wayPoint = GameObject.Find("wayPoint");
}
void Update ()
{
wayPointPos = new Vector3(wayPoint.transform.position.x, transform.position.y, wayPoint.transform.position.z);
//Here, the zombie's will follow the waypoint.
transform.position = Vector3.MoveTowards(transform.position, wayPointPos, speed * Time.deltaTime);
}
}
bump, I guess ? :)
You can use smooth follow script. I have created a sample class for you. This class has features to follow any given gameobject with some delay and offset. You will have to tweak some values according to your need.
using UnityEngine;
using System.Collections;
public class PlayerCompanion : MonoBehaviour
{
[SerializeField]
private GameObject wayPoint;
[SerializeField]
public Vector3 offset;
public Vector3 targetPos;//Edit: I forgot to declare this on firt time
public float interpVelocity;
public float cameraLerpTime = .1f;
public float followStrength = 15f;
// Use this for initialization
void Start ()
{
//At the start of the game, the zombies will find the gameobject called wayPoint.
wayPoint = GameObject.Find("wayPoint");
offset = new Vector3 (5,0,0);//input amount of offset you need
}
void FixedUpdate () {
if (wayPoint) {
Vector3 posNoZ = transform.position;
Vector3 targetDirection = (wayPoint.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * followStrength;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp (transform.position, targetPos + offset, cameraLerpTime);
}
}
}
Attach this class to your player companion, play with different values.
To preserve object orientation your companion schould not be anyways child of your main character.
Your wayPoint doesn't needs to be a GameObject but a Transform instead and your code will looks like better.
If your game is a 2D platform your and your companion needs to be backwards your player it probabli applys to just one axis (X?) so you can decrement your waiPoint in a more directly way by calculating it on your UpdatePosition function like this:
wayPoint.position = transform.position * (Vector3.left * distance);
where your "distance" could be a public float to easily setup.
so on your companion script Update just do:
transform.position = Vector3.MoveTowards(transform.position, wayPoint.position, speed * Time.deltaTime);
I can't test it right now so you could have problems with Vector3 multiply operations, just comment and I'll try to fix as possible ;)
I am trying to bounce the tile above the circle on top of the platform, there is no problem when the platform is fixed, but when the script who make the platform move is activated, the tile crash the circle.
This is the script for moving the platform:
using UnityEngine;
using System.Collections;
public class PlatformMoveH : MonoBehaviour {
public float min;
public float max;
public float speed;
public float sens;
void Start(){
sens *= speed;
}
void Update () {
if (transform.localPosition.x > max) {
sens = -speed;
} else if (transform.localPosition.x < min){
sens = speed;
}
transform.Translate (sens * Time.deltaTime, 0, 0);
}
}
i can't add pictures here but in unity answers you can understand the problem better with pictures
http://answers.unity3d.com/questions/1009619/collider2d-and-translate-problem.html
i have no idea what is the problem.
can anyone help me please
You have to add a kinematic Rigidbody2D to your moving colliders. Colliders without a rigidbody are treated as static colliders by Unity and should never be moved.
From the official documentation:
The physics engine assumes that static colliders never move or change and can make useful optimizations based on this assumption. Consequently, static colliders should not be disabled/enabled, moved or scaled during gameplay. If you do change a static collider then this will result in extra internal recomputation by the physics engine which causes a major drop in performance. Worse still, the changes can sometimes leave the collider in an undefined state that produces erroneous physics calculations. For example a raycast against an altered Static Collider could fail to detect it, or detect it at a random position in space.