Hello, i would like to say thanks in advance to anyone who is kind enough to help out. So here it goes, I am new to all of this and i am in the process of creating my own game. Right now my character must avoid obstacles by jumping over them and by ducking under them. Now, the thing is right now i have it set for random generator, and i do not really want a random generator. So my question to you is, how would i go about coding A certain object spawning pattern that i want? For example, right now it is just spawning randomly, BRICK, HOLE, BRICK, FENCE, FENCE, HOLE, ETC… What i want to do is set my own organized pattern that will always spawn obstacles the same way every time i start the game. Can someone please help me with this? I have been looking for help for over a week now.
I’ve never done this, so take my advice with a grain of salt…
The way I would accomplish this is to use a “buffer” to store the pattern I want spawns to occur in.
e.g perhaps an array of 10 items to spawn
0 fence
1 cube
2 sphere
3 fence
… and so on
There are probably 100 different ways to do this.
you cold even write different patterns into a lookup table and switch patterns that way.
The simple answer is that you probably want to store them in an array or a List–there are some Unity tutorials on working with those data structures here: Arrays - Lists and Dictionaries.
Thanks for your response @Antistone and @spryx … For some reason i cant seem to figure it out. I just keep randomly generating objects, if that doesnt work then it spawns the same object over and over… Is there a sample code you might be able to give to start my pattern of objects i want to spawn? I have levels drawn out and where the objets should go, but i can not seem to get them to work without a random generator.
@amichael
Try something like this:
//Set up level. 0 = Block, 1 = Bridge
string objectList = "00100101101001010100";
int objectNum = 0;
-------------------------------------------
// This is where you would create the objects
if(objectList[objectNum] == '0'){
//Spawn Block
}
if(objectList[objectNum] == '1'){
//Spawn Bridge
}
objectNum++;
if(objectNum == objectList.Length){
//Reached the end of the objects
}
The way it works is you first create a string. Each character in the string represents the next object. You can set the characters to ANYTHING you want, I just set it to 1 and 0.
Later when you create the object, it checks what the current character is, and creates the proper object.
Then it sets it to the next character. Also, you can do something once it hits the end of the object list.
Note: The reason I set it up this way is because each object is just 1 character in a string, so you can make a huge list of objects easily in a very small space. That up there is a list of 20 objects, and the code is so tiny.
Perhaps if you posted an excerpt from your current code to demonstrate how you’re currently utilizing the random output, we could suggest how to modify it?
You could have a play with something like this
Comments explain the process
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Starter : MonoBehaviour
{
// Select the spawning objects in the inspector.
// Attach the Script to an empty Game object or the Camera.
// FIFO collection
public List<GameObject> goList;
private int goListIndex;
private int goListLength;
private GameObject currentSpawnObject;
// Awake is called when the script instance is being loaded (Since v1.0)
private void Awake() {
goListLength = goList.Count();
goListIndex = goListLength;
}
// Update is called once per frame
private void Update() {
/* Continiously iterate the GameObjectList
* This could be done on a timer.
*/
goListIndex = (++goListIndex >= goListLength) ? 0 : goListIndex;
currentSpawnObject = goList[goListIndex];
// perform your mojo to spawn currentSpawnObject
Debug.Log(currentSpawnObject.name);
}
}
goListIndex = (++goListIndex >= goListLength) ? 0 : goListIndex;
Heh, that line is pretty cool…learn something every day
I normally do that with a modulus
goListIndex = (goListIndex+1) % goListLength;
Did you post that from your code editor or by copying from the previous post ??
The post is still not a true representation of your code.
Kerry
@kdubnz i copied it from my last post and added the tag. Sorry buddy, not trying to intentionally make things difficult.
@kdubnz i deleted the others and copied it directly.
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
public class ObstacleGeneration : MonoBehaviour {
public GameObject highBrickPrefab, lowBrickPrefab, fencePrefab;
public float recycle;
public float minZ, maxZ;
public int numberOfObjects;
private Vector3 lowPos, highPos, fPos;
public float lowBrickProbability, highBrickProbability, fenceProbability;
private Vector3 nextPos;
private Queue<Transform> obstacleQueue;
private Transform player;
private int curObst;
private int curQue = 1;
private bool start = true;
private bool nextCreate = false;
private bool waitCreate = true;
void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
highPos = new Vector3(3.083166f, 1.491387f, player.position.z);
lowPos = new Vector3(3.083166f, 0.2214425f, player.position.z);
carPos = new Vector3(4.687229f, 0.0924263f, player.position.z);
obstacleQueue = new Queue<Transform>(numberOfObjects);
Creation();
for(int i = 0; i < numberOfObjects; i++)
{
Recycle();
}
start=false;
}
private void Creation()
{
for(int i = 0; i < numberOfObjects; i++)
{
curObst = Random.Range(0,100);
if(curObst <= lowBrickProbability)
{
obstacleQueue.Enqueue((Transform) Instantiate(highBrickPrefab.transform));
if(i == 0 && start)
{
nextPos = highPos;
}
}
else if(curObst <= highBrickProbability && curObst > lowBrickProbability)
{
obstacleQueue.Enqueue((Transform) Instantiate(lowBrickPrefab.transform));
if(i == 0 && start)
{
nextPos = lowPos;
}
}
else if(curObst <= fenceProbability && curObst > highBrickProbability)
{
obstacleQueue.Enqueue((Transform) Instantiate(fencePrefab.transform));
if(i == 0 && start)
{
nextPos =fPos;
}
}
else if(curObst <= fenceProbability && curObst > fenceProbability)
{
obstacleQueue.Enqueue((Transform) Instantiate(longcarPrefab.transform));
if(i == 0 && start)
{
nextPos =fPos;
}
}
else
{
Debug.Log ("BREAK");
}
}
}
private void Recycle(float extraZ = 0f)
{
Transform o = obstacleQueue.Dequeue();
if(o.name == highBrickPrefab.name+"(Clone)")
{
nextPos = new Vector3(highPos.x,highPos.y,nextPos.z);
}
else if(o.name == lowBrickPrefab.name+"(Clone)")
{
nextPos = new Vector3(lowPos.x,lowPos.y,nextPos.z);
}
else
{
nextPos = new Vector3(fPos.x,fPos.y,nextPos.z);
}
nextPos += new Vector3(
0f,
0f,
Random.Range((0-minZ)+extraZ, (0-maxZ)+extraZ));
Vector3 position = nextPos;
o.localPosition = position;
obstacleQueue.Enqueue(o);
}
void Update()
{
if(curQue <= numberOfObjects && !nextCreate)
{
waitCreate = true;
if(obstacleQueue.Peek().localPosition.z - recycle > player.position.z)
{
Destroy(GameObject.Find (obstacleQueue.Peek().name));
obstacleQueue.Dequeue();
curQue++;
}
}
else
{
nextCreate = true;
StartCoroutine(Wait(0.5f));
curQue = 1;
}
}
private void GameStart()
{
nextPos = transform.localPosition;
for(int i = 0; i < numberOfObjects; i++)
{
Recycle();
}
}
IEnumerator Wait(float duration)
{
if(waitCreate)
{
waitCreate = false;
yield return new WaitForSeconds(duration); //Wait
Creation();
for(int i = 0; i < numberOfObjects; i++)
{
if(i == 0)
{
Recycle(-25f);
}
else { Recycle(); }
}
nextCreate = false;
}
}
}
@amichael
That’s a LOT better.
You are more likely to get responders with that effort
Kerry,
@Antistone I posted my code you asked about
OK, you probably want to take this part:
private void Creation()
{
for(int i = 0; i < numberOfObjects; i++)
{
curObst = Random.Range(0,100);
…and change it to something like:
private void Creation(int[] objects)
{
foreach(int curObst in objects)
{
Then, whenever you call Creation(), you can pass in the objects you want to use as an argument. For example:
int[] firstLevel = new int[]{1, 1, 2, 1, 3, 5, 7};
Creation(firstLevel);
That creates a level that has obstacles number 1, 1, 2, 1, 3, 5, and 7, in that order.
@Antistone thx buddy, and everyone for all the help you have been giving me with this. Just another question, when you say 1,2,3,4,5, etc. are you assigning the object prefabs to a number? Of so, how do you go about that? Sorry, again still trying to learn all this on my own and with help from all of you guys. I’m really excited about the help you have been giving me with this. I have tried other forums and they were just plain “rude” about my questions, because I was “new” to this stuff.
No, I’m not assigning object prefabs to the number, I’m just listing numbers. Since you were previously generating random numbers, I assume you already had some way of turning those numbers into prefabs.
But if you want, instead of passing in an int[ ], you could pass in a GameObject[ ], which can contain prefabs instead of numbers. And if you declare a public GameObject[ ] field in your MonoBehavior, you can populate the array in the inspector by dragging prefabs into it.
There are many additional flourishes you could add on top of this. Ultimately, you may want to read the levels in from a separate data file. But I suggest you take things one step at a time.