I have a circular motion of an object, and it should change its position to a circle with a bigger radius after pressing a key. The problem is, that it should lerp from the actual position to the new position in the bigger circle (image) and then it should continue with its circulation. Unfortunatley I dont know how to code that.
Greetings,
J.
public float RotateSpeed = 5f;
public float Radius;
private Vector2 centre;
private float angle;
private void Start()
{
centre = transform.position;
Radius = 0.3f;
}
private void Update()
{
if (Input.GetKeyDown (KeyCode.DownArrow)) {
Radius = 0.5f;
Vector2 newPos = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * Radius;
transform.position = Vector3.Lerp (transform.position, newPos, 0.5f);
}
angle += RotateSpeed * Time.deltaTime;
var offset = new Vector2 (Mathf.Sin (angle), Mathf.Cos (angle)) * Radius;
transform.position = centre + offset;
}
You have set it to 0.5, which will automatically set the position to inbetween the current position and the newPos.to achieve a successful lerp you must increase (c) by a time until it reaches 1 (hits your target position) here is an example script of how you can handle the lerp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LerpDemonstration : MonoBehaviour
{
public Vector3 targetPos;
private bool downPressed = false;
public float lerpSpeed;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.DownArrow))
{
if (!downPressed)
{
StartCoroutine(DoLerpFunction());
downPressed = true;
}
}
}
IEnumerator DoLerpFunction()
{
downPressed = true;
float time = 0.0f;
while (transform.position != targetPos)
{
if (time < 1.0f)
{
time += lerpSpeed * Time.deltaTime;// increase time by a set speed * deltatime (gives room to edit to a value you like)
transform.position = Vector3.Lerp(transform.position, targetPos, time);
}
yield return null;
}
downPressed = false;
}
}
The only issue with this code is that you will have to continuously set the Target position after the lerp has been completed, but you can easily edit this for desired results.
Also, in most cases when beginners reach for Lerp, what they really want is Mathf.MoveTowards (or Vector3.MoveTowards or whatever it is they’re dealing with).
In this case, you just want the Radius to MoveTowards the larger radius for a little bit each frame. Here’s how I would do it.
public float RotateSpeed = 5f;
public float RadiusChangeSpeed = 0.1f;
public float TargetRadius = 0.3f;
private Vector2 centre;
private float angle;
private float actualRadius;
private void Start()
{
centre = transform.position;
actualRadius = TargetRadius = 0.3f;
}
private void Update()
{
if (Input.GetKeyDown (KeyCode.DownArrow)) {
TargetRadius = 0.5f;
}
angle += RotateSpeed * Time.deltaTime;
actualRadius = Mathf.MoveTowards(actualRadius, targetRadius, RadiusChangeSpeed * Time.deltaTime);
var offset = new Vector2 (Mathf.Sin (angle), Mathf.Cos (angle)) * actualRadius;
transform.position = centre + offset;
}
thanks for your help! It works, but if I press a key it should move very fast to the larger radius towards the extended line between the center and the point where I pressed the button (red dotted line in the image). So the rotation should stop while the object moves/lerps and afterwards continue. What is the best way to do that?
public float RotateSpeed = 5f;
public float RadiusChangeSpeed = 0.2f;
public float TargetRadius = 0.3f;
private Vector2 centre;
private float angle;
private float actualRadius;
bool moving = false;
private void Start()
{
centre = transform.position;
actualRadius = TargetRadius = 0.3f;
}
private void Update()
{
if (Input.GetKeyDown (KeyCode.DownArrow)) {
moving = true;
TargetRadius = 0.5f;
StartCoroutine(WaitforLerp());
}
if (moving == true) {
angle += 1 * Time.deltaTime;
actualRadius = Mathf.MoveTowards (actualRadius, TargetRadius, 2 * Time.deltaTime);
Debug.Log (Time.deltaTime);
var offset = new Vector2 (Mathf.Sin (angle), Mathf.Cos (angle)) * actualRadius;
transform.position = centre + offset;
}
if (moving == false) {
angle += RotateSpeed * Time.deltaTime;
actualRadius = Mathf.MoveTowards (actualRadius, TargetRadius, RadiusChangeSpeed * Time.deltaTime);
var offset = new Vector2 (Mathf.Sin (angle), Mathf.Cos (angle)) * actualRadius;
transform.position = centre + offset;
}
}
public IEnumerator WaitforLerp()
{
yield return new WaitForSeconds(0.15f);
moving = false;
}
It seems to work, but I think your Method @JoeStrout is better. What do you think?
And do you have an Idea how I can adjust the speed of the object, so that it is the same for every radius size?