How to arrange objects like in 'snake' in unity? - c#

the idea is how to align objects like in photo below, what formula need to use for this?
Now I can only do it this way, through sin or cos
void Start()
{
for (int i = 0; i < 50; i++)
characters.Add(Instantiate(characterPrefab, charactersParent));
}
// Update is called once per frame
void Update()
{
for (int i = 0; i < characters.Count; i++)
{
float x = Mathf.Cos(i * verticalLines * Mathf.PI / characters.Count) * horizontalRadius;
characters[i].GetComponent<RectTransform>().anchoredPosition = new Vector3(x, -i * (1920f / characters.Count), 0);
}
}

In snake your rewards/bug eated are added on the opposite direction that the last body-part is facing.
The problem here is how you stablish your current snake movement, to get the opposite direction.
Let's guess that your movement is x += 1, then your opposite position will be your X position on your characters[characters.Count] and go on the opposite direction x -=1.

Related

Why when instantiating objects they are in the air and not on ground?

The Circle part put the objects in the air.
How can i make that they will be on the ground ?
They are standing in the air. When using the square formation they are on ground but with the circle they are in the air.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle
}
public Transform squadMemeber;
public int columns = 4;
public int space = 10;
public int numObjects = 20;
// Use this for initialization
void Start()
{
ChangeFormation();
}
// Update is called once per frame
void Update()
{
}
private void ChangeFormation()
{
Formation formation = Formation.Square;
switch (formation)
{
/*case Formation.Square:
for (int i = 0; i < 23; i++)
{
Transform go = Instantiate(squadMemeber);
Vector3 pos = FormationSquare(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
}
break;*/
case Formation.Circle:
Vector3 center = transform.position;
for (int i = 0; i < numObjects; i++)
{
Vector3 pos = RandomCircle(center, 5.0f);
var rot = Quaternion.LookRotation(pos - center);
Instantiate(squadMemeber, pos, rot);
}
break;
}
}
Vector2 FormationSquare(int index) // call this func for all your objects
{
float posX = (index % columns) * space;
float posY = (index / columns) * space;
return new Vector2(posX, posY);
}
Vector3 RandomCircle(Vector3 center, float radius)
{
float ang = Random.value * 360;
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;
}
}
They should be instantiating on the ground(Terrain).
Need to position them on the ground.
Update:
This is what i tried now.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle
}
public Transform squadMemeber;
public int columns = 4;
public int space = 10;
public int numObjects = 20;
public float yOffset = 1;
// Use this for initialization
void Start()
{
ChangeFormation();
}
// Update is called once per frame
void Update()
{
}
private void ChangeFormation()
{
Formation formation = Formation.Circle;
switch (formation)
{
/*case Formation.Square:
for (int i = 0; i < 23; i++)
{
Transform go = Instantiate(squadMemeber);
Vector3 pos = FormationSquare(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
}
break;*/
case Formation.Circle:
Vector3 center = transform.position;
for (int i = 0; i < numObjects; i++)
{
Vector3 pos = RandomCircle(center, 5.0f);
var rot = Quaternion.LookRotation(pos - center);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
Instantiate(squadMemeber, pos, rot);
}
break;
}
}
Vector2 FormationSquare(int index) // call this func for all your objects
{
float posX = (index % columns) * space;
float posY = (index / columns) * space;
return new Vector2(posX, posY);
}
Vector3 RandomCircle(Vector3 center, float radius)
{
float ang = Random.value * 360;
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;
}
}
I added a offset yOffset and this two lines inside the for loop:
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
Now they are on the ground but lie down on the back/stomach and not standing like they were in the air.
Why when instantiating objects they are in the air and not on ground?
You need to find a way to calculate the height of the terrain then use that as your y-axis value.
After you get your pos, modify the y-axis with the Terrain.activeTerrain.SampleHeight function.
Vector3 pos = RandomCircle(center, 5.0f);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
Maybe add an offset depending on the type of the GameObject(The yOffset should be a float)
pos.y = pos.y + yOffset;
Now, go ahead and instantiate with that new pos:
var rot = Quaternion.LookRotation(pos - center);
Instantiate(squadMemeber, pos, rot);
Note:
Depending on the size of your character,you must and have to keep changing the value of the yOffset until you get the position you want. This position should work well for the-same character. If you want to do this to the GameObjects with different size, you also have to modify the yOffset until you are satisfied with it.
Not an actual answer, but some advice:
I see some basic problem here with your code being kind of confused anyway. There are some things that should be similar that aren't. I think the baseline here is that you need some basic structure.
First things first, you should start with identifying the basic parts you need here.
There are three basic things to resolve:
XY-position
Z-position
rotation
Last one is the issue with your characters lying on the ground. See the rotation by -90 degrees for the square? I assume that this one does this.
But a more pressing matter here, here is a question for you: Aside from the XY-position, what should be the difference between squares and circles? Answer: none. You treat both cases far more different than they should be. The code should look somewhat like this:
Position xyPosition;
switch (formation)
case Circle: xyPosition = randomCirclePosition(someargument)
case Square: xyPosition = randomSquarePosition(someargument)
Position position = rotateUpright(xyPosition)
position = adjustZ(position)
See how the difference is applied only at one part?
The thing that jumps to my eyes immediately are those signatures: Vector2 FormationSquare and Vector3 RandomCircle. In particular, Vector2 and Vector3. Those are two entirely different approaches. Why? This makes your code unnecessarily heterogeneous, makes it harder to read. Does not allow for the clear structure I wrote above. Why did you derive that much? Why didn't you copy the old code of the square and then adjusted it as needed?
Do I assume correct when I say that you copied the square code from the internet? And that you have troubles understanding it for some reason? Maybe because you are not familiar with the math behind it? If so, my "answer" is this: Take the square code and do not continue until you understand any single line it it. What it does, why it is needed, what happens without it. Perfectly fine if you simply go and outcomment lines, then look what happens in the engine. Or ask somebody. But it is most important that you understand every single line in the end.
You also might want to put the code on CodeReview when it is working. I see some issues here and there in style. Like the mysterious 23 that comes out of nothing.
Sorry if this sounded a little headstrong or the like, or if I misjudge the situation here.

