# Why do we need a sinwave and all these codes?

Hi,

``````// to do protect against period is zero
if (period <= Mathf.Epsilon) { return; } // protect against period is zero
float cycles = Time.time / period; //grows continually from 0

float rawSineWave = Mathf.Sin(cycles * tau); // goes from -1 to +1

movementFactor = rawSineWave / 2f + 0.5f;
//movementFactor = rawSineWave;
Vector3 offset = movementFactor * movementVector;
transform.position = StartingPos + offset;
``````
1. Why do we need this code at the first place ? do we we want to make the movement of an object (in this case Obstacle) smoother ?

2. Why do we need a variable `float period = 2f` , particularly in relation to this line
` float cycles = Time.time / period; //grows continually from 0`

3. What does the comment mean â€ś//grows continually from 0`â€ť ?

4. Does the variable cycles have a purpose to find a number of total sinewaves in certain period ?

5. What is the purpose of this line `if (period <= Mathf.Epsilon) { return; }` . It says that to protect against period is zero. Could you explain to me that comment please ?

Thanks for the clarifications in advanced
Cheers

Hi Ihshan,

What is the purpose of this line `if (period <= Mathf.Epsilon) { return; }` . It says that to protect against period is zero. Could you explain to me that comment please ?

Log Mathf.Epsilon into your console. Youâ€™ll notice that it is a value which is almost 0. Actually, you could have written `period == 0` because Mathf.Epsilon is usually used when calculating with floats. All number types in programming are unprecise meaning you do not have a definite number of digits behind the dot. It might be that you are calculating something which is actually 0 but due to the unprecise type, the result is not 0 but 0.000000001 or something like that. Itâ€™s an example to visualise the problem.

To solve this, programmers invented Mathf.Epsilon which generates a very low value which is almost 0 to compare a result with it and treat it as though it was 0.

Why do we need this code at the first place ? do we we want to make the movement of an object (in this case Obstacle) smoother ?

Not smoother but it is supposed to appear more interesting. Itâ€™s difficult to explain. Go to this website and test the different curves to see how the function affects the movement. Ben is doing something similar with the sine function. You can imitate a part of the sine curve on that website and compare it to the linear movement.

What does the comment mean â€ś//grows continually from 0`â€ť ?

The time starts at 0. 0 seconds, 0.12 seconds, 0.245 seconds, and so on. 1001.02 seconds. You have two axes: time and offset in your imaginary diagram. The offset ranges from -1 to 1, and the time starts at 0 and never ends. With your function, you could pass on 1001.02 seconds to get the offset at this particular moment.

Maybe it helps if we take a brief look at a sine wave. I really like this website:
https://www.desmos.com/calculator/w9jrdpvsmk

I labeled the horizontal axis â€śtimeâ€ť, and the vertical axis â€śoffsetâ€ť. When you execute `float offset = Mathf.Sin(Mathf.PI / 2);`, you get `offset == 1`. Can you tell me what the result of `Mathf.Sin(3f * Mathf.PI / 2)` is just by looking at the curve and the axes? If you can do that, you know how Ben utilises this curve.

Pi is approximately 3.14. If we define the horizontal axis in time in seconds, this would mean that the offset is 0 at 3.14 seconds. `Time.time` represents the game time in seconds.

Does that make sense so far?

If so, we can get this curve by passing on `Time.time` to the sine method:

``````float rawSineWave = Mathf.Sin(Time.time);
``````

However, 3.14 is a fairly inconvenient value to intepret. How fast does our object move back and forth completely? According to our wave (see above), itâ€™s 2*PI seconds, 6.28 seconds. Wouldnâ€™t it be nicer if we could say it takes 1 seconds?

``````float tau = Mathf.PI * 2f;
float rawSineWave = Mathf.Sin(Time.time * tau);
``````

I changed the step to 1 on the x-axis, and I get this result:

Now, what happens if we manipulate `Time.time` by dividing it?

``````float cycles = Time.time / 2f;
float tau = Mathf.PI * 2f;
float rawSineWave = Mathf.Sin(cycles * tau);
``````

Type the values yourself on the linked website and toy around with them.

