- Home /
Lerp toward object while keeping a constant speed
Hello everyone,
Am trying to make a "following effect", something like homing missles, i tried to use both Slerp and Lerp but am always facing the same problem which is the acceleration loss at some point, i want to know if there is a way to follow an object while keeping the same speed. Here is the complete class that i use :
using UnityEngine;
using System.Collections;
public class EnemyFollow : MonoBehaviour
{
public float speed ;
public float damping;
Transform myTrans;
public Transform target ;
// Use this for initialization
void Start ()
{
myTrans = transform;
}
// Update is called once per frame
void Update ()
{
Quaternion rotation = Quaternion.LookRotation (target.position - myTrans.position);
myTrans.rotation = Quaternion.Lerp (myTrans.rotation, rotation, Time.deltaTime * damping);
myTrans.position = Vector3.Lerp (myTrans.position, target.position, Time.deltaTime * speed);
}
}
And here is a web version of the prototype so you can better understand what am saying, use arrows to control your spaceship : Prototype-test
PS : this is an off topic but do you have any idea why the enemy "flip" around sometimes ?
thank you and have a great day
Change your Vector3.Lerp() to Vector3.$$anonymous$$oveTowards() on line 21. The parameters remain the same. You will have to adjust your 'speed' variable since it will behave differently in $$anonymous$$oveTowards(). It will become units per second.
still don't have the effect am looking for, i don't thing moveTowards or lerp/slerp are the correct calls, since i don't need the object to move toward the player, i need it to always go forward based on his rotation, i don't know if you can see what am trying to do here or not, but the goal is to have an enemy who follow the player in a "slippery way" so the player can dodge and make the enemy go into obstacles and die
@Aladine then look at `Quaternion.RotateTowards()`.
@$$anonymous$$elly$$anonymous$$ i already tried that but the Quaternion type is somehow "over complicated" when it's used in a 2D game, however, RotateTowards() almost do exactly the same thing that my previous code do
Answer by KellyThomas · Feb 01, 2014 at 12:29 PM
This should rotate towards the target using only z-axis rotations.
float angleSpeed = 180f;
float movementSpeed = 10.0f;
float nearEnough = 20f;
void RotateTowards(Vector3 targetPosition) {
Vector2 targetDirection = targetPosition - transform.position;
float idealAngle = Mathf.Rad2Deg * Mathf.Atan2(targetDirection.y, targetDirection.x);
float currentAngle = transform.rotation.eulerAngles.z;
if(Mathf.Abs(Mathf.DeltaAngle(idealAngle, currentAngle)) > nearEnough) {
float nextAngle = Mathf.MoveTowardsAngle(currentAngle, idealAngle, angleSpeed * Time.deltaTime);
transform.rotation = Quaternion.Euler(new Vector3(0.0f, 0.0f, nextAngle));
}
}
at line 5, the "target" is a transform object, should i replace it by target.rotation.eulerAngles.z
cause $$anonymous$$athf.$$anonymous$$oveTowardsAngle take 3 floats, PS : i did the replacement and the enemy go crazy xD EDIT i like the way your code works, am starting to think about making a raycast that stop the rotation in case the enemy is facing the player cause for now all that it rest is stopping the rotation when it is in the right direction
Yeah... sorry line 5 should have been idealAngle i.e. the angle towards the target.
If you want to throttle the enemy you could reduce angleSpeed
or do a check with $$anonymous$$athf.DeltaAngle(myTrans.rotation.eulerAngles.z,idealAngle)
and stop rotating when "near enough is good enough".
this make it pre-perfect : float angle = 10; if (Vector3.Angle (myTrans.right, myTrans.position - target.position) > angle) { /your code here/ } but did you notice the "always-rotate-left" thing ??? anyway to fix that ??
Vector3.Angle()
will return both positive and negative values, you might want to wrap it in a call to $$anonymous$$athf.Abs()
to remove the bias in the condition posted above.
i don't see any need for that, but i tested it anyway, and the result is the same, i think what i need here is a way to tell either the target (player) is on the left or on the right of the enemy, and by left and right i don't mean their X position in the world, but on which side of the enemy the player is, do you get what i meant ?
Answer by robertbu · Feb 01, 2014 at 02:22 PM
Your question asked and your follow-up comments seem very different. Assuming your original code works except for flipping, I have to assume that 1) you are rotating around the 'z' axis for this 2D game and 2) the 'forward' of your follower is what is pointed at the the thing it is following. If so, you can solve your flip by adding the optional second parameter to the LookRotation() call. It is the 'up' vector, and for a 2D game planed on the XZ palne you want to use Vector3.forward:
Quaternion rotation = Quaternion.LookRotation (target.position - myTrans.position, Vector3.forward);
myTrans.rotation = Quaternion.Slerp (myTrans.rotation, rotation, Time.deltaTime * damping);
Note the use of .Slerp() here, will produce an eased rotation. You may want to use RotateTowards() instead. If so, you will need to increase the value of 'damping'.
Given you want, "i need it to always go forward based on his rotation," you want to change line 21 to:
myTrans.position += myTrans.forward * Time.deltaTime * speed;
Again this assumes you are using a 3D object and want the 'forward' side (the side facing positive 'z' when the rotation is (0,0,0)) to be the side aimed by the rotation.
Answer by jake4040 · Feb 05, 2015 at 03:14 AM
How about applying a torque to the homing object with a magnitude based on the difference in angle between the direction the missile is pointing and the ray from the homing object to the player? Then you can use the inertia of the homing object and/or the magnitude of the applied torque to control how tightly it can track.
You would also need to continue to apply forward thrust to the object so it will curve based on it's new direction.
This would use the physics engine to basically model a "homing missile" type effect.