Code doesn't get played on restart? (Android) - c#

so i made a endless runner on android(i know original right? hmmm..) And everything works fine at first. However when i die and press the restart button with the following code:
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
The game stops generating rooms? Any idea why? This is my generating rooms code:
void AddRoom(float farhtestRoomEndX) {
//pick a random room from the array and instantiate it.
int randomRoom = Random.Range(0, AllRooms.Length);
GameObject room = (GameObject)Instantiate(AllRooms[randomRoom]);
//Find the floor, and pos to instantiate(half of the screen) and add it to active rooms.
float roomWidth = room.transform.FindChild("Floor").localScale.x;
float roomCenter = farhtestRoomEndX + roomWidth * 0.5f;
room.transform.position = new Vector3(roomCenter, 0, 0);
ActiveRooms.Add(room);
}
void GenerateRoomIfRequired() {
//Create a new list with rooms to be deleted, and make a bool to check if rooms need to be added
List<GameObject> DeleteRooms = new List<GameObject>();
bool AddRooms = true;
//Save the playerPos, , calculate the point after when the room needs to be removed and calculate the starting pos for instantiating a new room
float playerX = transform.position.x;
float removeRoomX = playerX - screenWidthInPoints;
float addRoomX = playerX + screenWidthInPoints;
//store the point where the room ens, this is used to instantiate a new room aswell
float farthestRoomEndX = 0;
// use the floor to get the room width and calculate the roomStartX and roomEndX
foreach (var room in ActiveRooms) {
float roomWidth = room.transform.FindChild("Floor").localScale.x;
float roomStartX = room.transform.position.x - (roomWidth * 0.5f);
float roomEndX = roomStartX + roomWidth;
//If there is a room that starts after addRoomX, delete it. or ends to the left of removeRoomX, delete it
if (roomStartX > addRoomX)
AddRooms = false;
if (roomEndX < removeRoomX)
DeleteRooms.Add(room);
//the most right point of the level.
farthestRoomEndX = Mathf.Max(farthestRoomEndX, roomEndX -0.01f);
}
//remove rooms that are marked as removal, and if addRooms is still true, add a new room
foreach (var room in DeleteRooms) {
ActiveRooms.Remove(room);
Destroy(room);
}
if (AddRooms)
AddRoom(farthestRoomEndX);
}
The weird part is everything runs great the first time. (The code above is beeing called from a fixedupdate.)

Related

Random Position Generation

