- Home /

# Rotation roadblock

Hi,

I'm trying to create a 3d endless driving game based on instantiating tiles/panels as the player drives around. I started with perlin noise but settled on a more basic random generator. I have made it so that the PanelManager detects what type of panel the current one is and instantiates PanelGenerators around it but I can't figure out how to rotate those new panels so that the starting point is at the endpoints of the first panel without completely screwing up the positioning or having to hard-code every variation.

I'm looking for advice on how to have the newly instantiated panels "look at" the current panel and rotate accordingly, this will allow for continuous panel generation in all directions but I just don't understand something about rotation in unity and would appreciate any guidance available.

Here are some pictures of what I have and what I want to have:

Here's the PanelGenerator code, please ignore the perlin noise stuff:

```
public class PanelGenerator : MonoBehaviour
{
//public Material whitemat;
//public GameObject[] buildings, shapes;
public GameObject cross, downT, rightT, leftT, grass, roadx, roadz; //cube, sphere, capsule, cylinder,
public int mapWidth = 20;
public int mapHeight = 20;
public float seed = 42, noisediv = 10, buildingfootprint = 20, perlinNoiseDivider =10;
public enum intersectionType { straight, cross, downT, rightT, leftT};
public intersectionType _intersectionType;
public enum areaType { city, town, woods, shops };
public areaType _areaType;
//mapgrid
int[,] mapgrid;
void Awake()
{
//MakeShapes();
QuadMaker();
}
void Start()
{
//QuadMaker();
//MapGridMaker();
//PerlinRun(mapWidth, mapHeight, seed, noisediv);
}
// Update is called once per frame
void Update()
{
}
public void QuadMaker()
{
//create new gameobject Panel
GameObject Panel = new GameObject();
Panel.transform.position = transform.position;
mapgrid = new int[mapWidth, mapHeight];
//generate new map data
for (int h = 0; h < mapHeight; h++)
{
for (int w = 0; w < mapWidth; w++)
{
//mapgrid[w, h] = (int)(Mathf.PerlinNoise(w / noisediv + seed, h / noisediv + seed) * perlinNoiseDivider);
mapgrid[w, h] = 2;
}
}
//build streets - randomly pick intersection
mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] = Random.Range(-3, -8);
//for testing
//mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)]= -7;
//Debug.Log(mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)]);
//build connecting streets
if (mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] < -6) //straight road
{
//continue straight
for (int rs = 0; rs < mapHeight; rs++)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2), rs] = -1;
//buildings/trees/etc. after grass along road
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 2, rs] = 1;
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, rs] = 1;
//grass along border of roads
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] = 0;
}
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] = 0;
}
}
}
else if (mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] < -5) //cross
{
//right at intersection
for (int rr = Mathf.RoundToInt(mapWidth / 2) + 1; rr < mapWidth; rr++)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2)] = -2;
//buildings/trees/etc. after grass along road
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 2] = 1;
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//grass along border of roads
if (mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 1] != 0)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 1] = 0;
}
if (mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 1] != 0)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 1] = 0;
}
}
//left at intersection
for (int rl = 0; rl < Mathf.RoundToInt(mapWidth / 2); rl++)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2)] = -2;
//buildings/trees/etc. after grass along road
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 2] = 1;
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//grass along border of roads
if (mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 1] != 0)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 1] = 0;
}
if (mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 1] != 0)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 1] = 0;
}
}
//continue straight
for (int rs = Mathf.RoundToInt(mapHeight / 2) + 1; rs < mapHeight; rs++)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2), rs] = -1;
//buildings/trees/etc. after grass along road
if (rs > Mathf.RoundToInt(mapWidth / 2) + 2)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 2, rs] = 1;
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, rs] = 1;
}
//grass along border of roads
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] = 0;
}
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] = 0;
}
}
}
else if (mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] < -4) //down
{
mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)+1] = 0;
mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//right at intersection
for (int rr = Mathf.RoundToInt(mapWidth / 2) + 1; rr < mapWidth; rr++)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2)] = -2;
//buildings/trees/etc. after grass along road
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 2] = 1;
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//grass
if (mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 1] != 0)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 1] = 0;
}
if (mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 1] != 0)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 1] = 0;
}
}
//left at intersection
for (int rl = 0; rl < Mathf.RoundToInt(mapWidth / 2); rl++)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2)] = -2;
//buildings/trees/etc. after grass along road
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 2] = 1;
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//grass along border of roads
if (mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 1] != 0)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 1] = 0;
}
if (mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 1] != 0)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 1] = 0;
}
}
}
else if (mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] < -3) //left
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, Mathf.RoundToInt(mapHeight / 2)] = 0;
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, Mathf.RoundToInt(mapHeight / 2)] = 1;
//left at intersection
for (int rl = 0; rl < Mathf.RoundToInt(mapWidth / 2); rl++)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2)] = -2;
//buildings/trees/etc. after grass along road
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 2] = 1;
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//grass
if (mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 1] != 0)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) - 1] = 0;
}
if (mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 1] != 0)
{
mapgrid[rl, Mathf.RoundToInt(mapHeight / 2) + 1] = 0;
}
}
//continue straight
for (int rs = Mathf.RoundToInt(mapWidth / 2) + 1; rs < mapHeight; rs++)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2), rs] = -1;
//buildings/trees/etc. after grass along road
if (rs > Mathf.RoundToInt(mapHeight / 2) + 2)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 2, rs] = 1;
}
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, rs] = 1;
//grass along border of roads
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] = 0;
}
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] = 0;
}
}
}
else if (mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] < -2) //right
{
mapgrid[Mathf.RoundToInt(mapWidth / 2)-1, Mathf.RoundToInt(mapHeight / 2)] = 0;
mapgrid[Mathf.RoundToInt(mapWidth / 2)-2, Mathf.RoundToInt(mapHeight / 2)] = 1;
//right at intersection
for (int rr = Mathf.RoundToInt(mapWidth / 2) + 1; rr < mapWidth; rr++)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2)] = -2;
//buildings/trees/etc. after grass along road
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 2] = 1;
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 2] = 1;
//grass along border of roads
if (mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 1] != 0)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) - 1] = 0;
}
if (mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 1] != 0)
{
mapgrid[rr, Mathf.RoundToInt(mapHeight / 2) + 1] = 0;
}
}
//continue straight
for (int rs = Mathf.RoundToInt(mapWidth / 2) + 1; rs < mapHeight; rs++)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2), rs] = -1;
//buildings/trees/etc. after grass along road
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 2, rs] = 1;
if (rs > Mathf.RoundToInt(mapHeight / 2) + 2)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, rs] = 1;
}
//grass along border of roads
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, rs] = 0;
}
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, rs] = 0;
}
}
}
//continue road
for (int r = 0; r < Mathf.RoundToInt(mapHeight / 2); r++) // road onto new tile
{
mapgrid[Mathf.RoundToInt(mapWidth / 2), r] = -1;
//buildings/trees/etc. after grass along road
if (r < Mathf.RoundToInt(mapHeight / 2) - 1 )
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 2, r] = 1;
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, r] = 1;
}
if (mapgrid[Mathf.RoundToInt(mapWidth/2), Mathf.RoundToInt(mapHeight/2)] ==-3)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 2, r] = 1;
}
if (mapgrid[Mathf.RoundToInt(mapWidth / 2), Mathf.RoundToInt(mapHeight / 2)] == -4)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 2, r] = 1;
}
//grass along border of roads
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, r] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) - 1, r] = 0;
}
if (mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, r] != 0)
{
mapgrid[Mathf.RoundToInt(mapWidth / 2) + 1, r] = 0;
}
}
//generate city
for (int h = 0; h < mapHeight; h++)
{
for (int w = 0; w < mapWidth; w++)
{
int result = mapgrid[w, h];
//make each position based on the width times the buildingfootprint and height(depth) times building footprint to make squares
Vector3 pos = new Vector3(w * buildingfootprint, 0, h * buildingfootprint);
//adjust position based on "pos" and height(depth) and width of each prefab
Vector3 adjustedpos = pos + transform.position;
//adjustedpos.x= pos.x +
adjustedpos.y = 0f;
//pick intersection and set type
//straight
if (result < -6)
{
_intersectionType = intersectionType.straight;
GameObject output = Instantiate(roadz, adjustedpos, roadz.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
//cross
else if (result < -5)
{
_intersectionType = intersectionType.cross;
GameObject output = Instantiate(cross, adjustedpos, cross.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
else if (result < -4)
{
_intersectionType = intersectionType.downT;
GameObject output = Instantiate(downT, adjustedpos, downT.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
else if (result < -3)
{
_intersectionType = intersectionType.leftT;
GameObject output = Instantiate(leftT, adjustedpos, leftT.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
else if (result < -2)
{
_intersectionType = intersectionType.rightT;
GameObject output = Instantiate(rightT, adjustedpos, rightT.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
//roads
else if (result < -1)
{
GameObject output = Instantiate(roadx, adjustedpos, roadx.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
else if (result < 0)
{
GameObject output = Instantiate(roadz, adjustedpos, roadz.transform.rotation) as GameObject;
output.transform.SetParent(Panel.transform);
}
//get result of perlin noise (1-10) and instantiate a prefab based on it
else if (result < 1)// roadside grass =0
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
output.transform.SetParent(Panel.transform);
//set enum of area type - concrete, sparse trees, etc for city - hedges, trees, etc for town
}
else if (result < 2)//buildings =1
{
//GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
//output.transform.SetParent(Panel.transform);
//set enum of area type - city, town (check for house and put garage of same array number), woods, farm (put field and barn behind), shops, police, factory, powerplant, military, scifi, park, etc
//rotate toward road
}
else if (result < 3) //foliage = 2
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
output.transform.SetParent(Panel.transform);
//set enum of area type - tree groups, rocks, hills, etc
}
else if (result < 4)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
else if (result < 5)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
else if (result < 6)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
else if (result < 7)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
else if (result < 8)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
else if (result < 9)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
else if (result < 10)
{
GameObject output = Instantiate(grass, adjustedpos, Quaternion.identity) as GameObject;
}
}
}
}
```

