I need to transform.Translate (x, 0, 0) and yield (x seconds), and that seems to work fine and all, but I also need to incorporate a “fake-slow motion” effect (without using Time.timeScale) and my solution was to
transform.Translate (x * y, 0, 0) and yield (x / y seconds) where y is a fraction.
However produces different results from the original x translation and yield because the object ends up in a different place then where it should be. If I’m correct, multiplying and dividing the translate and yield should end up in the same place over a longer amount of time… right?
Thanks in advance!
I’m wondering why you use a yield in the first place… To get a smooth movement you should update your position every visual frame (so each update). When using WaitForSeconds the movement just gets choppy.
If I can’t use Time.timeScale i would create a deltaTime wrapper class. Every object that has a movement function needs to use a wrapper instead of Time.deltaTime.
Something like that:
// C#
public class DTProvider
{
private static Stack<float> m_Layers = new Stack<float>();
private static float m_CurrentRealTime = 1.0f;
public static void AddLayer(float aScale)
{
m_Layers.Push(m_CurrentRealTime);
m_CurrentRealTime *= aScale;
}
public static void RemoveLayer()
{
if (m_Layers.Count > 0)
m_CurrentRealTime = m_Layers.Pop();
}
private float m_Scale = 1.0f;
public DTProvider()
{
m_Scale = 1.0f / m_CurrentRealTime;
}
public DTProvider(float aScale)
{
m_Scale = aScale;
}
public float DT
{
get
{
return Time.deltaTime * m_CurrentRealTime * m_Scale;
}
}
public static implicit operator float(DTProvider aProvider)
{
return aProvider.DT;
}
}
Every script that controls movement should create such a wrapper in Awake. That way it’s movement is bound to the current time layer. All movement is simply multiplied with the DT value of the provider. When a new layer is added it will become the new “realtime” and everything from the “old” layer will get slower. When you remove a layer, objects on a deeper layer will get faster.
A movement script could look like this:
public class Movement : UnitySingleton<App>
{
DTProvider DT;
void Awake()
{
DT = new DTProvider();
}
void Update()
{
transform.Translate(5.0f*DT, 0, 0);
}
}
You can also create a provider for a certain timescale:
DT = new DTProvider(4.0f);
this would make the object move 4 times faster than realtime. Now when you add two layers of 0.5f the object would move at normal speed since 0.5f * 0.5f == 0.25f. Since the object’s private timescale is 4 the result will be 1.0f (==0.25f * 4.0f). If you add another layer of 0.5f the speed will continue to slow down.
Okay so instead I just used a trigger system that turns off the movement instead of trying to time it, so now it only has to reduce the speed and no matter what speed when it hits the trigger it’ll stop at that point.