I'm very new at coding (like two weeks), so forgive me for the silly question. But I'm trying to code a block sliding 3d game in unity, where the obstacles randomly generate, forever, the random generation is fine, but for my life, i cannot figure out how to get the obstacles to spawn at random Z positions. i"m currently stuck with a CS0117 error, so i cant test my latest attempt to fix this.
here's my current code:
using UnityEngine;
public class BlockSpawner : MonoBehaviour
{
public Transform[] SpawnPoints;
public GameObject blockPrefab;
public float timeBetweenWaves = 1f;
private float timeToSpawn = 2f;
public class Random { }
void Update()
{
if (Time.time >= timeToSpawn)
{
SpawnBlocks();
timeToSpawn = Time.time + timeBetweenWaves;
}
}
void SpawnBlocks()
{
//Spawning blocks in
int randomIndex = Random.Range(0, SpawnPoints.Length);
{
for (int i = 0; i < SpawnPoints.Length; i++)
if (randomIndex != i)
{
// generate random position
var viewRange = this.Size - SpawnPoints.Size;
Random random = new Random();
var left = random.Next(0, viewRange.Width);
var top = random.Next(0, viewRange.Height);
// set the random position
SpawnPoints.Location = new Point(left, top);
}
}
}
And Heres is my last working Code (note this has no random location code attempts):
using UnityEngine;
public class BlockSpawner : MonoBehaviour
{
public Transform[] SpawnPoints;
public GameObject blockPrefab;
public float timeBetweenWaves = 1f;
private float timeToSpawn = 2f;
void Update()
{
if (Time.time >= timeToSpawn)
{
SpawnBlocks();
timeToSpawn = Time.time + timeBetweenWaves;
}
}
void SpawnBlocks()
{
//Spawning blocks in
int randomIndex = Random.Range(0, SpawnPoints.Length);
{
for (int i = 0; i < SpawnPoints.Length; i++)
if (randomIndex != i)
{
Instantiate(blockPrefab, SpawnPoints[i].position, Quaternion.identity);
}
}
}
}
Please help!
I will guess at the error and say this is wrong
var viewRange = this.Size - SpawnPoints.Size;
var left = random.Next(0, viewRange.Width);
var top = random.Next(0, viewRange.Height);
// set the random position
SpawnPoints.Location = new Point(left, top);
Random random = new Random();
you are calling methods on 'random' before you have set it up. YOu need
var viewRange = this.Size - SpawnPoints.Size;
Random random = new Random();
var left = random.Next(0, viewRange.Width);
var top = random.Next(0, viewRange.Height);
// set the random position
SpawnPoints.Location = new Point(left, top);
But I will point out 2 things
unity has given you its random number generator, and you already used it (Random.Range) but for some reason you decide to use the c# standard one
creating a new Random each time round that loop will keep generating the same numbers over and over again if called in rapid succession better is to create the Random once at the start of the function (or use the Unity one)
To Generate Obstacles At Random Z position.
Am I keeping it much Simple!.
To Do this we have to keep these things in mind:
1: The X and Y Coordinates are not going to change.
2: The only Z coordinates are going to change.
Solution:
Generate a new Vector3 that will contains same X and Y coordinates but random Z coordinates.
Code:
// the game object (mean obstacle to generate)
public GameObject ObstaclePrefab;
// this will be the coordinates that will not going to change (X and Y coordinates as they will be same for all obstacles but only the Z coordinates will change.)
public Vector2 ConstantCords = new Vector2(0, 0);
// the max and minimum range for obstacles to be generated (X represents the negative [minimum] while y will represent the positive [maximum] position (Cordinates) )
public Vector2 MaxZCords = new Vector2(-50f, 50f);
// this method will generate the obstacle at random position
public void GenerateRandomObstacle()
{
// getting a random Z coordinates
// Random.Range will give random values
float Z = Random.Range(MaxZCords.x, MaxZCords.Y);
// getting position to generate the obstacle
// putting the constant and the random Z value
Vector3 pos = new Vector3(ConstantCords.x, ConstantCords.y, Z);
// generating the obstacle at the generated random position
// we are setting the rotation to rotation of the prefab
Instantiate(ObstaclePerfab, pos, ObstaclePrefab.transfrom.rotation);
}

Instantiate predefined number of object along a raycast in Unity

I have a raycast that's being rendered every frame based on 2 points, and those 2 points change position each frame.
What I need is a system that doesn't need a direction, or a number of objects, but instead takes in 2 points, and then instantiates or destroys as many objects as necessary to get the instantiated objects from one side to another minus spaceBetweenPoints. If you wanted you could think of it as an Angry Birds Style slingshot HUD, except without gravity, and based on raycasts.
My Script:
public int numOfPoints; // The number of points that are generated (This would need to chnage based one the distance in the end)
public float spaceBetweenPoints; // The spacing between the generated points
private GameObject[] predictionPoints; // The prefab to be gernerated
private Vector2 firstPathStart; // The starting point for the raycast (Changes each frame)
private Vector2 firstPathEnd; // The ending point for the raycast (Changes each frame)
void start()
{
predictionPoints = new GameObject[numOfPoints];
for (int i = 0; i < numOfPoints; i++)
{
predictionPoints[i] = Instantiate(predictionPointPrefab, firePoint.position,
Quaternion.identity);
}
}
void Update
{
Debug.DrawLine(firstPathStart, firstPathEnd, UnityEngine.Color.black);
DrawPredictionDisplay();
}
void DrawPredictionDisplay()
{
for (int i = 0; i < numOfPoints; i++)
{
predictionPoints[i].transform.position = predictionPointPosition(i * spaceBetweenPoints);
}
}
Vector2 predictionPointPosition(float time)
{
Vector2 position = (Vector2)firstPathStart + direction.normalized * 10f * time;
return position;
}
The current system simply takes in a starting position, a direction, and then moves a preset number of objects in that direction based on time. This way of doing it also causes problems because it's endess instead of only going till the end of the raycast: (Pardon my drawing skills)
Blue line = raycast
Black dots = instantiated prefab
Orange dot = raycast orange
Green dot = end of raycast
Notes:
direction is the momentum which I set in the editor, I needed it to put together what I currently have working, but it shouldn't be necessary when running based on points.
If you ask me I would say it is kinda easy if you know little bit of Math trickery. I'm not saying that I'm very good at Math, but once you get it it's kind of easy to pull off next time. Here if I try to explain everything, i won't be able to explain clearly. Take a look as the code below I've commented the whole code so that you can understand easily.
Basically I used a Method called Vector2.Lerp() Liner Interpolation, which means that this method will return value between point1, and point2 based on the value of 3rd argument t which goes from 0 to 1.
public class TestScript : MonoBehaviour
{
public Transform StartPoint;
public Transform EndPoint;
public float spaceBetweenPoints;
[Space]
public Vector2 startPosition;
public Vector2 endPosition;
[Space]
public List<Vector3> points;
private float distance;
private void Update()
{
startPosition = StartPoint.position; //Setting Starting point and Ending point.
endPosition = EndPoint.position;
//Finding the distance between point
distance = Vector2.Distance(startPosition, endPosition);
//Generating the points
GeneratePointsObjects();
Debug.DrawLine(StartPoint.position, EndPoint.position, Color.black);
}
private void OnDrawGizmos()
{
//Drawing the Dummy Gizmo Sphere to see the points
Gizmos.color = Color.black;
foreach (Vector3 p in points)
{
Gizmos.DrawSphere(p, spaceBetweenPoints / 2);
}
}
private void OnValidate()
{
//Validating that the space between two objects is not 0 because that would be Raise an exception "Devide by Zero"
if (spaceBetweenPoints <= 0)
{
spaceBetweenPoints = 0.01f;
}
}
private void GeneratePointsObjects()
{
//Vlearing the list so that we don't iterate over old points
points.Clear();
float numbersOfPoints = distance / spaceBetweenPoints; //Finding numbers of objects to be spawned by dividing "distance" by "spaceBetweenPoints"
float increnment = 1 / numbersOfPoints; //finding the increment for Lerp this will always be between 0 to 1, because Lerp() takes value between 0 to 1;
for (int i = 1; i < numbersOfPoints; i ++)
{
Vector3 v = Vector2.Lerp(startPosition, endPosition, increnment * i); //Find next position using Vector2.Lerp()
points.Add(v);//Add the newlly found position in List so that we can spwan the Object at that position.
}
}
}
Update: Added, How to set prefab on the positions
I just simply Destroyed old objects and Instantiated new Objects. But remember instantiating and Destroying object frequently in your game in unity will eat-up memory on your player's machine. Os I would suggest you to use Object-Pooling. For the reference I'll add a link to tutorial.
private void Update()
{
startPosition = StartPoint.position; //Setting Starting point and Ending point.
endPosition = EndPoint.position;
//Finding the distance between point
distance = Vector2.Distance(startPosition, endPosition);
//Generating the points
GeneratePointsObjects();
//Update: Generating points/dots on all to location;
InstenciatePrefabsOnPositions();
Debug.DrawLine(StartPoint.position, EndPoint.position, Color.black);
}
private void InstenciatePrefabsOnPositions()
{
//Remove all old prefabs/objects/points
for (int i = 0; i < pointParent.childCount; i++)
{
Destroy(pointParent.GetChild(i).gameObject);
}
//Instantiate new Object on the positions calculated in GeneratePointsObjects()
foreach (Vector3 v in points)
{
Transform t = Instantiate(pointPrefab);
t.SetParent(pointParent);
t.localScale = Vector3.one;
t.position = v;
t.gameObject.SetActive(true);
}
}
Hope this helps please see below links for more reference
OBJECT POOLING in Unity
Vector2.Lerp
I hope I understood you right.
First, compute the A to B line, so B minus A.
To get the number of needed objects, divide the line magnitude by the objects' spacing. You could also add the diameter of the prediction point object to avoid overlapping.
Then to get each object position, write (almost) the same for loop.
Here's what I came up with, didn't tested it, let me know if it helps!
public class CustomLineRenderer : MonoBehaviour
{
public float SpaceBetweenPoints;
public GameObject PredictionPointPrefab;
// remove transforms if you need to
public Transform start;
public Transform end;
private List<GameObject> _predictionPoints;
// these are your raycast start & end point, make them public or whatever
private Vector2 _firstPathStart;
private Vector2 _firstPathEnd;
private void Awake()
{
_firstPathStart = start.position;
_firstPathEnd = end.position;
_predictionPoints = new List<GameObject>();
}
private void Update()
{
_firstPathStart = start.position;
_firstPathEnd = end.position;
// using any small value to clamp everything and avoid division by zero
if (SpaceBetweenPoints < 0.001f) SpaceBetweenPoints = 0.001f;
var line = _firstPathEnd - _firstPathStart;
var objectsNumber = Mathf.FloorToInt(line.magnitude / SpaceBetweenPoints);
var direction = line.normalized;
// Update the collection so that the line isn't too short
for (var i = _predictionPoints.Count; i <= objectsNumber; ++i)
_predictionPoints.Add(Instantiate(PredictionPointPrefab));
for (var i = 0; i < objectsNumber; ++i)
{
_predictionPoints[i].SetActive(true);
_predictionPoints[i].transform.position = _firstPathStart + direction * (SpaceBetweenPoints * i);
}
// You could destroy objects, but it's better to add them to the pool since you'll use them quite often
for (var i = objectsNumber; i < _predictionPoints.Count; ++i)
_predictionPoints[i].SetActive(false);
}
}

How to instantiate object on correct position?

I have one really big issue with my game . When i try press play when he spawn first prefab everything is correct X position is -0.604f , z is -1.49f..But when i spawn second object the second and the third object get spawned on wrong position of x and z.
On the second object X position is not good ( in this case second Z position of object is -1.208 and i need here same value as before -0.604) I really don't know why this happens and I don't know how i can change Z position when i spawn third object in other side so if first two objects are on right and left and when i spawn third object he get Z position of -4.968 which is not correct because I need on third position on Z = -1.655984 and i am getting on third object z position of ~-5f.
Here is my code to spawn objects..
public class StackPiecesSpawner : Singleton<StackPiecesSpawner> {
public GameObject stackPrefab;
[SerializeField] public Transform StackPieceSpawnPoint;
[SerializeField] public float PieceSpawnSize = 0.1f;
[SerializeField] public float PieceSpawnWidth = 1.0f;
[SerializeField] private float speed = 1f;
public Vector3 OriginalSpawnPointPosition;
protected override void Awake()
{
base.Awake();
OriginalSpawnPointPosition = StackPieceSpawnPoint.position;
}
public void SpawnNextStackPiece()
{
//StackPieceSpawnPoint.position += new Vector3(0f,PieceSpawnSize,0f);
StackPieceSpawnPoint.position += new Vector3(0.604f, 0.1f, -1.656f);
//GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
GameObject go = GameObject.Instantiate(stackPrefab);
//go.transform.localScale = new Vector3(PieceSpawnWidth,PieceSpawnSize,PieceSpawnWidth);
go.transform.localScale = new Vector3(0.4f, 0.4f,0.05f);
go.transform.position = nextSpawnPosition();
go.AddComponent<Rigidbody>();
go.GetComponent<Rigidbody>().isKinematic = true;
go.AddComponent<StackPiece>();
go.transform.parent = transform;
go.transform.name = "StackPiece_" + (StackPiecesManager.StackPieces.Count + 1);
StackPiece piece = go.GetComponent<StackPiece>();
piece.TargetTransform = StackPieceSpawnPoint;
piece.Speed = speed;
StackPiecesManager.Instance.AddNewPiece(piece);
}
private Vector3 nextSpawnPosition()
{
System.Random rnd = new System.Random();
int num = rnd.Next(0, 100);
Vector3 modifier = new Vector3();
modifier = num < 50 ? Vector3.back : Vector3.left;
modifier *= StackPiecesManager.Instance.SpawnDistance;
Vector3 returned = (StackPieceSpawnPoint.position - modifier) + Vector3.up * (StackPiecesManager.Instance.ExtraHeight);
// returned = (StackPieceSpawnPoint.position) + Vector3.up * (StackPiecesManager.Instance.ExtraHeight);
return returned;
}
public void Reset()
{
StackPieceSpawnPoint.position = OriginalSpawnPointPosition;
}
}
I cannot completely answer this question as not all the code and context is available, however, I could maybe point you in the right direction.
Parent-child relationship
In the SpawnNextStackPiece you instantiate a prefab and have its current parent transform equal the current transform(of the object this script is attached to), check if the transform you're changing the parent to is shifting each time a prefab is instantiated. I tend to avoid changing parent transforms, I usually try to attach it to different parents and change the actual objects offset not the parents, it can be easier to manage. I suspect go.transform.parent = transform; is causing a problem.
Diagnosing the problem through zeroing out values
Try forcefully making the z-axis 0 so you can see how much it is getting offset by each time it spawns, that may make diagnosing the problem much easier. Do this with StackPieceSpawnPoint.position = new Vector3(0.604f, 0.1f,0f);

Objects not pooling correctly

I'm having a problem pooling some objects. I've looked at a starter file we got in class to recreate the scene but different, but I'm not having the correct results and I can't seem to figure it out :/
What I have is:
Environment which has 3 child object pools (ground, dew, corona). Ground has 3 childs (planes), dew and corona both have 10 childs (models).
What I'm trying to do is move the first object in an array to the last place of the array and changing the z position to move it forward once the player has ran past it.
My ground objects correctly go forward once my character has passed a certain position, the dews and coronas however do not, and I don't understand why.
This is the code I'm using:
public class Environment : MonoBehaviour
{
List<Transform> dews = new List<Transform>();
List<Transform> coronas = new List<Transform>();
List<Transform> grounds = new List<Transform>();
Transform player;
int propsCount = 0;
int groundCount = 0;
// Use this for initialization
void Start()
{
player = GameObject.Find("Player").transform;
dews = GameObject.Find("DewPool").GetComponentsInChildren<Transform>().ToList();
coronas = GameObject.Find("CoronaPool").GetComponentsInChildren<Transform>().ToList();
grounds = GameObject.Find("GroundPool").GetComponentsInChildren<Transform>().ToList();
dews.RemoveAt (0);
coronas.RemoveAt (0);
grounds.RemoveAt (0);
}
// Update is called once per frame
void Update()
{
// Voeg hier code toe voor Object Pooling!
Vector3 nieuwePos;
if (player.transform.position.z > dews[0].transform.position.z + 5)
{
dews[0].transform.position = nieuwePos = new Vector3(dews[0].transform.position.x, dews[0].transform.position.y, dews[0].transform.position.z + 50);
dews.Add(dews[0]);
dews.RemoveAt(0);
}
if (player.transform.position.z > coronas[0].transform.position.z + 5)
{
coronas[0].transform.position = nieuwePos = new Vector3(coronas[0].transform.position.x, coronas[0].transform.position.y, coronas[0].transform.position.z + 55);
coronas.Add(coronas[0]);
coronas.RemoveAt(0);
}
if (player.transform.position.z > grounds[0].transform.position.z + 40)
{
grounds[0].transform.position = nieuwePos = new Vector3(grounds[0].transform.position.x, grounds[0].transform.position.y, grounds[0].transform.position.z + 120);
grounds.Add(grounds[0]);
grounds.RemoveAt(0);
}
}
}
All the pools containing the objects are positioned at 0, the dews and coronas start at Z-index 7.5 and 10 respectively and the copies are always 5 Z further.
Player is an empty gameobject positioned at 0 - 0 - 4.4 containing the model Ethan.
The first dew and corona correctly get pushed backwards, the rest is very buggy.
If anyone can help out it would be greatly appreciated, thanks in advance!
Fixed it by adding
for (int i = dews.Count-1; i > 0; i-=2) {
dews.RemoveAt (i);
}
for (int i = coronas.Count-1; i > 0; i-=2) {
coronas.RemoveAt (i);
}
into my start() function, my objects had another child while my ground objects did not.
Probably not the best solution but for now I'm okay with this :-)

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

Categories

Resources