I am a beginner. I want to create a game where there are six different positions and objects that spawn from them everytime player collides one of them and then they respawn. it s a loop until game finish.
I am having a problem with positions; if player stays at a position it just collides continually. I need to deactivate the position that player collides and reactivate when player collides other position. Position were made with empthy object and its collider. I dont know where to add what.
Thanks for your help
public class NewSpawnScript : MonoBehaviour{
public GameObject[] SpawnPoints;
public float spawnTime;
public GameObject[] threeD;
public List<GameObject> possibleSpawn = new List<GameObject>();
public List<GameObject> possibleThreeD = new List<GameObject>();
void Start()
{
//to avoid spawn more then one object at a position
for(int i=0;i<SpawnPoints.Length;i++)
{
possibleSpawn.Add(SpawnPoints[i]);
}
// to avoid to spawn same objects at different positions
for (int l=0;l<threeD.Length;l++)
{
possibleThreeD.Add(threeD[l]);
}
InvokeRepeating("SpawnItems", spawnTime, spawnTime);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag=="Obj")
{
//to avoid spawn more then one object at a position
for (int i = 0; i < SpawnPoints.Length; i++)
{
possibleSpawn.Add(SpawnPoints[i]);
}
// to avoid to spawn same objects at different positions
for (int l = 0; l<threeD.Length; l++)
{
possibleThreeD.Add(threeD[l]);
}
InvokeRepeating("SpawnItems", 2.5f, 2.5f);
}
}
void Update()
{
}
void SpawnItems()
{
if(possibleSpawn.Count>0 && possibleThreeD.Count>0)
{
for(int i=0;i<12;i++)
{
int spawnIndex = Random.Range(0, possibleSpawn.Count);
int spawnObject = Random.Range(0, possibleThreeD.Count);
GameObject newObj = Instantiate(possibleThreeD[spawnObject], possibleSpawn[spawnIndex].transform.position, possibleSpawn[spawnIndex].transform.rotation) as GameObject;
newObj.GetComponent<Destroyer>().mySpawnPoint = possibleSpawn[spawnIndex];
newObj.transform.parent = newObj.GetComponent<Destroyer>().mySpawnPoint.transform;
possibleSpawn.RemoveAt(spawnIndex);
possibleThreeD.RemoveAt(spawnObject);
i++;
}
}
}
}
Related
I currently write a game, and I have 2 scripts that generate the ground in the game. However, instead of generating them as the player comes to the end of one ground, they're generated as soon as the game starts. I don't want this to happen.
Does someone know why it happens?
Please help me fix this.
Thanks!
This is my code:
Script 1:
public class ObjectPooler : MonoBehaviour
{
public GameObject pooledObject;
public int pooledamnt;
List<GameObject> pooledObjects;
// Start is called before the first frame update
void Start()
{
pooledObjects = new List<GameObject>();
for (int i = 0; i < pooledamnt; i++)
{
GameObject obj = (GameObject)Instantiate(pooledObject);
obj.SetActive(false);
pooledObjects.Add(obj);
}
}
public GameObject GetPooledObject()
{
for (int i = 0; i < pooledObjects.Count; i++)
{
if (pooledObjects[i].activeInHierarchy)
{
return pooledObjects[i];
}
}
GameObject obj = (GameObject)Instantiate(pooledObject);
obj.SetActive(false);
pooledObjects.Add(obj);
return obj;
}
// Update is called once per frame
void Update()
{
}
}
Script 2:
public class
GroundGenerator : MonoBehaviour
{
public GameObject thePlatform;
public Transform GenOnPoint;
public float DistanceBetween;
private float PlatformWidth;
public float DistanceBewtweenmin;
public float Di stanceBetweenmax;
public ObjectPooler objectpool;
public GameObject[] thePlatforms;
private int platformSelecter;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
GameObject newPlatform = objectpool.GetPooledObject();
newPlatform.transform.position = transform.position;
newPlatform.transform.rotation = transform.rotation;
newPlatform.SetActive(true);
}
}
Here is a basic script to generate ground as the player moves :
using UnityEngine;
public class GroundGeneration : MonoBehaviour
{
public float ClosestDistacnceFromPlayer;
public GameObject GroundTile;
public float TileWidth;
public Transform Player;
void Start()
{
//Spawn a tile so that the player won't fall off at the start
SpawnTile(1);
}
void SpawnTile(int n)
{
int i = 0;
//Spawn n tiles
while (i < n)
{
Instantiate(GroundTile, transform.position, Quaternion.identity);
i++;
//Teleport the "Ground generator" to the end of the tile spawned
transform.position += TileWidth * Vector3.right; // Or use Vector3.forward if you want to generate ground on z axis.
}
}
void FixedUpdate()
{
if (Vector3.Distance(Player.position, transform.position) <= ClosestDistacnceFromPlayer)
{
SpawnTile(1);
}
}
}
The GroundTile should have its origin at the point where it meets with the previous tile and it should be a prefab.
The Ground will start generating at the position of the object containing the ground generation script.
I am newbie to Unity 3D. I have created a game object(A missile) at position x:-1 y:-3 z:0 Added a component script which moves the ball in upward direction. Saved it as a prefab. Then deleted the Game object from the scene.
Component Script used
using UnityEngine;
public class Missile : MonoBehaviour
{
[SerializeField] protected Rigidbody2D rb;
public float speed = 4;
void Start()
{
Invoke("Object", 2.0f);
}
void Object()
{
float x = Random.Range(-2.0f, 2.0f);
float y = -5.0f;
rb.MovePosition(new Vector3(x, y, 0));
Debug.Log("Position of Rigid Body: " + rb.position);
rb.velocity = Vector2.up * speed;
}
virtual protected void Die()
{
Destroy(gameObject);
}
}
Invoked a script which takes prefab as input parameter and spawns the Game object at random position & moves up as per the script component of missile. I need the missile to trigger at random location, but the missile is getting triggered both at position x:-1 y:-3 z:0(Game object position) & some random location. How can I avoid the Game object position while spawning
Script used to invoke the prefabs
using UnityEngine;
using System.Collections;
using TMPro;
public class MissileSpawnner : MonoBehaviour
{
[SerializeField] GameObject[] missilePrefabs;
[SerializeField] int missileCount;
[SerializeField] float spawnDelay;
GameObject[] missiles;
#region Singleton class: MissileSpawnner
public static MissileSpawnner Instance;
void Awake()
{
Instance = this;
}
#endregion
void Start()
{
PrepareMissiles();
StartCoroutine(SpawnMissiles());
}
IEnumerator SpawnMissiles()
{
for (int i = 0; i < missileCount;i++)
{
Debug.Log("Object set as active");
missiles[i].SetActive(true);
yield return new WaitForSeconds(spawnDelay);
}
}
void PrepareMissiles()
{
missiles = new GameObject[missileCount];
int prefabsCount = missilePrefabs.Length;
for (int i = 0; i < missileCount; i++)
{
missiles[i] = Instantiate(missilePrefabs[Random.Range(0, prefabsCount )]);
missiles[i].SetActive(false);
}
}
}
Change this:
missiles[i] = Instantiate(missilePrefabs[Random.Range(0, prefabsCount )]);
to
missiles[i] = Instantiate(missilePrefabs[Random.Range(0, prefabsCount )], <vector3position>, <quaternionrotation>);
and you will specify its position and rotation, just replace vector3position with a vector3 of your choosing and quaternionrotation with a quaternion rotation of your choosing. You can use Quaternion.Identity if you don't want any rotation. You can also add a parent if you choose as well.
missiles[i] = Instantiate(missilePrefabs[Random.Range(0, prefabsCount )], <vector3position>, <quaternionrotation>, <transformparent>);
Just replace transformparent with the gameobject you want to be the parent of the bullet, if this override can prove useful to you.
More reading on Object.Instantiate
https://docs.unity3d.com/ScriptReference/Object.Instantiate.html
I am making a game like 2 cars. And I have written code to create a instantiater. It is a car game and there are 4 lanes. Let me show you a picture of my game and yeah this is solely for practise.
Player should avoid square objects and eat circle objects but sometimes 2 square objects get spawned in a same lane making impossible for player to win. I have written this script to control that but I failed. Please help me. At least have a check to my DetectSameLaneFunction(). And tell me what I am doing wrong.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour {
public GameObject[] objects;
public float delaytime = 2f; // this is separate for each prefab with which script is attaches
public float spawnrate = 1f; // this is separate for each prefab with which script is attaches
public static int lastgameobjectindex;
public static GameObject lastgameobject;
public static GameObject SecondLastGameObject;
private float loadingtime;
private GameObject go; // just a temporary variable
public static List<GameObject> spawnobjects = new List<GameObject>();
// Use this for initialization
void Start () {
loadingtime = delaytime;
}
// Update is called once per frame
void Update () {
if (Time.time > loadingtime)
{
float randomness = spawnrate * Time.deltaTime;
if ( randomness < Random.value)
{
Spawners();
}
NextLoadTime();
}
}
private void Spawners()
{
int spawnnumber = Random.Range(0, 2);
GameObject go = Instantiate(objects[spawnnumber]) as GameObject;
go.transform.position = this.transform.position;
spawnobjects.Add(go);
Debug.Log(spawnobjects[spawnobjects.Count-1]);
DetectSameLaneObjects();
/* if (spawnobjects.Count > 4)
{
spawnobjects.RemoveAt(0);
}*/
}
private void DetectSameLaneObjects()
{
if (spawnobjects.Count > 3)
{
lastgameobject = spawnobjects[spawnobjects.Count - 1];
SecondLastGameObject = spawnobjects[spawnobjects.Count - 2];
lastgameobjectindex = spawnobjects.Count - 1;
if (SecondLastGameObject.transform.position.x != lastgameobject.transform.position.x
)
{
if (Mathf.Abs(lastgameobject.transform.position.x- SecondLastGameObject.transform.position.x) < 2.3f)
{
Debug.Log("Destroy function getting called");
Destroy(spawnobjects[lastgameobjectindex]);
spawnobjects.RemoveAt(lastgameobjectindex);
}
}
}
}
void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, 0.6f);
}
void NextLoadTime()
{
loadingtime = Time.time + delaytime;
}
}
I'm working in a mobile game that has multiples areas in the same scene. Each area has a trigger and when the player enters in it several objects are spawned to pick up them. How can I do to deactivate a picked up object so when the player enters in this area again this object doesn't spawn again?
This is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using PathologicalGames;
public class InOutZone_ZONAS: MonoBehaviour {
//Objetos
[Header("Objetos")]
public List<GameObject> spawnPositions;
public List<GameObject> spawnObjects;
private GameObject[] despawnObjects;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
SpawnObjectsZ ();
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
GameObject[] despawnObjects = GameObject.FindGameObjectsWithTag("ItemZona");
for (int i = 0; i < despawnObjects.Length; i++)
{
PoolManager.Pools ["Objetos"].Despawn (despawnObjects[i].transform);
Debug.Log("Despawnea Objetos");
}
}
}
void SpawnObjectsZ()
{
foreach (GameObject spawnPosition in spawnPositions) {
int selection = Random.Range (0, spawnObjects.Count);
PoolManager.Pools ["Objetos"].Spawn (spawnObjects [selection], spawnPosition.transform.position, spawnPosition.transform.rotation);
}
}
}
How can I do to deactivate a picked up object so when the player
enters in this area again this object doesn't spawn again?
There are many ways to do this. You can simply remove the GameObject from the List after you spawn it with spawnObjects.Remove(spawnObjects[selection]);
public class Playervitals : MonoBehaviour
{
//Objetos
[Header("Objetos")]
public List<GameObject> spawnPositions;
public List<GameObject> spawnObjects;
private GameObject[] despawnObjects;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
SpawnObjectsZ();
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
GameObject[] despawnObjects = GameObject.FindGameObjectsWithTag("ItemZona");
for (int i = 0; i < despawnObjects.Length; i++)
{
PoolManager.Pools["Objetos"].Despawn(despawnObjects[i].transform);
Debug.Log("Despawnea Objetos");
}
}
}
void SpawnObjectsZ()
{
for (int i = 0; i < spawnPositions.Count; i++)
{
GameObject spawnPosition = spawnPositions[i];
int selection = Random.Range(0, spawnObjects.Count);
PoolManager.Pools["Objetos"].Spawn(spawnObjects[selection], spawnPosition.transform.position, spawnPosition.transform.rotation);
spawnObjects.Remove(spawnObjects[selection]);
}
}
}
This question already has answers here:
How to reference a class from child to parent?
(3 answers)
Closed 6 years ago.
I am trying to manage some variables in TileScript like TileGroupID, TileIsSelected from the TilesManager script in parent but i cant find a way to do it. For example i want to search all the Tiles if one of them have TileIsSelected True and then do something in all Tiles that have TileGroupID 1. I created tilesArray to keep track all the game objects but i don't know how i can use that to do what i said earlier.
TileScript:
//Public
public int tileGroupID = 0; //Indicates the Tile Group ID.
public bool tileIsSelected = false; //If this Tile is Selected.
public GameObject[] tilesArray; //Reference to Tiles Array.
//Private
private Rigidbody myRigidbody;
private Renderer myRenderer;
private Material tileDefaultMaterial;
private Material tileSelectedMaterial;
private Material tileSameGroupMaterial;
void Start () {
tilesArray = GetComponentInParent<TilesManager> ().tilesArray;
myRigidbody = GetComponent<Rigidbody> ();
myRenderer = GetComponent<Renderer> ();
tileDefaultMaterial = Resources.Load ("TileDefault", typeof(Material)) as Material;
tileSelectedMaterial = Resources.Load ("TileSelected", typeof(Material)) as Material;
tileSameGroupMaterial = Resources.Load ("TileSameGroup", typeof(Material)) as Material;
}
TilesManager:
//Public
public GameObject[] tilesArray; //Aray of all Tiles GameObject.
//Private
void Start () {
tilesArray = new GameObject[transform.childCount];
for(int i = 0; i < transform.childCount; i++){
tilesArray [i] = transform.GetChild (i).gameObject;
}
}
void OnMouseDown (){
//Do stuff with each tile.
}
The OnMouseDown function should be moved from the TilesManager script to the TileScript script. It will be called when each Tile is clicked on. When this happens, you can call a function on the TilesManager function and pass it the current GameObject that was clicked on.
In your TileScript script:
void OnMouseDown()
{
//Let Tiles Manager know that there was a press on (this) Tile
tileManagerInstance.OnObjectSelection(this.gameObject);
}
In your TilesManager script:
public void OnObjectSelection(GameObject selectedObj)
{
//Change Material of the Selected GameObject
selectedObj.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
}
when i click on a tile TileIsSelected change to true, change his
material and change all the other tile material that have same
TileGroupID as the one i clicked.
All you need now is a basic for loop. Loop through the tilesArray array and check which one has the-same tileGroupID as the GameObject that was clicked.
void findTheSameTileGroupIDAndChangeColor(GameObject selectedObj)
{
//Get the TileScript attached to the selectedObj
TileScript selectedTileScript = selectedObj.GetComponent<TileScript>();
//Loop through all GameObject in the array
for (int i = 0; i < tilesArray.Length; i++)
{
/*
Make sure this is NOT selectedObj since we've arleady
changed its Material in OnObjectSelection function
*/
if (selectedObj != tilesArray[i])
{
//Get TileScript attached to the current Tile loop
TileScript tileLoop = tilesArray[i].GetComponent<TileScript>();
//Check if selectedObj and the current loop tileGroupID matches
if (selectedTileScript.tileGroupID == tileLoop.tileGroupID)
{
//It matches! Now, change it's color
tileLoop.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
}
}
}
}
Finally the Whole thing I said put together:
TileScript:
public class TileScript : MonoBehaviour
{
public int tileGroupID = 0; //Indicates the Tile Group ID.
public bool tileIsSelected = false; //If this Tile is Selected.
public GameObject[] tilesArray; //Reference to Tiles Array.
//Private
private Rigidbody myRigidbody;
private Renderer myRenderer;
private Material tileDefaultMaterial;
private Material tileSelectedMaterial;
private Material tileSameGroupMaterial;
private TilesManager tileManager;
void Start()
{
tilesArray = GetComponentInParent<TilesManager>().tilesArray;
myRigidbody = GetComponent<Rigidbody>();
myRenderer = GetComponent<Renderer>();
tileDefaultMaterial = Resources.Load("TileDefault", typeof(Material)) as Material;
tileSelectedMaterial = Resources.Load("TileSelected", typeof(Material)) as Material;
tileSameGroupMaterial = Resources.Load("TileSameGroup", typeof(Material)) as Material;
//Get Tiles Manager
GameObject tileManagerObj = GameObject.Find("Tiles");
tileManager = tileManagerObj.GetComponent<TilesManager>();
}
void OnMouseDown()
{
//Let Tiles Manager know that there was a press on (this) Tile
tileManager.OnObjectSelection(this.gameObject);
}
}
TilesManager:
public class TilesManager : MonoBehaviour
{
public GameObject[] tilesArray; //Aray of all Tiles GameObject.
public Material tileSelectedMaterial;
void Start()
{
tilesArray = new GameObject[transform.childCount];
for (int i = 0; i < transform.childCount; i++)
{
tilesArray[i] = transform.GetChild(i).gameObject;
}
}
//Will be called from the TileScript(Receives any tile that is selected)
public void OnObjectSelection(GameObject selectedObj)
{
//Change Material of the Selected GameObject
selectedObj.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
//Change Mateial of other GameObjects that matches the tileGroupID of the selectedObj
findTheSameTileGroupIDAndChangeColor(selectedObj);
}
void findTheSameTileGroupIDAndChangeColor(GameObject selectedObj)
{
//Get the TileScript attached to the selectedObj
TileScript selectedTileScript = selectedObj.GetComponent<TileScript>();
//Loop through all GameObject in the array
for (int i = 0; i < tilesArray.Length; i++)
{
/*
Make sure this is NOT selectedObj since we've arleady
changed its Material in OnObjectSelection function
*/
if (selectedObj != tilesArray[i])
{
//Get TileScript attached to the current Tile loop
TileScript tileLoop = tilesArray[i].GetComponent<TileScript>();
//Check if selectedObj and the current loop tileGroupID matches
if (selectedTileScript.tileGroupID == tileLoop.tileGroupID)
{
//It matches! Now, change it's color
tileLoop.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
}
}
}
}
}