As you can see, the remaining problem is that the values on the y-axis range from -1 to +1. We want 0 to 1.

4 Likes

I donâ€™t know what this is for, but Iâ€™ll take a shot at answering some of these because it helps my own learning process.

#1. The only reason I can think of to put Mathf.Sin into a movement script is if you want a steady back and forth movement. Thatâ€™s what Sin waves are really good for. They can not only move stuff back and forth, but you can predict where something should be in between the two points based at a specific point in time. Because itâ€™s based on a Sin formula. You punch in a time, you get a position. You punch in a position, you get a time. Think of Sin just as a specific relationship between time and position.

#2. Not sure on this one. (edit: Kind of figured this out while thinking of #3, below.)

#3. Well, Time.time starts at 0 and just keeps counting up as the game progresses. Assuming that period is constant and doesnâ€™t change, then yeah, cycles will start at 0 but over time will gradually grow larger. Generally speaking, the cycles will be the number of periods that have passed. So I guess, period would be the total amount of time over which you want your stuff to move from one point to the other. Cycles is the number of periods that have passed. This way you can edit the period as much as you want without interfering with the rest of the formula.

#4. Period is the total time it takes to do one cycle. Cycles are number of total periods that have passed (with a decimal point indicating part of a period has passed).

#5. This oneâ€™s a two parter, and is just part of Benâ€™s style of coding, I think. Youâ€™ll notice that we divide by â€śperiodâ€ť in the next line. Well, we want to make sure that â€śperiodâ€ť is never 0. Dividing by 0 is a mathmatical impossibility and sometimes does bad things to computer processors in the form of errors and crashes. Your game wonâ€™t run properly if you try to divide by 0.

Mathf.Epsilon is a const variable built into Unity. It is equal to the smallest floating value that Unity can keep track of. So if period is equal to or smaller than this, then the functionâ€™s just going to return out and not do anything. Itâ€™s called an â€śearly escapeâ€ť. Most of the time, however, this If statement is going to be FALSE because the â€śperiodâ€ť will be higher than Mathf.Episolon. (I believe you mentioned itâ€™s hardcoded at 2f.) So because the IF statement is false, the {return;} code wonâ€™t happen and the method will continue on normally. Itâ€™s just a little bit of defensive coding to protect against possible errors.

Basically what this code seems to do is,
Check how much time has passed, and determine how many periods have passed in that time.
Take the typical length of a sin wave and multiply it by the number of periods that have passed.
Get the Sin of this value.
Because sin waves are cyclical, the actual number of periods (cycles) does not matter when calculating the sin. Mathf.Sin(1 * tau) = Math.Sin(2 * tau) = Mathf.Sin(3 * tau) = Mathf.Sin(4 * tau), etc.
So you can ignore the actual number of cycles that have passed. The thing is when you calculate cycles (Time / period), youâ€™re likely going to get a decimal number and this is whatâ€™s important. Itâ€™s that remainder.
The remainder indicates only part of a period has passed. So letâ€™s say 25 seconds have passed and your period is 2. When you calculate cycles (time / period), youâ€™re going to get 12.5. That means youâ€™ve gone back and forth 12 times. Who cares? If you start at position X, and you go back and forth from position Y 12 times, youâ€™ll still be at position X afterward. It doesnâ€™t matter. That extra 0.5 is important though. It means youâ€™re not at that starting place, youâ€™re half way through a trip back and forth. In this case, it means youâ€™re actually at a different position right now. We can predict that in another 0.5 second, you will be back at position X.

All this means is that if we set a period, at any given point in time, weâ€™re going to get a value from -1 to 1. But the last couple of lines multiply this value by a vector. So now we get a vector that gradually gets larger (up to 1, or 100%) then starts to get smaller (until it gets to 0), then reverses direction and starts again, and keeps doing that.

6 Likes

Hello Nina,

Thank you for this math explanation. I have a better understanding now for how the object moves.

Cheers

Hello @Anthony_Juarez ,

Your simple explanation is awesome. It helps me to have deeper understanding in a simple way after reading Ninaâ€™s explanation.

Thanks a lot

Best

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.