Drawing a Turkey in unity2d using Verlet method - c#

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;
}
}

Related

For some reason when I reactivate objects in my object pool they are static?

I'm currently working on a game and I ran into a small issue. I'm currently trying to create an object pool for objects that will reappear constantly in my game in order to improve the framerate of my game. However when creating this object pool whenever the game starts and the pool of objects is created and then activated and then deactivated and then reactivated again the game objects always get reactivated in a static state. I've tried going through my code to find out where this problem might be coming from but I have no Idea. All the reactivated game objects have rigidbodys and the proper tags.
Ive tried going trough all the different classes which might be creating this problem but I haven't found anything out of the ordinary myself.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnPoint: MonoBehaviour
{
public Transform SpawnPoints;
public GameObject[] interact;
List<float> StarPositions = new List<float>();
int Interact;
int index = 1;
public int pooledAmount = 40;
List<GameObject> colouredBalls;
public static bool spawnAllowed;
public static int count = 0;
public void Start()
{
colouredBalls = new List<GameObject>();
for (int c = 0; c < pooledAmount; c++)
{
GameObject obj = (GameObject)Instantiate(interact[0]);
obj.SetActive(false);
colouredBalls.Add(obj);
}
if (ScoreScript.scoreValue < 5)
{
Vector2 pos = Camera.main.WorldToViewportPoint(transform.position);
for (int x = 1; x < 5; x++)
{
//Vector3 SpawnPos = spawnPoints[d].position;
int NrSpawnpoints = 4;
int NrSpaces = NrSpawnpoints + 1;
double Xlegnth = 1.0;
double spawnPosX = x * Xlegnth / NrSpaces;
pos.x = (float)spawnPosX;
pos.y = 1.3f;
Vector2 Posi = Camera.main.ViewportToWorldPoint(pos);
Instantiate(SpawnPoints, Posi, Quaternion.identity);
//Debug.Log(Posi);
}
}
spawnAllowed = true;
InvokeRepeating("SpawnAInteract", 0f, 1f);
}
void SpawnAInteract()
{
if (spawnAllowed)
{
int randomSpawnPoint;
Vector2 pos = Camera.main.WorldToViewportPoint(transform.position);
//Vector2 starpos = Camera.main.WorldToViewportPoint(transform.position);
if (index % 10 != 0)
{
for (int d = 1; d < 5; d++)
{
//Vector3 SpawnPos = spawnPoints[d].position;
int NrSpawnpoints = 4;
int NrSpaces = NrSpawnpoints + 1;
double Xlegnth = 1.0;
double spawnPosX = d * Xlegnth / NrSpaces;
pos.x = (float)spawnPosX;
pos.y = 1.3f;
Vector2 Posi = Camera.main.ViewportToWorldPoint(pos);
if (!colouredBalls[d].activeInHierarchy)
{
colouredBalls[d].transform.position = Posi;
colouredBalls[d].transform.rotation = transform.rotation;
colouredBalls[d].SetActive(true);
//Debug.Log("Nr active Balls:" + f + colouredBalls[f].activeInHierarchy);
Debug.Log("Nr active Balls:" + d + colouredBalls[d].activeInHierarchy);
count++;
break;
}
}
index++;
}
else
{
for (int d = 1; d < 5; d++)
{
int NrSpawnpoints = 4;
int NrSpaces = NrSpawnpoints + 1;
double Xlegnth = 1.0;
double spawnPosX = d * Xlegnth / NrSpaces;
pos.x = (float)spawnPosX;
pos.y = 1.3f;
Vector2 Posi = Camera.main.ViewportToWorldPoint(pos);
StarPositions.Add((float)spawnPosX);
//Debug.Log("Starpositions " + StarPositions.ToString());
//edit this
double StarPos = spawnPosX - Xlegnth / NrSpaces / 2;
//Change to a list
//Debug.Log("Star " + d);
StarPositions[d - 1] = (float)StarPos;
}
//edit this to make the star appear at the StarPosition directly to the left or to the right of the WhiteBall
Vector2 Start = new Vector2(0, 0);
Vector2 StartCon = Camera.main.ViewportToWorldPoint(Start);
float whiteBallX = GameObject.FindWithTag("White Ball").transform.position.x;
for (int d = 1; d < 5; d++)
{
if (whiteBallX >= StartCon.x && whiteBallX <= StarPositions[d - 1])
{
int[] potentialStarPositions = { d, d + 2 };
int positionIndex = Random.Range(0, 2);
int randomSpawnPoin = potentialStarPositions[positionIndex];
pos.x = StarPositions[randomSpawnPoin];
pos.y = 1.3f;
Vector2 StarPosi = Camera.main.ViewportToWorldPoint(pos);
Interact = 1;
Instantiate(interact[Interact], StarPosi, Quaternion.identity);
break;
}
}
index++;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectDestroy: MonoBehaviour
{
public Transform CameraCollider;
int NonActive = 0;
void Start()
{
Vector3 ScreenSize = new Vector3(1.5f, 1.5f, 1.5f);
Vector3 ScreenSizeAdj = Camera.main.ViewportToWorldPoint(ScreenSize);
CameraCollider.localScale = ScreenSizeAdj;
Vector3 ScreenPos = new Vector3(0.5f, 0.5f, 0);
Vector3 ScreenPosAdj = Camera.main.ViewportToWorldPoint(ScreenPos);
Instantiate(CameraCollider, ScreenPosAdj, Quaternion.identity);
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.CompareTag("ColouredBall Highress") || other.gameObject.CompareTag("Star"))
{
other.gameObject.SetActive(false);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InteractControl : MonoBehaviour
{
Rigidbody2D rb;
GameObject target;
float moveSpeed;
Vector3 directionToTarget;
Renderer m_Renderer;
void Start()
{
target = GameObject.Find("White Ball");
rb = GetComponent<Rigidbody2D>();
moveSpeed = 3f; //Movement speed of all the obstacles and powerups
MoveInteract(); //Method responsable for the movement of the obstacles and powerups, gets called at start
}
void MoveInteract() //Method responsable for the movement of the obstacles and stars
{
if (target != null)
{
if(ScoreScript.scoreValue > 5) //Determine when RedBall goes from going down in a straigh line to following white ball
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
else //Red Ball goes down in a straigh line
{
directionToTarget = new Vector3(0, -1, 0);
rb.velocity = new Vector2(0, directionToTarget.y * moveSpeed);
}
}
else
rb.velocity = Vector3.zero;
}
}
This is normal, when you deactivate an object the velocity resets. You must save their velocity before deactivating then set it again when reactivated.
I would look for other kind of optimization, this makes code more complex and probably there are better ways of optimizing it.
Edit: A quick solution would be to deactivate the sprite renderer, instead of the whole game object. This would optimize gpu load which I guess is the problem.

How can I prevent from adding more and more new objects when pressing F to change formation?

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle, Triangle
}
[Header("Main Settings")]
[Space(5)]
public Transform squadMemeberPrefab;
[Range(4, 100)]
public int numberOfSquadMembers = 20;
[Range(1, 20)]
public int numberOfSquads = 1;
[Range(0, 4)]
public int columns = 4;
public int gaps = 10;
public int circleRadius = 10;
public float yOffset = 0;
[Range(3, 50)]
public float moveSpeed = 3;
[Range(3, 50)]
public float rotateSpeed = 1;
public float threshold = 0.1f;
public bool randomSpeed = false;
[Range(1, 100)]
public int randSpeedMin = 1;
[Range(1, 100)]
public int randSpeedMax = 1;
public bool startRandomFormation = false;
public string currentFormation;
private Formation formation;
private List<Quaternion> quaternions = new List<Quaternion>();
private List<Vector3> newpositions = new List<Vector3>();
private bool move = false;
private bool squareFormation = false;
private List<GameObject> squadMembers = new List<GameObject>();
private float[] step;
private int[] randomSpeeds;
private int index = 0;
private int numofobjects = 0;
// Use this for initialization
void Start()
{
numofobjects = numberOfSquadMembers;
if (startRandomFormation)
{
formation = (Formation)UnityEngine.Random.Range(0, Enum.GetNames(typeof(Formation)).Length);
}
else
{
formation = Formation.Square;
}
currentFormation = formation.ToString();
ChangeFormation();
foreach (Transform child in gameObject.transform)
{
if (child.tag == "Squad Member")
squadMembers.Add(child.gameObject);
}
randomSpeeds = RandomNumbers(randSpeedMin, randSpeedMax, squadMembers.Count);
step = new float[squadMembers.Count];
}
// Update is called once per frame
void Update()
{
if (numofobjects != numberOfSquadMembers)
{
numofobjects = 0;
numofobjects = numberOfSquadMembers;
squadMembers = new List<GameObject>();
FormationSquare();
}
if (Input.GetKeyDown(KeyCode.F))
{
randomSpeeds = RandomNumbers(randSpeedMin, randSpeedMax, squadMembers.Count);
foreach (int speedV in randomSpeeds)
{
if (index == randomSpeeds.Length)
index = 0;
step[index] = speedV * Time.deltaTime;
index++;
}
ChangeFormation();
}
if (move == true)
{
MoveToNextFormation();
}
}
private void ChangeFormation()
{
switch (formation)
{
case Formation.Square:
FormationSquare();
break;
case Formation.Circle:
FormationCircle();
break;
}
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * gaps;
float posY = (index / columns) * gaps;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
newpositions = new List<Vector3>();
quaternions = new List<Quaternion>();
Transform go = squadMemeberPrefab;
for (int i = 0; i < numofobjects; i++)
{
if (squadMembers.Count == 0)
go = Instantiate(squadMemeberPrefab);
Vector3 pos = FormationSquarePositionCalculation(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
go.tag = "Squad Member";
go.transform.parent = gameObject.transform;
newpositions.Add(go.transform.position);
}
move = true;
squareFormation = true;
formation = Formation.Circle;
}
private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
{
float ang = index * angleIncrement;
Vector3 pos;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = center.y;
return pos;
}
private void FormationCircle()
{
newpositions = new List<Vector3>();
quaternions = new List<Quaternion>();
Vector3 center = transform.position;
float radius = (float)circleRadius / 2;
float angleIncrement = 360 / (float)numberOfSquadMembers;
for (int i = 0; i < numberOfSquadMembers; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpositions.Add(pos);
quaternions.Add(rot);
}
move = true;
squareFormation = false;
formation = Formation.Square;
}
private void MoveToNextFormation()
{
if (randomSpeed == false)
{
if (step.Length > 0)
step[0] = moveSpeed * Time.deltaTime;
}
for (int i = 0; i < squadMembers.Count; i++)
{
squadMembers[i].transform.LookAt(newpositions[i]);
if (randomSpeed == true)
{
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpositions[i], step[i]);
}
else
{
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpositions[i], step[0]);
}
if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) < threshold)
{
if (squareFormation == true)
{
Vector3 degrees = new Vector3(0, 0, 0);
Quaternion quaternion = Quaternion.Euler(degrees);
squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternion, rotateSpeed * Time.deltaTime);
}
else
{
squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternions[i], rotateSpeed * Time.deltaTime);
}
}
}
}
private static int[] RandomNumbers(int min, int max, int howMany)
{
int[] myNumbers = new int[howMany];
for (int i = 0; i < howMany; i++)
{
myNumbers[i] = UnityEngine.Random.Range(min, max);
}
return myNumbers;
}
}
In the constructor I'm searching for childs with the tag Squad Member.
But the List squadMembers will be empty since the script is attached to a new empty GameObject without any childs.
Then also the variable step will be empty.
Then inside the method MoveToNextFormation I'm checking if step is empty or not:
if (step.Length > 0)
step[0] = moveSpeed * Time.deltaTime;
If not checking the it will throw exception since there is nothing at index 0 it's null. But then if step is empty there will be no speed/s at all for the objects movements.
That's one problem.
I'm not sure even why in the constructor I did the part with the children and the "Squad Member" tag. I'm not creating yet any children with this tag so I'm confused about what I tried to do in the constructor.
The second problem is in this lines in the FormationSquare method:
if (squadMembers.Count == 0)
go = Instantiate(squadMemeberPrefab);
But if squadMembers is empty then it will throw exception somewhere else in other places in the code. And I'm creating new objects inside the FormationSquare method that's since I'm starting by default with the FormationSquare but what if I want to start by default with the FormationCircle method ?
The idea is to start with minimum (1) number of squads and with minimum (4) number of members in the squad when starting the program. Or to start with any range between min and max. But it's all messed up.
In your case, I would separate the squad member prefab instantiation from the squad shape formatting, doing this will help you identify your bug.
For example add the following methods and use them during 'Start':
void AddSquadMember()
{
// Use this to instantiate/spawn a new game object prefab.
}
void AddSquadMember(GameObject object)
{
// Use this for game object already in the scene. (.eg the children with your tag)
}
Then on the formation methods remove the intantiate calls and just use whatever game object you have in the list.
Finally, I would toss the 'numofobjects' variable. Then use 'squadMembers.Count' instead of both 'numofobjects' and 'numberOfSquadMembers' assuming that during 'Start' you have taken care of instantiating all game objects in order to 'numberOfSquadMembers == squadMembers.Count'. That is because you might need to raise the squad with a few more members during gameplay.