How can I change position of instantiate objects (clones)?

I created a series of sphere clones in my game. After that I adapted the scale so that they appear smaller. However, now there is a gap between these spheres ... and I would have to change the position of this instatiate game objects. I changed my code already exactly at this position but nothing happens. So please I need your help! How can I do this? I would have very small spheres which are located near together.
Here the code:
using UnityEngine;
using System.Collections;
public class SineWave : MonoBehaviour {
private GameObject plotPointObject;
private int numberOfPoints= 100;
private float animSpeed =1.0f;
private float scaleInputRange = 8*Mathf.PI; // scale number from [0 to 99] to [0 to 2Pi] //Zahl vor Mathf, Anzahl Bön
private float scaleResult = 2.5f; // Y Achse Range
public bool animate = true;
GameObject[] plotPoints;
// Use this for initialization
void Start () {
if (plotPointObject == null) //if user did not fill in a game object to use for the plot points
plotPointObject = GameObject.CreatePrimitive(PrimitiveType.Sphere); //create a sphere
//add Material to the spheres , load material in the folder Resources/Materials
Material myMaterial = Resources.Load("Materials/green", typeof(Material)) as Material;
plotPointObject.GetComponent<MeshRenderer> ().material = myMaterial;
//change the scale of the spheres
//plotPointObject.transform.localScale = Vector3.one * 0.5f ;
plotPointObject.transform.localScale -= new Vector3(0.5f,0.5f,0.5f);
plotPoints = new GameObject[numberOfPoints]; //creat an array of 100 points.
//plotPointObject.GetComponent<MeshRenderer> ().material =Material.Load("blue") as Material
//plotPointObject.transform.localScale -= new Vector3 (0.5F, 0.5F, 0.5F); //neu: change the scale of the spheres
for (int i = 0; i < numberOfPoints; i++)
{
plotPoints[i] = (GameObject)GameObject.Instantiate(plotPointObject, new Vector3(i -
(numberOfPoints/2), 0, 0), Quaternion.identity); //this specifies
what object to create, where to place it and how to orient it
}
//we now have an array of 100 points- your should see them in the hierarchy when you hit play
plotPointObject.SetActive(false); //hide the original
}
Thank you already in advance!
Edit:
As I said in the comment I achieved now to place my spheres without a gap in between. However, as soon as I animate my spheres (with a sine wave) there is still that gap between the spheres. How can I adapt this? Should I copy the code of the Start function in the Update function?
I would be very happy to get some help. Thank you very much!
enter code here void Update()
{
for (int i = 0; i < numberOfPoints; i++)
{
float functionXvalue = i * scaleInputRange / numberOfPoints; // scale number from [0 to 99] to [0 to 2Pi]
if (animate)
{
functionXvalue += Time.time * animSpeed;
}
plotPoints[i].transform.position = new Vector3(i - (numberOfPoints/2), ComputeFunction(functionXvalue) * scaleResult, 0);
//print (plotPointObject.GetComponent<MeshRenderer> ().bounds.size.x);
// put the position information of sphere clone 50 in a vector3 named posSphere
posSphere = plotPoints [50].transform.position;
}
//print position of sphere 50 in console
//print (posSphere);
}
float ComputeFunction(float x)
{
return Mathf.Sin(x);
}
}
I think you could make the Barış solution.
For each new object that you are instantiating, you will set his position to the lasted instantiated position adding the size of the object itself, or whatever distance that you want they have from each other.
var initialPosition = 0;
var distanceFromEachOther = 20;
for (int i = 0; i < numberOfPoints; i++) {
var newPos = new Vector3(initialPosition + (i * distanceFromEachOther), 0, 0);
plotPoints[i] = (GameObject)GameObject.Instantiate(plotPointObject, newPos, Quaternion.identity);
}
That will make a gap between the spheres at X pivot, depending on their size. Change the distanceFromEachOther var, adjusting for your needs.
You could also get the object distance with plotPointObject.GetComponent<MeshRenderer>().bounds.size, so distanceFromEachOther could be, for example distanceFromEachOther = plotPointObject.GetComponent<MeshRenderer>().bounds.size.x + 5. So then you will have the objects with a perfectly distance of 5 from each other.
give this a try:
Transform objectToSpawn;
for (int i = 0; i < numberOfPoints; i++)
{
float someX = 200;
float someY = 200;
Transform t = Instantiate(objectToSpawn, new Vector3(i -(numberOfPoints/2), 0, 0), Quaternion.identity) as Transform;
plotPoints[i] = t.gameObject;
t.position = new Vector(someX, someY);
}

