set value to 0 every forth iteration.
Hello!
I am making a graph with a set amount of local (or relative?) maximum/minimum-points. Between these points there are lines containing 3 gameobjects. The maximum/minimum-points are randomly generated between y = 0f,1f. What i am trying to put the 3 gameobjects between the maximum/minimum-points, these 3 objects should follow the equation of a line that is calculated from said maximum/minimum-points.
I have done everything right, but what i cant figure out is how to reset the b value of the lines (y = ax+b).
This is the code with some comments:
using UnityEngine;
using System.Collections;
public class perlin : MonoBehaviour {
public GameObject point;
public GameObject[] points;
private float x;
private float y;
private float a;
private float b;
void Start () {
//Generetes a straight line of gameobjects
for (int i = 0; i < points.Length; i++){
x = i;
points[i] = Instantiate(point,new Vector3 (x*0.25f,y,0),transform.rotation) as GameObject;
}
//Sets the local maximum/minimum-points.
for (int i = 0; i < points.Length; i+=4){
Vector3 temp = points[i].transform.position;
temp.y = Random.Range(0f,1f);
points[i].transform.position = temp;
}
//Sets the position of the gameobjects between the local maximum/minimum-points.
for (int i = 0; i < points.Length; i++){
if ((i % 4) == 0 && i < points.Length - 4){
if (points[i].transform.position.y > points[i+4].transform.position.y){
a = -Mathf.Abs((points[i].transform.position.y-points[i+4].transform.position.y)/(points[i].transform.position.x-points[i+4].transform.position.x));
}
if (points[i].transform.position.y < points[i+4].transform.position.y){
a = Mathf.Abs((points[i].transform.position.y-points[i+4].transform.position.y)/(points[i].transform.position.x-points[i+4].transform.position.x));
}
b = points[i].transform.position.y; //HOW TO RESET THIS?
}
if ((i % 4) != 0){
Vector3 temp = points[i].transform.position;
temp.y = a*points[i].transform.position.x+b;
points[i].transform.position = temp;
}
}
}
}
Now, this first line of gameobjects is at its right position but the second, third, forth.... is way out of position since b never resets to 0. If i reset b to 0 every 4th iteration of i (when the index is at a maximum/minimum-point) i think i could achive what i want, my question is how to do this in the code.
A poorly drawn picture of what i am trying to achive:
Any help is appretiated!
Thank you!
Answer by wibble82 · Dec 21, 2015 at 01:58 PM
The issue with your maths is that you calculate a 'gradient' every 4 points, which you call 'a', and also store an offset, 'b'. 'a' is a number that you can plug into the equation:
y = ax + b
to get a new position.
However, writing it more fully we would write:
new_y = gradient * change_in_x_since_last_worked_out_gradient + y_when_last_worked_out_gradient
When we look at it that way, we can see why your code doesn't work. On line 48, you simply multiply the current point's x position by a. This works for the first 4 points that have an x between 0 and 1, but after that you're going wrong - for the 10th point you're doing:
new_y = (10/4)*a + b
However you haven't traveled a distance of 10/4 (or 2.5) since you last calculated a gradient - you've traveled a distance of 0.5.
I had a go at rewriting your logic a bit, in a slightly cleaner way. I've thought of it in terms of 'key frames', so my maths is based around working out how far my current point is from the previous key frame.
void Start () {
//Generate a line of points at y = 0 (as the variable y defaults to 0 and we don't change it anywhere else)
for (int i = 0; i < points.Length; i++){
x = i;
//instantiate object at x*0.25, so every 4 points are 1 unit apart
//note: we use static '(type)' cast, not dynamic 'as' cast, because we EXPECT result to be game object
points[i] = (GameObject)Instantiate(point,new Vector3 (x*0.25f,y,0),transform.rotation);
}
//Assign random y between 0 and 1 to every 4th point
for (int i = 0; i < points.Length; i+=4){
Vector3 temp = points[i].transform.position;
temp.y = Random.Range(0f,1f);
points[i].transform.position = temp;
}
//Sets the position of the gameobjects between the local maximum/minimum-points
//(I would call these keyframes, as that's what they really are in this sense!)
for (int i = 0; i < points.Length; i++){
//calculate the number of points
int points_since_keyframe = i%4;
if (points_since_keyframe == 0 && i < points.Length - 4)
{
//get current and next y
float current_y = points[i].transform.position.y;
float next_y = points[i+4].transform.position.y;
//calculate change in y
float y_delta = (next_y-current_y);
//calculate change in x (note: this is always 1, as we spaced our points 1 unit apart earlier!)
//float x_delta = points[i].transform.position.x-points[i+4].transform.position.x;
float x_delta = 1;
//gradient (a) is dy/dx
a = y_delta/x_delta;
//offset (b) is y position of first point
b = points[i].transform.position.y; //HOW TO RESET THIS?
}
if (points_since_keyframe != 0)
{
//we need to calculate how far we have moved since a and b were calculated (will be somewhere between 0.25 and 0.75)
//I'm pretty sure it'll be the remainder of the points since the key frame / 4, as that would mean that:
float x_delta = (float)points_since_keyframe / 4.0f;
//now that we know how far we've moved in x since we calculated a and b, we can use y=ax+b to get the new position
//proof for start/end points:
// after 0 points, we would have x_delta = 0, so y = 0*a+b = current_y in above logic
// after 4 points (assuming we didn't reset above), we would have x_delta = 1, so y = 1*a+b = next_y in above logic
float new_y = x_delta*a + b;
//now store the new y
Vector3 temp = points[i].transform.position;
temp.y = new_y;
points[i].transform.position = temp;
}
}
}
It's untested so might need some compile fixes, but is along the correct lines. Critically:
I'm doing almost exactly the same as you (in a slightly simpler way) to recalculate a and b every 4th point
However when using a and b, I am using the x distance travelled since the last key frame, not the overall x position
Hope that helps
-Chris
Thank you for the explicit answer Chris! It really helped solve my problem!
Answer by dhore · Dec 21, 2015 at 05:16 AM
You're already doing other calculations on every fourth iteration of i when you check if ((i % 4) == 0 ... )
So if you want to set b to 0 then just do b = 0;
instead of b = points[i].transform.position.y;
Your answer
Follow this Question
Related Questions
create graph editior for values 0 Answers
Get comments on Unity using Facebook Graph API 0 Answers
how do i read a node value in shader graph with c # code? 0 Answers
Emulating an X-Y oscilloscope? 1 Answer
,Code in loop simultaneously executing on members of array rather than iterating one at a time 1 Answer