This is a homework problem(Do not copy, copy is not smart): We need to draw a 2d turkey in unity 2d using Verlet method to update the positions of the vertices. However, We don't know the forces involved to trace the Turkey. Here is a picture of the Turkey. Is there a trick?
Here is the codes that we started:
public class GenerateTurkeys : MonoBehaviour
{
LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
// Start is called before the first frame update
int numberOfTurkeys;
int NUM_PARTICLES;
float fTimeStep;
Vector3[] m_position = new Vector3[NUM_PARTICLES];
Vector3[] m_acceleration = new Vector3[NUM_PARTICLES];
Vector3[] m_oldPosition = new Vector3[NUM_PARTICLES];
void Start()
{
NUM_PARTICLES = 100;
numberOfTurkeys = 0;
}
// Verlet integration step void ParticleSystem::
Verlet()
{
for (int i=0; i<NUM_PARTICLES; i++)
{
Vector3 x = m_position[i];
Vector3 temp = x;
Vector3 oldx = m_oldPosition[i];
Vector3 a = m_acceleration[i];
x += x-oldx+a* fTimeStep*fTimeStep;
oldx = temp;
}
}
void DrawLine(float[] heights)
{
LineRenderer lineRenderer = GetComponent<LineRenderer>();
var t = Time.time;
for (int i = 0; i < NUM_PARTICLES; i++)
{
lineRenderer.SetPosition(i, );
}
}
// Update is called once per frame
void Update()
{
}
}
I'm not sure that I correctly decided, due to the fact that the contour does not match, but in the solution the speed is exactly iterative. I think this is a small error of physics in Unity, Because if you use the resulting accelerations, you can draw the graph very accurately.
Here is code:
public class Drawer : MonoBehaviour
{
[SerializeField]
private Transform[] m_Dots;
private Rigidbody2D m_Dot;
private Vector2[] m_Acceler;
float deltaT = 0.5f;//for example
private void Start()
{
m_Acceler = GetAcceler();
var go = new GameObject("Tracer");
var tr = go.AddComponent<TrailRenderer>();
tr.widthMultiplier = 0.1f;
tr.time = 50f;
m_Dot = go.AddComponent<Rigidbody2D>();
m_Dot.bodyType = RigidbodyType2D.Kinematic;
m_Dot.gravityScale = 0;
StartCoroutine(VerletCoroutine());
}
private Vector2[] GetAcceler()
{
Vector2[] result = new Vector2[m_Dots.Length];
float T = deltaT;
int len = m_Dots.Length;
result[0] = An(m_Dots[1].position, m_Dots[0].position, m_Dots[0].position, T);
for (int i = 1 ; i < len - 1 ; i++, T += deltaT)
{
result[i] = An(m_Dots[i + 1].position, m_Dots[i].position, m_Dots[i].position, T);
}
result[len - 1] = An(m_Dots[0].position, m_Dots[len - 1].position, m_Dots[len - 1].position, T);
return result;
}
private Vector2 An(Vector2 Xnext, Vector2 Xn, Vector2 Xprev, float t)
{// a[n] = (x[n+1] - 2*x[n]+x[n-1])/t^2
return (Xnext - 2 * Xn + Xprev) / t * t;
}
private IEnumerator VerletCoroutine()
{
m_Dot.transform.position = m_Dots[0].position;
Vector2 Vprev = Vector2.zero;
int len = m_Acceler.Length - 1;
float t = 0;
int i = 0;
while (true)
{
t += Time.deltaTime;
if (t >= deltaT)
{
i++;
if (i > len)
{
break;
}
t = 0;
Vprev = Vector2.zero;
}
Vprev = Vnext(Vprev, m_Acceler[i], m_Acceler[i], t);
m_Dot.velocity = Vprev;
yield return new WaitForEndOfFrame();
}
m_Dot.velocity = Vector3.zero;
yield return null;
}
private Vector2 Vnext(Vector2 Vn, Vector2 Anext, Vector2 An, float t)
{//v[n+1]= v[n]+0,5(a[n+1] +a[n]) * t
var v = Vn + 0.5f * (Anext + An) * t;
return v;
}
}