How can i check when the object MoveTowards has reached to the new position and then rotate it?

private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position = Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
//squadMembers[i].transform.rotation = qua[i];
}
}
And calling it in the Update:
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ChangeFormation();
}
if (move == true)
MoveToNewFormation();
}
Once when one of the squadMembers reached to the newpos then i want to make
squadMembers[i].transform.rotation = qua[i];
qua is a List and i want to rotate the squad member once he reached the newpos.
Inside MoveToNewFormation i thought to add after the loop the line:
if (squadMembers[i].transform.position == newpos[i])
{
squadMembers[i].transform.rotation = qua[i];
}
But it's after the loop so 'i' not exist.
This is the complete script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle, Triangle
}
public Transform squadMemeber;
public int columns = 4;
public int squareSpace = 10;
public int circleSpace = 40;
public int numberOfObjects = 20;
public float yOffset = 0;
public float speed = 3;
private Formation formation;
private GameObject[] squadMembers;
private List<Quaternion> qua = new List<Quaternion>();
private List<Vector3> newpos = new List<Vector3>();
private bool move = false;
// Use this for initialization
void Start()
{
formation = Formation.Square;
ChangeFormation();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ChangeFormation();
}
if (move == true)
MoveToNewFormation();
}
private void ChangeFormation()
{
switch (formation)
{
case Formation.Square:
FormationSquare();
break;
case Formation.Circle:
FormationCircle();
break;
}
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * squareSpace;
float posY = (index / columns) * squareSpace;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
for (int i = 0; i < numberOfObjects; i++)
{
Transform go = Instantiate(squadMemeber);
Vector3 pos = FormationSquarePositionCalculation(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
go.tag = "Squad Member";
}
formation = Formation.Circle;
}
private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
{
float ang = index * angleIncrement;
Vector3 pos;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = center.y;
return pos;
}
private void FormationCircle()
{
Vector3 center = transform.position;
float radius = (float)circleSpace / 2;
float angleIncrement = 360 / (float)numberOfObjects;
for (int i = 0; i < numberOfObjects; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpos.Add(pos);
qua.Add(rot);
}
move = true;
formation = Formation.Square;
}
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position = Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
//squadMembers[i].transform.rotation = qua[i];
}
//if (squadMembers[i].transform.position == newpos[i])
}
}
You can use a threshold and check the distance using that threshold.
Define threshold like this at start of script.
public float threshold = 0.1f;
Then change the MoveToNewFormation() function like this:
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
if(Vector3.Distance(squadMembers[i].transform.position,newpos[i])<threshold){
squadMembers[i].transform.rotation = qua[i];
}
}
//if (squadMembers[i].transform.position == newpos[i])
}

