- Home /
Moving object doesn't move smoothly
I have an enemy object moving towards the player using this script: using UnityEngine; using System.Collections;
public class EnemyMovement : MonoBehaviour {
Transform player;
NavMeshAgent nav;
float timer;
void Awake () {
player = GameObject.FindGameObjectWithTag ("Player").transform;
nav = GetComponent <NavMeshAgent> ();
}
void Update () {
nav.destination = player.position;
}
}
I also have my camera moving to the player's position using this script: using UnityEngine; using System.Collections;
public class CameraControl : MonoBehaviour
{
public GameObject player;
private Vector3 offset;
void Start ()
{
offset = transform.position;
}
void LateUpdate ()
{
transform.position = player.transform.position + offset;
}
}
When the player moves and the enemy moves towards the player, the enemy movement is not smooth but is flickering/faltering. When I stand still (and the camera is not moving), the enemy movement is nice and smooth. It's also nice and smooth when I stop the camera from moving towards the player.
Does anyone know what is causing this and how I can fix it?
Answer by _dns_ · Oct 01, 2014 at 04:31 PM
Hi, I think the problem you have is linked to Update and FixedUpdate and the way the navigation works.
What I think is that the navmesh internal engine will only update the position of your enemy during a FixedUpdate (just before or after all FixedUpdates, probably because pathfinding depends on collisions that are also updated during FixedUpdates). You are changing the navmesh destination during Update, and I guess your player moving code is in Update too.
You also know that sometime you can have multiple Update called when only 1 FixedUpdate is called, depending on the project's physics settings and the current framerate. Example: U,U,FU,U,FU,U,U,FU
Then, imagine there is U,FU,U,FU : your enemy will go toward the player during a FU (coz physics&navmesh are updated during FU), and the camera follow the player during a PU (there will be exactly as many PostUpdate as Update). In this case, everything is fine, the camera is not late or in advance in following the player, and the enemy is also not late.
In the case U, FU, U, U, FU: the player will change position during the two "continuous" U. The camera will change position during the 2 U (=PU), but the navmesh will only update the destination during the FU. Then, the enemy will "be late" while the camera will be exactly on time.
As the sequences of U and PU are quite random, sometimes the camera and enemy are not in sync, causing the jitter. That also explains that if either one of them is static, everything looks fine.
Now, to fix this: I don't know the navemesh system very well so I don't know if there is an "interpolate" flag like there is in the physics system. Maybe the navmesh will use this flag if there is a Rigidbody on your enemy: if so, you could try setting the interpolate flag to the "interpolate" value.
Something you can also do is update your camera with some damping: transform.position = Vector3.Lerp (transform.position, player.transform.position+offset, Time.deltaTime * Damping). Damping being a public float field that you can tune to have the camera following "slower" or "faster", try different values. This might be enough to eliminate the jitter.
If this doesn't work, I would make sure everything is in sync:
Change the priority of your player script in the project settings (setting this script to a value like "-10") so you can be sure it's updated before all enemies.
Update the enemy's navmesh destination during a FixedUpdate instead of Update.
Define a public Vector3 CameraTarget in your player's script. In the player's FixedUpdate, set CameraTarget to transform.position.
Use the damping code to update your camera during FU but now, instead of using player.transform.position, use player.CameraTarget.
Doing this, everyone, enemy + camera will target the same position that is updated during FixedUpdate so the navmesh system will use this one too, hopefully fixing your problem (make sure to use the damping on the camera or the camera will not be smooth if it targets a position updated during FixedUpdate)
I'm not 100% sure that this is the cause of the problem, I hope one solution will work, please tell me if it does in the comments :-)
Thanks a lot for your answer. I have tried everything, but the only thing that seemed to make a difference is the camera smoothing. When I set the Damping variable to below 50 the player will jitter, and above 50 the enemy will jitter.
Answer by smoggach · Sep 30, 2014 at 04:40 PM
The camera movement plus LateUpdate is what is causing this. Your enemy is trying to animate at the same time his coordinate system is being animated.
LateUpdate is called after all other Updates. So your enemy gets maybe 2 or 3 updates for each LateUpdate in your camera. What's happening when the camera moves is the enemy changes his position, and then the camera moves and changes it again. The next frame he has to move even farther because the camera moved him by moving itsself, then the camera moves again.
A solution would be to render the enemies to a different camera.
It would smooth itsself out a little better if both the enemy and camera were actually animated (via animations, tweens, Vector3.Lerp). I'd try that first. If that's no good then i'd find a way to do it without moving the camera.
To render to a different camera: Put your enemy onto a new layer. Duplicate your main camera. Set it's culling mask to the enemy layer only Set it's clear flag to depth only.
Now your enemy will render to his own camera. However I don't know if this will help you achieve the desired effect.
I can animate the camera by using Vector3.Lerp, but how can I animate the enemy? The enemy uses a nav mesh.
Does anyone else have an idea on how to fix this? I'm still not sure how to fix it with smoggach's answer.
Have you tried swapping your updates? (enemy uses LateUpdate and camera uses Update)
An alternative to moving your camera would be to move your actual scene (put everything in the scene under one GameObject and move that GameObject around).
Answer by Cortex99 · Sep 30, 2014 at 04:44 PM
Alright, thanks for your answer. How would I render the enemies to a different camera? Also, when I change LateUpdate to FixedUpdate or just Update, the same thing happens.
EDIT: Also I would like to note that the enemy is just a capsule object without any animation/animator controller to it.
Hi Cortex99. I have a problem like you now. Did you find solution for this problem. I expect your answer. Thanks :).
The solution I found is to replace completely the Update function with Fixed Update. $$anonymous$$y Character then moved smoothly all of a sudden.