Generating a procedural tiled background

I'm trying to build a Shmup game with a tiled background, where I would like to make it procedure generated in the future.
But right now, I can't even make a static background. No matter what, I can't make the tiles fill the screen.
I'm using a tile of 64x64 pixels.
And here the code I'm using:
void Start()
{
m_screenHeight = 1408;
m_screenWidht = Camera.main.aspect * m_screenHeight;
float UnitsPerPixel = 1f / 100f;
Camera.main.orthographicSize = m_screenHeight / 2f * UnitsPerPixel;
m_horizontalTilesNumber = (int)Math.Floor(m_screenWidht / TileSize);
m_verticalTilesNumber = (int)Math.Floor(m_screenHeight / TileSize);
for (int i = 0; i < m_horizontalTilesNumber; i++)
{
for (int j = 0; j < m_verticalTilesNumber; j++)
{
Instantiate(Tile, Camera.main.ScreenToWorldPoint(new Vector3(TileSize * i, TileSize * j, 0)), Quaternion.identity);
}
}
}
Here is what It look likes:
Seems to me that I'm having some problem converting my pixel coordinates to Units, or something like this.
Any tips or directions here would be appreciated.
Try to use this code below:
/// <summary>
/// Tile prefab to fill background.
/// </summary>
[SerializeField]
public GameObject tilePrefab;
/// <summary>
/// Use this for initialization
/// </summary>
void Start()
{
if (tilePrefab.renderer == null)
{
Debug.LogError("There is no renderer available to fill background.");
}
// tile size.
Vector2 tileSize = tilePrefab.renderer.bounds.size;
// set camera to orthographic.
Camera mainCamera = Camera.main;
mainCamera.orthographic = true;
// columns and rows.
int columns = Mathf.CeilToInt(mainCamera.aspect * mainCamera.orthographicSize / tileSize.x);
int rows = Mathf.CeilToInt(mainCamera.orthographicSize / tileSize.y);
// from screen left side to screen right side, because camera is orthographic.
for (int c = -columns; c < columns; c++)
{
for (int r = -rows; r < rows; r++)
{
Vector2 position = new Vector2(c * tileSize.x + tileSize.x / 2, r * tileSize.y + tileSize.y / 2);
GameObject tile = Instantiate(tilePrefab, position, Quaternion.identity) as GameObject;
tile.transform.parent = transform;
}
}
}
You can find the whole demo project here: https://github.com/joaokucera/unity-procedural-tiled-background

