Lerp Animation Problem
Dear Forum,
I am an experienced 3D animator but only a C# beginner and I have a (probably) very simple problem which I can´t solve on my own.
In a nutshell:
I have 4 objects (players) and three buttons placed between them. On clicking the buttons I want the objects left and right of the button to switch their positions. Due to the fact that the objects will be passed from button to button I need to check their positions and then decide wether to move them or not. The buttons call the SwitchPos() on click and the script is placed on a parent empty game object and checks the objects by their tag "asset3_objects". Currently I only have one if clause running checking if an object has transform.x equals 4 and needs to be moved to 7
I use the following script:
using UnityEngine;
using System.Collections;
public class asset2_master_v2 : MonoBehaviour
{
public GameObject[] players;
public void SwitchPos()
{
players = GameObject.FindGameObjectsWithTag("asset3_objects");
for (int i = 0; i < players.Length; i++)
{
// Debug.Log("Player Number " + i + " is named " + players[i].transform.position.x);
if(players[i].transform.position.x==4)
{
Debug.Log("Object Number" + i + "fits");
private float timeElapsed;
private float lerpDuration = 30f;
private float startValue = 4;
private float endValue = 7;
private float valueToLerp = players[i].transform.position.x;
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
timeElapsed += Time.deltaTime;
}
}
}
}
The Debug Log tells me that the object fits the position. Now when I add the Lerp components things start to go sideways and I get the error codes:
Assets\scripts\asset3\asset2_master_v2.cs(28,15): error CS1519: Invalid token '.' in class, struct, or interface member declaration
Assets\scripts\asset3\asset2_master_v2.cs(28,36): error CS1519: Invalid token ';' in class, struct, or interface member declaration
Where do I go wrong? I am probably pretty close but I am still learning and do not have the necessary knowledge to solve this on my own. I have read a bit on the Lerp function but the tutorials and documentation cover topics which are a lot more complex than this.
Thank you and best regards
Dunkel-san
Remove all that private
keywords. Those are invalid for local variables.
Answer by dunkel-san · Jul 16, 2021 at 10:18 AM
Hey there, I removed the private keywords and that took care of the CS1519 errors, thank you very much. It still is not working however and now I get a new compilation error which reads
Assets\scripts\asset3\asset2_master_v2.cs(28,18): error CS0165: Use of unassigned local variable 'timeElapsed'
I then commented those parts out of the script (because the float did not have a value) and now it reads and still does not work. The debug message runs fine, but the Lerp animation is not working
using UnityEngine;
using System.Collections;
public class asset2_master_v2 : MonoBehaviour
{
public GameObject[] players;
public void SwitchPos()
{
players = GameObject.FindGameObjectsWithTag("asset3_objects");
for (int i = 0; i < players.Length; i++)
{
if (players[i].transform.position.x == 4)
{
Debug.Log("Object Number" + i + "fits");
//float timeElapsed;
float lerpDuration = 3;
float startValue = 4;
float endValue = 10;
float valueToLerp = players[i].transform.position.x;
valueToLerp = Mathf.Lerp(startValue, endValue, lerpDuration);
// timeElapsed += Time.deltaTime;
}
}
}
}
public variables are automatically set to a default value by unity, however private values need to be set first...so just put
float timeElapsed = 0f;
and there should be no erros
Okay, put the timeElapsed back in and gave it 0f, but it´s still not doing anything. startValue and endValue are there, I checked that with another Debug.Log, but something is not right with the Lerp. Could it have something to do with all the values being floats?
you have to multiply the lerp duration with Time.deltaTime and also shift it to the update method....void methods run only once when called and hence cannot run a proper lerping action
Okay, I´m almost there, threw out all the if clauses and concentrated on Lerp and button add listener. Please have a look at this, the lerp runs well from the TaskOnClick() , but it´s not waiting for the Button to get clicked, i.e. I still must have missed something on the Addlistener setup. using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;
public class lerp4 : MonoBehaviour
{
public Button Button1;
private Vector3 startPos, endPos;
public GameObject target;
private float lerp = 0, duration = 1;
// Start is called before the first frame update
void Start()
{
Button btn = Button1.GetComponent<Button>();
btn.onClick.AddListener(TaskOnClick);
startPos = transform.position;
endPos = target.transform.position;
}
void TaskOnClick()
{
Debug.Log("Button has been clicked");
lerp += Time.deltaTime / duration;
transform.position = Vector3.Lerp(startPos, endPos, lerp);
}
// Update is called once per frame
void Update()
{
TaskOnClick();
}
}
It is because you are actually calling TaskOnClick() in every frame in update...i corrected this in here..and tested it...works totally fine in my opinion...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class lerp4 : MonoBehaviour
{
public Button Button1;
private Vector3 startPos, endPos;
public GameObject target;
private float lerp = 0f, duration = 1f;
public bool lerpactive;
// Start is called before the first frame update
void Start()
{
Button1.onClick.AddListener(StartLerp);
}
//Sets the lerping variable to true and starts the stopping Coroutine
void StartLerp()
{
lerp = 0f;
Debug.Log("Button has been clicked");
lerpactive = true;
StartCoroutine(StopLerp());
}
//Does the actual lerping
void LerpAction()
{
lerp += Time.deltaTime / duration;
transform.position = Vector3.Lerp(startPos, endPos, lerp);
}
//Stops the lerp 0.1s after the duration
IEnumerator StopLerp()
{
yield return new WaitForSeconds(duration + 0.1f);
lerpactive = false;
Debug.Log("the lerp action has ended");
}
// Update is called once per frame
void Update()
{
startPos = transform.position;
endPos = target.transform.position;
if(lerpactive)
{
LerpAction();
}
}
}
The IEnumerator coroutine closes the lerp after a set period of time, which in this case is the duration...i added 0.1f to be sure that the process has properly finished....you could also use Mathf.Approximately, but i think that's be quite unnecessary..also you'll notice that i removed the btn variable since you had already reference the button as Button 1 and the rest was quite unnecessary...i have tested it and this should work totally fine....glad i could be of service
EDIt: added some comments to make the code more legible and corrected the Debug.Log 's position
Thank you so much, I finally understand where I was missing out. I will read up on Coroutines to understand what you did there, that look very useful.
Your answer
Follow this Question
Related Questions
How to make enemy detect a character in his certain range? 1 Answer
Pausing a the starting movement 0 Answers
Why is Nothing Moving? 0 Answers
Switching lanes 1 Answer
Help please, movement and animator issue 0 Answers