- Home /
Slerpy Spider Won't Behave (Chaining Slerps)
Hey all,
I'm having problems getting my script to switch between two slerps depending on the state of a bool.
I've got a spider that swings from "Start" to point "End" along an arc. Start and End are both public Transforms that can be set through the inspector and I've put in two empty game objects (A and B) that have been placed in the scene (at (0,0,0) and (10,0,0).
If A→B is true, then the spider slerps towards point B.
If the distance between A and B drops beneath a certain point (I've tried a few values) then the spider slerps back from B to A. Problem is that while A→B works fine, once the B→A bool kicks in, the spider darts between points A and B (linearly) within the span of a frame and then continues to dart in a straight line between the two points.
Here is the code.
using UnityEngine;
using System.Collections;
public class spiderTest : MonoBehaviour {
public Transform start;
public Transform end;
public bool startToFinish;
public bool finishToStart;
public float speed;
public float distance;
GameObject spider;
public GameObject A;
public GameObject B;
Vector3 spiderPos;
Vector3 startPos;
Vector3 endPos;
// Use this for initialization
void Start ()
{
spider = this.gameObject;
startPos = start.transform.position;
endPos = end.transform.position;
startToFinish = true;
finishToStart = false;
speed = 0.1f;
transform.position = start.position;
//transform.position = end.position;
}
// Update is called once per frame
void Update ()
{
if(startToFinish == true)
{
Vector3 center = start.position + end.position * 0.5f;
center -= new Vector3(0,-1,0);
Vector3 startRelCenter = start.position - center;
Vector3 endRelCenter = end.position - center;
distance = Vector3.Distance(transform.position, end.transform.position);
if(distance >= 0.1)
{
transform.position = Vector3.Slerp(startRelCenter, endRelCenter, Time.time * speed);
transform.position += center;
}
if(distance <= 0.1)
{
ResetA();
}
}
if (finishToStart == true)
{
Vector3 center = (start.position + end.position) * 0.5f;
center -= new Vector3(0,-1,0);
Vector3 startRelCenter = end.position - center;
Vector3 endRelCenter = start.position - center;
distance = Vector3.Distance(transform.position, start.transform.position);
if(distance > 0.1)
{
transform.position = Vector3.Slerp(startRelCenter, endRelCenter, Time.time * speed);
transform.position += center;
}
if(distance <= 0.1)
{
ResetB();
}
}
}
void ResetA()
{
if(startToFinish == true)
{
startToFinish = false;
transform.position = end.position;
distance = 0;
finishToStart = true;
}
}
void ResetB()
{
if(finishToStart == true)
{
finishToStart = false;
transform.position = start.position;
distance = 0;
startToFinish = true;
}
}
}
Can you see where I'm going wrong? Is there a way to make the spider slerp back from B to A?
(On a side note, I did think about handling the whole thing through the physics engine via a hinge joint chain, but at this point, it seems like handling it through scripts would fit the project better.)
Thanks for your time!
It's much easier if you use coroutines. See the example code for $$anonymous$$oveObject (that's the general idea, not that it will do this exact thing).
Not sure what a coroutine is, but I'll take a look at your hyperlink! Thanks!
Did a bit of reading into this and looks interesting. I still have a bit more reading to do before I feel like I can use it well, but thanks for the link! :D
Answer by WillTAtl · Dec 03, 2011 at 06:43 AM
Eric's comment is a good one, and there are many little ways this code could be improved, but that's for later, right now, you just want to make this work; you can learn to make the code better later!
The specific reason you're seeing the behavior you describe is that you're using Time.time for your slerp time, and Time.time always goes up. It only works the first time because Time.time starts at 0 when you hit "play," but it never resets, so when it reaches the end and you switch directions, "Time.time * speed" is still greater than 1, so the following slerps happen instantly!
three quick steps to make it work like you expect:
1) add a variable of type float called slerpStartTime to the script, at the top next to speed.
2) in Start(), ResetA(), and ResetB() - all three! - set slerpStartTime = Time.time
3) in both lines that call Slerp, change the last parameter from "Time.time speed" to "(Time.time - slerpStartTime) speed"
That should get you past this problem so you can move on to the next challenge!
Thank you.
I've found that I can adjust the Y values (the depth to which the spider descends at the half-way point, (the radius?)) by messing "center -= new Vector3(0,-1,0);" line. Seems like the deepest I can go is about 0.01f before the spider starts wigging out. Would be nice to get a bit more though. Trying to make it easier for our developers to set the spider's path to their liking. ;D
First time for using slerps so I'm still trying to figure out what everything does but your answer worked perfectly for what I'm trying to do. Thanks again for your time!
Your answer
Follow this Question
Related Questions
Error : Animator has not been initialized. UnityEngine.Animator:SetBool(String, Boolean) 1 Answer
Unexpected Symbol 'public' 1 Answer
I'm having trouble setting a bool. 2 Answers
How to add WAKE_UP animation before the character enters IDLE state? 1 Answer
Setting a bool to false using CharacterControllerHit? 1 Answer