3D infinite runner game platform generation gives an exception

Situation: I am referring to tutorial for my project,and there is an object pooling concept within the code.
Problem: What happens is , after I scripting the generation platform(PlatformManager.cs), I get an exceptions saying,
InvalidOperationException: Operation is not valid due to the current
state of the object
System.Collections.Generic.Queue`1[UnityEngine.Transform].Peek ()
PlatformManager.Update () (at Assets/Platform/PlatformManager.cs:35)
PlatformManager.cs script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PlatformManager : MonoBehaviour {
public Transform prefab;
public int numberOfObjects;
public float recycleOffset;
public Vector3 startPosition;
public Vector3 minSize, maxSize,minGap, maxGap;
public float minY, maxY;
private Vector3 nextPosition;
private Queue<Transform> objectQueue;
void Start () {
objectQueue = new Queue<Transform>(numberOfObjects);
for (int i = 0; i < numberOfObjects; i++) {
objectQueue.Enqueue((Transform)Instantiate(prefab));
}
nextPosition = startPosition;
for (int i = 0; i < numberOfObjects; i++) {
Transform o = (Transform)Instantiate(prefab);
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
}
}
void Update () {
if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)//THIS IS THE 35TH LINE WHICH CAUSE THE ERROR
{
Transform o = objectQueue.Dequeue();
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
Recycle();
}
}
private void Recycle () {
Vector3 scale = new Vector3(
Random.Range(minSize.x, maxSize.x),
Random.Range(minSize.y, maxSize.y),
Random.Range(minSize.z, maxSize.z));
Vector3 position = nextPosition;
position.x += scale.x * 0.5f;
position.y += scale.y * 0.5f;
Transform o = objectQueue.Dequeue();
o.localScale = scale;
o.localPosition = position;
nextPosition.x += scale.x;
objectQueue.Enqueue(o);
nextPosition += new Vector3(
Random.Range(minGap.x, maxGap.x) + scale.x,
Random.Range(minGap.y, maxGap.y),
Random.Range(minGap.z, maxGap.z));
if(nextPosition.y < minY){
nextPosition.y = minY + maxGap.y;
}
else if(nextPosition.y > maxY){
nextPosition.y = maxY - maxGap.y;
}
}
}
Thanks in advance.
Make sure the queue is not empty.
if(objectQueue.Count != 0)
{
if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)//THIS IS THE 35TH LINE WHICH CAUSE THE ERROR
{
Transform o = objectQueue.Dequeue();
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
Recycle();
}
}

How to rotate two game objects together?

I have a game where you need to rotate clocks.I cant figure out how to rotate two or more clock arrows toghether.Arrows are not on the same clock.Arrows have diffrent rotations and they have to keep their rotation diffrences.I.E one arrow is 180 another 90 so after 90 degree turn fist one should be 270 and another one 180.Here is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MoveClock : MonoBehaviour
{
public GameObject root;
public Transform arrow;
public CircleCollider2D circleCollider;
public BoxCollider2D boxColliderTrigger;
public List<MoveClock> connectedClocks;
public GameManger gameManager;
public BoxCollider2D[] colliders;
public int n;
public BoxCollider2D[] disabledTriggers;
public bool equal;
const float initialValue = 90;
static public int k;
public float angle;
public float snapAngle;
public float dif;
public Vector3 mousepos;
public Vector3 dir;
public int[] zAngles;
void Start()
{
zAngles = new int[n];
SetAngles();
CalculateDiffrence();
}
void Update()
{
}
public void MoveArrow(out float snapAngle)
{
snapAngle = 0;
if (Input.GetMouseButton(0))
{
mousepos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
dir = transform.position - mousepos;
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + initialValue;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
snapAngle = SnapAngle(angle);
SetAngleTo(angle);
}
}
private void SetAngles()
{
int angle = 360 / n;
for (int i = 0; i < n; i++)
{
zAngles[i] = angle * i;
}
}
private float SnapAngle(float target)
{
float minDiffrence = float.MaxValue;
float closest = float.MaxValue;
for (int i = 0; i < zAngles.Length; i++)
{
float diff = Mathf.Abs(zAngles[i] - target);
if (minDiffrence > diff)
{
minDiffrence = diff;
closest = zAngles[i];
}
}
return closest;
}
public void SetAngleTo(float a)
{
for (int i = 0; i < connectedClocks.Count; i++)
{
if(equal==true)
connectedClocks[i].arrow.rotation = Quaternion.AngleAxis(a, Vector3.forward);
else
connectedClocks[i].arrow.rotation = Quaternion.AngleAxis(a + connectedClocks[i].dif, Vector3.forward);
}
}
public void CalculateDiffrence()
{
for (int i = 0; i < connectedClocks.Count; i++)
{
Vector3 dir = connectedClocks[i].transform.position - transform.position;
dir = connectedClocks[i].transform.InverseTransformDirection(dir);
dif = SnapAngle(Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg+initialValue);
Debug.Log(string.Format("{0} {1}", dif, connectedClocks[i].circleCollider.name));
}
}
}
Simply put one of the object as the child of another, that will do.
A //or B
|__B // |__A
Or programmatically:
A.transform.parent = B.transform; //or
A.transform.SetParent(B.transform);
In this setting, if you rotate A any angles, B will follow and no need to calculate and keep their angle difference in code.

Categories

Resources