Rotating enemy characters

I have a list of characters created in XNA C# as follows
for (int i = 0; i < GameConstants.NumDaleks; i++)
{
if (dalekList[i].isActive)
{
Vector3 line = dalekList[i].direction;
float rotationDal = (float)(Math.Atan2(dalekList[i].position.Y, dalekList[i].position.X) / (2 * Math.PI));
Matrix dalekTransform = Matrix.CreateScale(GameConstants.DalekScalar) * Matrix.CreateRotationY(rotationDal) * Matrix.CreateTranslation(dalekList[i].position);
DrawModel(mdlDalek, dalekTransform, mdDalekTransforms);
}
}
I'm trying to get characters to rotate to move in the direction they are facing. I believe this method is where I need to do but cannot figure out how to work out the angle require to go

applying direction to npc XNA

I have NPC's in my game that follow a script where they move randomly around the game. I would like them to face the direction they are moving in though.
for (int i = 0; i < GameConstants.NumDaleks; i++)
{
if (dalekList[i].isActive)
{
Vector3 line = dalekList[i].direction;
float rotationDal = (float)(Math.Atan2(dalekList[i].position.Y, dalekList[i].position.X) / (2 * Math.PI));
Matrix dalekTransform = Matrix.CreateScale(GameConstants.DalekScalar) * Matrix.CreateRotationY(rotationDal) * Matrix.CreateTranslation(dalekList[i].position);
DrawModel(mdlDalek, dalekTransform, mdDalekTransforms);
}
}
I'm sure it must be something to do with rotationDal, I have tried changing the calculation and the characters do seem to rotate differently, just not in their current direction
Xna has a built in function that you might find handy here.
Matrix.CreateWorld(positionVector, DirectionVector, UpVector);
here's the doc: http://msdn.microsoft.com/en-us/library/bb975261(v=xnagamestudio.40).aspx
In your case:
for (int i = 0; i < GameConstants.NumDaleks; i++)
{
if (dalekList[i].isActive)
{
Matrix dalekTransform = Matrix.CreateScale(GameConstants.DalekScalar) * Matrix.CreateWorld(dalekList[i].position, dalekList[i].direction, Vector3.Up);
DrawModel(mdlDalek, dalekTransform, mdDalekTransforms);
}
}

Categories

Resources