I am trying to animate a platform prefab that is spawned (the platform object itself is within an empty because its position changes) DOWN when a Runner object collides with it (onCollisonEnter) and UP on collision exit.
I have followed answers given to my old question here verbatim- Unity, C# - cannot make object move down from current y position ONCE on collision enter? but can't get animations using the Animator to work despite having this in my animator as directed:
One person who answered suggested I use Lerp to animate the platform prefab entirely using code. I have researched Lerp but as I need 2 separate states for Down/Idle Down (to make platform stay down) and the same for up/idle up I do not know how to do this.
How can I achieve this effect using Lerp programmatically? Is it possible to achieve the effect I am going for?
ERROR:
EDIT:
how i spawn (dequeue then enqueue) my platforms:
nextPosition += new Vector3 (
Random.Range (minGap.x, maxGap.x) + scale.x,
Random.Range (minGap.y, maxGap.y),
Random.Range (minGap.z, maxGap.z));
Transform o = objectQueue.Dequeue();
o.localScale = scale;
o.localPosition = position;
//o.localEulerAngles = rotation;
o.gameObject.SetActive (true);
int materialIndex = Random.Range(0, materials.Length);
o.GetComponent<Renderer>().material = materials[materialIndex];
o.GetComponent<Collider> ().material = noFrictionMaterial;
platform newScript = new o.GetComponent<platform>(); //getting an error here when I tried to implement your code
objectQueue.Enqueue (o);
if(nextPosition.y < minY){
nextPosition.y = minY + maxGap.y;
}
else if(nextPosition.y > maxY){
nextPosition.y = maxY - maxGap.y;
}
This is what the vectors should ALWAYS be and what I set them at originally in start():
up = new Vector3 (transform.position.x, transform.position.y, transform.position.z);
down = new Vector3 (transform.position.x, transform.position.y-2f, transform.position.z);
Since the platforms aren't actually spawning, are you sure that's the error? Can you help me?
This should work for you:
using UnityEngine;
using System.Collections;
public class Collision : MonoBehaviour {
public Vector3 up, down;
public bool isUp = false;
public float speed = 5f;
float startTime,
length;
bool isMoving = false;
void Start () {
//initialise the platform to a position
if (isUp) transform.position = up;
else transform.position = down;
length = Vector3.Distance(up, down);
}
void Update()
{
if (isUp)
{
//move Down
transform.position = Vector3.Lerp(up, down, ((Time.time - startTime) * speed) / length);
}
else
{
//move Up
transform.position = Vector3.Lerp(down, up, ((Time.time - startTime) * speed) / length);
}
}
//move down
void OnCollisionEnter(Collision col)
{
if (!isMoving)
{
startTime = Time.time;
isMoving = true;
}
}
//move up
void OnCollisionExit(Collision col)
{
if (!isMoving)
{
startTime = Time.time;
isMoving = true;
}
}
}
The thing you have to watch out for is making sure that the "runner" stays on the platform until it's on the bottom so that it can move up again. You could add a check so that it moves back up regardless with another bool it it doesn't work for you. Hope it helps :)
EDIT
What lerp (short for linear interpolation) does is pick points between two vectors based on the progression of the time component (0 to 1). So in order for the platform to go up and down it needs a starting point and an end point, in this case it's up or down (up to the upper position down for the other).
If you want to create a new platform without causing an error you need to set these values after creating it so that everything works correctly (if you leap from any position it will jump aggressively in the first step of the lerp). For example:
//after instantiating the new platform object
scriptName newObject = newGameobject.GetComponent<scriptName>();
newObject.up = (up Vector);
newObject.down = (down Vector);