1. Move to position on OnTriggerEnter() and move back on OnTriggerExit()
The following should start the raiseSign coroutine whenever the player enters the trigger. It force stops that coroutine whenever it leaves it again and then starts the lowerSign coroutine (and vice versa).
public Transform sign;
public Vector3 signTargetOffset;
public float raiseTime = 2;
public GameObject player;
private Vector3 signStart;
private Vector3 signTarget;
private bool isEnabled = false;
private float elapsedTime = 0;
void Start()
{
signStart = sign.position;
signTarget = signStart + signTargetOffset;
}
void OnTriggerEnter(Collider other)
{
if(!isEnabled && other.gameObject == player)
{
isEnabled = true;
StopCoroutine("LowerSign");
StartCoroutine("RaiseSign", raiseTime);
}
}
void OnTriggerExit(Collider other)
{
if(isEnabled && other.gameObject == player)
{
isEnabled = false;
StopCoroutine("RaiseSign");
StartCoroutine("LowerSign", raiseTime);
}
}
IEnumerator RaiseSign(float time)
{
// Move to the raised position
while(elapsedTime < time)
{
sign.position = Vector3.Lerp(signStart, signTarget, elapsedTime / time);
elapsedTime += Time.deltaTime;
yield return null;
}
elapsedTime = time;
sign.position = signTarget;
}
IEnumerator LowerSign(float time)
{
// Come back from the raised position
while(elapsedTime > 0)
{
sign.position = Vector3.Lerp(signStart, signTarget, elapsedTime / time);
elapsedTime -= Time.deltaTime;
yield return null;
}
elapsedTime = 0;
sign.position = signStart;
}
Old (Before edit:)
I had this here before. I misunderstood the question, but I’m keeping it here as a reference on how to do the ‘back and forth’ motion at once.
public Transform sign;
public Vector3 signTargetOffset;
public float raiseTime = 2;
Vector3 signStart;
Vector3 signTarget;
public GameObject player;
void Start()
{
signStart = sign.position;
signTarget = signStart + signTargetOffset;
}
void OnTriggerEnter(Collider other)
{
if(other.gameObject == player)
{
StartCoroutine(RaiseSign(raiseTime));
}
}
IEnumerator RaiseSign(float time)
{
// Move to the raised position
float elapsedTime = 0;
while(elapsedTime < time)
{
sign.position = Vector3.Lerp(signStart, signTarget, elapsedTime / time);
elapsedTime += Time.deltaTime;
yield return null;
}
sign.position = signTarget;
// Move back from the raised position
elapsedTime = 0;
while(elapsedTime < time)
{
sign.position = Vector3.Lerp(signTarget, signStart, elapsedTime / time);
elapsedTime += Time.deltaTime;
yield return null;
}
sign.position = signStart;
}
Note about your collisions and the Coroutine running multiple routines at the same time.
Note that since you’re using a Coroutine for this that it is possible that the player runs into the collision area, runs out in the meantime and back in while it’s still performing the routine. This will result in having two of the same Coroutines going on at being performed at the same time.
A possible solution is to have a variable that stores whether it’s already raising the sign, if so it will not trigger it again until it ended. (Shouldn’t be too hard to add. Let me know if you want me to add an example of this quickly.)
2. Move more objects
This should be a slight modification on the script above. You can add extra public Transform sign variables and then also include those in the coroutine, or you could add extra coroutines for them.
To apply rotational changes instead of doing sign.position use sign.rotation.
You can do this because the sign variable in the script is actually a Transform object.
3. Keep moving an object ever since the first collision.
This sounds like it’s activating another script. Instead of writing out the script for you I’ll give you some pointers, here are some possible ways to proceed:
- Enable a component on the object you want to keep moving from within this script
- Set a public variable on another object to True and perform your movements in that script.
- You could also (I think) initialize a looping animation from that point using Unity’s animation system.