And here is the PanelManager (I realize I need to make it dependent on the current panel in the future):

```
public class PanelManager : MonoBehaviour
{
public List<GameObject> Panels;
public GameObject PanelGenerator, Player;
// Start is called before the first frame update
void Start()
{
MakePanels();
}
// Update is called once per frame
void Update()
{
}
public void MakePanels()
{
//change this to current panel once everything gets going and start with one
GameObject panel1 = Instantiate(PanelGenerator) as GameObject;
PanelGenerator pg = panel1.gameObject.GetComponent<PanelGenerator>();
Debug.Log(pg._intersectionType);
if (pg._intersectionType == global::PanelGenerator.intersectionType.straight)
{
//top
GameObject panel3 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x, 0, pg.transform.position.z + (pg.mapHeight * pg.buildingfootprint)), Quaternion.identity) as GameObject;
}
else if (pg._intersectionType == global::PanelGenerator.intersectionType.cross)
{
//left
GameObject panel2 = Instantiate(PanelGenerator, new Vector3 (pg.transform.position.x - (pg.mapWidth*pg.buildingfootprint), 0, pg.transform.position.z), Quaternion.identity) as GameObject;
//top
GameObject panel3 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x, 0, pg.transform.position.z+(pg.mapHeight * pg.buildingfootprint)), Quaternion.identity) as GameObject;
//right
GameObject panel4 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x + (pg.mapWidth * pg.buildingfootprint), 0, pg.transform.position.z), Quaternion.AngleAxis(90, Vector3.up)) as GameObject;
}
else if (pg._intersectionType == global::PanelGenerator.intersectionType.downT)
{
//left
GameObject panel2 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x - (pg.mapWidth * pg.buildingfootprint), 0, pg.transform.position.z), Quaternion.identity) as GameObject;
//right
GameObject panel4 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x + (pg.mapWidth * pg.buildingfootprint), 0, pg.transform.position.z), Quaternion.AngleAxis(90, Vector3.up)) as GameObject;
}
else if (pg._intersectionType == global::PanelGenerator.intersectionType.leftT)
{
//left
GameObject panel2 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x - (pg.mapWidth * pg.buildingfootprint), 0, pg.transform.position.z), Quaternion.identity) as GameObject;
//top
GameObject panel3 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x, 0, pg.transform.position.z + (pg.mapHeight * pg.buildingfootprint)), Quaternion.identity) as GameObject;
}
else if (pg._intersectionType == global::PanelGenerator.intersectionType.rightT)
{
//top
GameObject panel3 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x, 0, pg.transform.position.z + (pg.mapHeight * pg.buildingfootprint)), Quaternion.identity) as GameObject;
//right
GameObject panel4 = Instantiate(PanelGenerator, new Vector3(pg.transform.position.x + (pg.mapWidth * pg.buildingfootprint), 0, pg.transform.position.z), Quaternion.AngleAxis(90, Vector3.up)) as GameObject;
}
}
}
```

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.

### Follow this Question

### Related Questions

How can I rotate my player with a Joystick? 0 Answers

How to make a player rotate in a direction with a slope of the ground. 0 Answers

How to rotate camera around 3D object without breaking camera rotation 0 Answers

On Finger Touch and Drag Rotate 3D Ball 1 Answer

How to make a bone rotate facing towards a given Transform? 0 Answers