i am trying to generate some islands in a 2d game in unity using this code:
public class terraingen : MonoBehaviour
{
int generate = 10;
public int distance = 5;
int i;
void Start()
{
for (i = 1; i <= generate; i++)
{
float x = transform.position.x;
float a = x + distance;
transform.position = new Vector3(a, 2, 0);
Instantiate(gameObject);
}
}
}
now the problem is when i enter play mode because it doesnt load, i mean it only shows "Hold up(busy for mins:sec)" and the time it is "busy" never ends.
i tried using other codes from the internet but none worked, some had the same result and others just didnt work
Related
I have created a script who will spawn objects and give tag and color for one element of prefab. But script not working with clones. This 2 scripts, GameManager( he must spawn objects) and
RandomTagAndColor( he give to element of prefab tag and name). And in scene of game, where objects is spawning, script give tag and colour only to first prefab. In game those prefabs 10. Well, I'm sorry if question is stupid, this first thing, what i doing without books,guides.
GameManager script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GameManager : MonoBehaviour
{
// Start is called before the first frame update
public GameObject firstBarrier;
public GameObject secondBarrier;
public int numOfBarriers = 0;
System.Random rnd = new System.Random();
System.Random rndY = new System.Random();
Vector3 vector = new Vector3(5, 1/3 , 1);
void Start()
{
for (numOfBarriers = 0; numOfBarriers < 10; numOfBarriers++)
{
int ewq = rnd.Next(1, 20);
int rY = rndY.Next(1, 4);
if(ewq <= 10)
{
Instantiate(firstBarrier, vector, Quaternion.identity);
}
else
{
Instantiate(secondBarrier, vector, Quaternion.identity);
}
vector.x -= 7;
vector.y = rY;
}
}
void Update()
{
}}
RandomColorAndTag script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class RandomColorAndTag : MonoBehaviour
{
GameObject Bar;
System.Random randomElement = new System.Random();
int el = 0 ;
void Start()
{
el = randomElement.Next(2, 6);
GameObject.Find($"Cube ({el})").GetComponent<Renderer>().material.color = Color.green;
if (GameObject.Find($"Cube ({el})").GetComponent<Renderer>().material.color == Color.green)
{
GameObject.Find($"Cube ({el})").transform.tag = "Green";
}
}
void Update()
{
}
}
As mentioned there are lot of unclear issues in your codes.
I will assume the RandomColorAndTag is attached to the objects you spawn. In that case don't use Find but rather simply assign the random color and tag to yourself
what is a random value between 1 and 19 good for, of all you ever do with it is check whether it is bigger or smaller than 10? => Simply use only a random 0 or 1 and check whether it is 0 ;)
I'm unsure exactly what items should be green now .. I assume among the 10 spawned items you want to pick one and make it special..
finally I wouldn't even let the objects assign their own tag and color but let the GameManager trigger it
So I would do something like
public class GameManager : MonoBehaviour
{
public TagAndColorController fortBarrier;
public TagAndColorController secondBarrier;
public int numOfBarriers = 10;
public Vector3 vector = new Vector3(5, 1f/3f , 1);
public Color specialColor = Color.Green;
public string specialTag = "Green";
private void Start()
{
var specialIndex = Random.Range(0, numberOfBarriers);
for (var i = 0; i < numOfBarriers; i++)
{
// upper bound is exclusive -> this returns 0 or 1
var rndBarrier = Random.Range(0, 2);
// not sure if intended but again: upper bound is exclusive -> this return 1, 2, or 3
var rY = Random.Range(1, 4);
var tagAndColor = Instantiate(rndBarrier == 0 ? firstBarrier : secondBarrier, vector, Quaternion.identity);
if(i == numberOfBarriers)
{
tagAndColor.SetColorAndTag(specialColor, specialTag);
}
vector.x -= 7;
vector.y = rY;
}
}
}
And the other script has no logic whatsoever but rather only is a quick access to the objects renderer and bundles the behavior
public class TagAndColorController : MonoBehaviour
{
[SerializeField] private Renderer _renderer;
public void SetColorAndTag(Color newColor, string newTag)
{
gameObject.tag = newTag;
if(!_renderer) _renderer = GetComponent<Renderer>();
_renderer.material.color = newColor;
}
}
I am generating gameobjects (spheres) based on coordinates, which are stored in a .csv file. I have a Gameobject with a Single Sphere as primitive childobject. Based on the data the Object will clone this sphere 17 times and move them around. I can move the whole thing around like i want it to by accessing the parent object, but in editing mode the position of the root sphere makes it uneasy to use.
The following Code makes this possible.
public GameObject parentObj;
public TextAsset csvFile;
[SerializeField]
private float scaleDownFactor = 10;
private int index = 0;
//class Deck : MonoBehaviour
//{
[SerializeField]
private GameObject[] deck;
private GameObject[] instanciatedObjects;
private void Start()
{
Fill();
}
public void Fill()
{
instanciatedObjects = new GameObject[deck.Length];
for (int i = 0; i < deck.Length; i++)
{
instanciatedObjects[i] = Instantiate(deck[i]) as GameObject;
}
}
//}
// Update is called once per frame
void Update()
{
readCSV();
}
void readCSV()
{
string[] frames = csvFile.text.Split('\n');
int[] relevant = {
0
};
string[] coordinates = frames[index].Split(',');
for (int i = 0; i < 17; i++)
{
float x = float.Parse(coordinates[relevant[i] * 3]) / scaleDownFactor;
float y = float.Parse(coordinates[relevant[i] * 3+1]) / scaleDownFactor;
float z = float.Parse(coordinates[relevant[i] * 3+2]) / scaleDownFactor;
//objectTest.transform.Rotate(float.Parse(fields[1]), float.Parse(fields[2]), float.Parse(fields[3]));
//objectTest.transform.Translate(x, y, z);
//parentObj.transform.position = new Vector3(x, y, z);
instanciatedObjects[i].transform.position = new Vector3(parentObj.transform.position.x, parentObj.transform.position.y, parentObj.transform.position.z);
instanciatedObjects[i].transform.eulerAngles = new Vector3(parentObj.transform.eulerAngles.x, parentObj.transform.eulerAngles.y, parentObj.transform.eulerAngles.z);
//instanciatedObjects[i].transform.position = new Vector3(x, y, z);
instanciatedObjects[i].transform.Translate(x, y, z);
}
if (index < frames.Length - 1)
{
index++;
}
if (index >= frames.Length -1)
{
index = 0;
}
}
Here is a Screenshot:
So my question is:
How can I set the Position of this Sphere to one of the moving points, without changing the position of the cloned objects? Since all behave based on the BaseSphere?
Is it possible to make the BaseSphere not visible While the Objects are getting cloned or generated?
I am looking for a solution, that makes it easier to move the datagenerated Object around in Editor.
I would appreciate any kind of input.
Make all Spheres children of Empty Gameobject (for example. Sphere_root) and use this for moving Spheres.
Also check Scriptable Objects. It is simple and very quick method to manage data in Unity.
#Edit
public void Fill()
{
instanciatedObjects = new GameObject[deck.Length];
for (int i = 0; i < deck.Length; i++)
{
instanciatedObjects[i] = Instantiate(deck[i]) as GameObject;
instanciatedObjects[i].transform.parent = Baumer; // or Sphere Root or somehing else.
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateStairs : MonoBehaviour
{
public GameObject stairsPrefab;
public int delay = 3;
public int stairsNumber = 5;
public int stairsHeight = 0;
public Vector3 stairsPosition;
public Vector2 stairsSize;
// Use this for initialization
void Start ()
{
StartCoroutine(BuildStairs());
}
// Update is called once per frame
void Update ()
{
}
private IEnumerator BuildStairs()
{
for (float i = 0; i <= stairsSize.x; i++)
{
for (float k = 0; k <= stairsSize.y; k++)
{
stairsPosition = new Vector3(i, stairsHeight, k);
GameObject stairs = Instantiate(stairsPrefab, stairsPosition, Quaternion.identity);
stairs.transform.localScale = new Vector3(stairsSize.x, 1 , stairsSize.y);
stairsHeight += 1;
yield return new WaitForSeconds(delay);
}
}
}
private void CalculateNextStair()
{
}
}
I messed it up. For example I want to build 5 stairs but the loops are over the stairs size and not number of stairs.
Second it's creating 10 sets of stairs not 5 stairs:
Another problem is how can I make that each stair will be build slowly ? Now it's just Instantiate slowly with delay but how can I generate each stair with delay?
Screenshot of the script inspector:
My current code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateStairs : MonoBehaviour
{
public GameObject stairsPrefab;
public float delay = 0.3f;
public int stairsNumber = 5;
public int stairsPositions = 0;
public int stairsStartPositionHeight = 0;
public float stairsScalingHaight = 1;
public Vector2 stairsPosition;
public Vector2 stairsSize;
// Use this for initialization
void Start()
{
StartCoroutine(BuildStairs());
}
// Update is called once per frame
void Update()
{
}
private IEnumerator BuildStairs()
{
for (float i = 0; i <= stairsNumber; i++)
{
// x=0f, y=z=stairsHeight
stairsPosition = new Vector3(0f, stairsPositions, stairsPositions);
GameObject stairs = Instantiate(
stairsPrefab,
stairsPosition,
Quaternion.identity);
stairs.transform.localScale = new Vector3(
stairsSize.x,
stairsScalingHaight,
stairsSize.y);
stairsStartPositionHeight += 1;
yield return new WaitForSeconds(delay);
}
}
private void CalculateNextStair()
{
}
}
There's no reason to loop over the size of the stairs at all; you want to loop over stairsNumber, which is yet unused in your code.
Also, you don't need to change the x component of your stairs' positions. Keep it at 0f (or whatever you need).
The y and z components of your stairs positions (relative to the starting point) should both be factors of stairHeight. In this particular case, you want them to be equal to stairHeight, so that you get "square" step shapes.
private IEnumerator BuildStairs()
{
for (int i = 0; i <= stairsNumber ; i++) {
// x=0f, y=z=stairsHeight
stairsPosition = new Vector3(0f, stairsHeight, stairsHeight);
GameObject stairs = Instantiate(
stairsPrefab,
stairsPosition,
Quaternion.identity);
stairs.transform.localScale = new Vector3(
stairsSize.x,
1f ,
stairsSize.y);
stairsHeight += 1f;
yield return new WaitForSeconds(delay);
}
}
If you change stairSize to be a Vector3, then you can just use stairSize directly as the localScale, and increment stairsHeight by stairsSize.y instead of just 1f.
If you want to offset the starting position of your stairs, you need to include an offset. I recommend keeping it separate from the height counter until you need to add them.
Also, if you want to have rectangular sized steps, keep a widthFactor to multiply by the height to find how far each step moves horizontally.
Combining these changes might look like this:
Vector3 stairSize;
float stepWidthFactor=1f;
Vector3 stairsStartPosition;
private IEnumerator BuildStairs() {
for (int i = 0; i <= stairsNumber ; i++) {
stairsPosition = new Vector3(
stairsStartPosition.x,
stairsStartPosition.y + stairsHeight,
stairsStartPosition.z + stairsHeight*stepWidthFactor);
GameObject stairs = Instantiate(
stairsPrefab,
stairsPosition,
Quaternion.identity);
stairsHeight += stairsSize.y;
stairs.transform.localScale = stairSize;
yield return new WaitForSeconds(delay);
}
}
Here is my code, brick_col is updating itself as it should be, print(brick_col), tells me once the loop is complete brick_col is +1 itself, but, print (positions[i]), tells me my y value is always 0) the Vector3 isn't being updated with the value. Any ideas? Many thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Brick_Spawn_Test : MonoBehaviour {
List<Vector3> positions = new List<Vector3>();
private int bricks_in_row=9;
public GameObject Brick;
private int no_in_row=9;
private int brick_col=0;
private int number_of_brick_col=2;
void Start(){
Check_Bricks ();
}
void Check_Bricks(){
if (brick_col != number_of_brick_col) {
print ("not enough bricks");
Create_Bricks ();
}
}
void Create_Bricks(){
for (int i = 0; i <= bricks_in_row-1; i++)
{
for (int a = -4; a <= no_in_row/2; a++)
{
positions.Add(new Vector3(a,brick_col,0f));
}
print (brick_col);
print (positions [i]);
transform.position = positions[i];
Instantiate(Brick,transform.position, transform.rotation);
}
brick_col = brick_col + 1;
Check_Bricks ();
}
}
In your code you use the following variable as your y value
private int brick_col=0;
In your inner loop you add elements to your positions list with
positions.Add(new Vector3(a,brick_col,0f));
Without updating the brick_col until you are outside both loops.
Move this brick_col = brick_col + 1;
to where you want the update to really happen and if you put it into the inner loop you will probably also want to reset it just before entering again.
Alright honestly, you are doing some unnecessary things I will explain why as I go over it, I do things like this at times as well when I am trying to figure out what is going on, or when I am in a rush to build something I am excited to try, so starting out I will use your code and explain, then the fix then I will show another way to do this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Brick_Spawn_Test : MonoBehaviour {
List<Vector3> positions = new List<Vector3>();
private int bricks_in_row=9;
public GameObject Brick;
private int no_in_row=9; // No need for a number in row because you have bricks in row which is the same thing.
private int brick_col=0; // No need for this variable, as you are going to be counting anyways (in this case your i variable)
private int number_of_brick_col=2;
void Start(){
Check_Bricks ();
}
void Check_Bricks(){ // This function is unnessary, it appears it may have been added when you were trying to fix your y issue.
if (brick_col != number_of_brick_col) {
print ("not enough bricks");
Create_Bricks ();
}
}
void Create_Bricks(){
for (int i = 0; i <= bricks_in_row-1; i++) // This will run 9 times.
{
for (int a = -4; a <= no_in_row/2; a++) // This will also run 9 times
{
positions.Add(new Vector3(a,brick_col,0f));
}
// Move all this into the inner loop.
print (brick_col);
print (positions [i]); // By this point you will have 9 then 18 then 27... as your inner loop this position would be positons[i * bricks_in_row + (a +4)] with how you are looping
transform.position = positions[i]; /// This positions should be based off of the individual brick, next time around you are setting this position to the second index but by this time you have 18.
Instantiate(Brick,transform.position, transform.rotation);
//
// brick_col = brick_col + 1; This will be in the outter loop
}
brick_col = brick_col + 1; // This should be before the closing bracket. not outside the loop
Check_Bricks ();
}
}
This is how it would look, if I kept your variables and just fixed your y and positioning problems:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Brick_Spawn_Test : MonoBehaviour {
List<Vector3> positions = new List<Vector3>();
private int bricks_in_row=9;
public GameObject Brick;
private int no_in_row=9;
private int brick_col=0;
private int number_of_brick_col=2;
void Start(){
Check_Bricks ();
}
void Check_Bricks(){
if (brick_col != number_of_brick_col) {
print ("not enough bricks");
Create_Bricks ();
}
}
void Create_Bricks(){
for (int i = 0; i <= bricks_in_row-1; i++)
{
for (int a = -4; a <= no_in_row/2; a++)
{
positions.Add(new Vector3(a,brick_col,0f));
print (brick_col);
print (positions [i * bricks_in_row + a +4]);
transform.position = positions[i * bricks_in_row + a +4];
Instantiate(Brick,transform.position, transform.rotation);
}
brick_col = brick_col + 1;
}
Check_Bricks ();
}
}
This is a way to handle this, you can ignore the way I name variables as it is a matter of preference:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Brick_Spawn_Test : MonoBehaviour {
[SerializeField]
private int totalBrickColumns = 9; // Serializing it so I can use this for multiple test cases and edit the variable in the inpsector.
[SerializeField]
private int totalBrickRows = 2;
[SerializeField]
private Vector2 startingPoint = new Vector2(-4, 0);
[SerializeField]
private GameObject Brick;
void Start()
{
CreateBricks();
}
void CreateBricks()
{
Vector2 spawnPosition = startingPoint;
for(int x = 0; x < totalBrickColumns; ++x) // x is my column
{
spawnPosition.x = startingPoint.x + x; // the x is my offset from the startingPoint.x so if I wanted to start at -4 i just set the startingPoint.x to -4
for(int y = 0; y < totalBrickColums; ++y) // y is my row
{
spawnPosition.y = startingPoint.y + y; // the y is my offset from the startingPoint.y
print("Brick Location: " + spawnPosition.toString());
Instantiate(Brick,spawnPosition, transform.rotation);
}
}
}
}
In regards to why your y isn't updating, is because you are not updating the variable inside of your first loop. See the comment in your code on brick_col in the Create_Brick() function.
EDIT: I noticed something I wasn't considering when I said you needed to update your outter loop, I also added a fix using only your code, with your variables.
I'm making bubble shooter replica in unity and I encountered a problem with initalizing the bubbles in random places, should I create an array of them in the background class?
For example i have class Sprite1 and Sprite2 and I want to display them in random places in the background how can I do it?
This is how it looks.
http://imgur.com/a/DGpZj
And below it's my attempt to display it by for loop, but dont know the method.
void Start () {
Random.Range(0f,4.5f);
for (int i = 0; i < 100; i++)
{
Sprite.Create(?)
}
}
Displaying your bubbles randomly in the background all depends on what your "randomly" word means: if it like randomly on a grid, completely randomly, can they overlay other bubbles, ...
So here's a first approach to your problem using a grid generation: to generate your bubbles, you can either use the Instantiate method or create new GameObjects.
Your game seems to be a 2D one so I highly recommend you looking for the Unity UI tutorials. Once you'll understand the basics of the UI system, create a Canvas and add an empty game object to it. Afterward you can assign it the below script:
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(RectTransform))]
public class TestScript: MonoBehaviour
{
[SerializeField]
private float m_BubbleSize;
[SerializeField]
private int m_BubbleColumns;
[SerializeField]
private int m_BubbleRows;
[SerializeField]
private Sprite[] m_BubbleSprites;
private GameObject[][] m_Bubbles;
void Start()
{
GenerateBubbles();
}
private void GenerateBubbles()
{
// Position of the most top left bubble
Vector3 initialPosition = GetComponent<RectTransform>().position;
initialPosition.y += GetComponent<RectTransform>().rect.height * 0.5f;
initialPosition.y -= 0.5f * m_BubbleSize;
initialPosition.x -= (m_BubbleColumns - 1) * 0.5f * m_BubbleSize;
initialPosition.x -= 0.25f * m_BubbleSize;
// Rows height: comes from https://en.wikipedia.org/wiki/Close-packing_of_equal_spheres
float rowsHeight = Mathf.Sqrt(6.0f * m_BubbleSize * m_BubbleSize) / 3.0f;
// Bubbles references array
m_Bubbles = new GameObject[m_BubbleColumns][];
for(int i = 0; i < m_Bubbles.Length; i++)
{
m_Bubbles[i] = new GameObject[m_BubbleRows];
}
// Generation
for(int x = 0; x < m_Bubbles.Length; x++)
{
for(int y = 0; y < m_Bubbles[x].Length; y++)
{
GameObject bubble = new GameObject("Bubble_" + x.ToString() + y.ToString(), new System.Type[] { typeof(RectTransform), typeof(Image), typeof(CircleCollider2D) });
bubble.transform.SetParent(transform);
if(y % 2 == 0)
{
bubble.GetComponent<RectTransform>().position = initialPosition + new Vector3(x * m_BubbleSize, -y * rowsHeight, 0.0f);
}
else
{
bubble.GetComponent<RectTransform>().position = initialPosition + new Vector3(0.5f * m_BubbleSize + x * m_BubbleSize, -y * rowsHeight, 0.0f);
}
bubble.GetComponent<RectTransform>().sizeDelta = new Vector2(m_BubbleSize, m_BubbleSize);
bubble.GetComponent<Image>().sprite = m_BubbleSprites[Random.Range(0, m_BubbleSprites.Length)];
bubble.GetComponent<CircleCollider2D>().radius = m_BubbleSize * 0.5f;
}
}
}
}
To complete your game here are the few (maybe not exhaustive list) steps you will need to go through:
Populating a list of the potential "cell" where bubbles can be
Creating a pool of bubble to be fired (with random shuffling)
Writing the shooting + rebounds dynamic (Unity 2D Physic can help with that)
Detecting collision after bubble has been fired
Finding nearest possible "cell"
Searching if enough bubbles are connected (and if so destroying them)
Searching if some of the bubbles aren't connected anymore (and if so deleting them too)
OPTIONAL Implementing a scoring system (and saving the scores)
OPTIONAL Implementing apparition of new bubbles row on top every X bubbles fired
...
Hope this helps,