I have a Parent GameObject ZombieArmy with an attached script Zombie; its Transform changes each time a new zombie is instantiated as a child. How do I prevent the zombieArmy transform from changing and keep its transformed fixed at Vector3(0,0,0) while having the zombie have its own unique transform from each reSpawn()?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Zombie : MonoBehaviour {
public GameObject zombiePrefab;
public Transform zombieArmy;
public Transform zombieSpawnPoint;
private Transform[] spawnPositions;
public bool reSpawn = false;
private bool lastToggle = false;
private GameObject spawn;
// Use this for initialization
void Start () {
spawnPositions = zombieSpawnPoint.GetComponentsInChildren<Transform>();
}
private void NewSpawn() //spawn location of newZombie
{
if (reSpawn)
{
int i = Random.Range(1, spawnPositions.Length);
transform.position = spawnPositions[i].transform.position;
spawn = Instantiate(zombiePrefab, this.transform.position, this.transform.rotation, zombieArmy);
// zombieArmy.transform.position = new Vector3(0, 0, 0);
}
}
void Update () { //T-toggle
if (reSpawn != lastToggle)
{
NewSpawn();
reSpawn = false;
}
else
lastToggle = reSpawn;
}
}
If I'm understanding you correctly, that Zombie script is attached to the parent gameobject, right?
Then your NewSpawn() method is a bit incorrect.. This line
transform.position = spawnPositions[i].transform.position;
is actually changing the transform of the parent gameobject, as you say, because that's exactly what you're telling it to do.
If what you want is place each newly spawned object in the location of the randomly selected spawn point, try this instead:
int i = Random.Range(0, spawnPositions.Length); // Any reason the 0th index shouldn't be used?
spawn = Instantiate(zombiePrefab, this.transform);
spawn.transform.position = spawnPositions[i].transform.position;
spawn.transform.rotation = spawnPositions[i].transform.rotation;
Related
I'm fairly new to programming and right now I'm working on a 2D-Game for Android with Unity. The basic concept right now is that a object moves to the middle of the screen and it needs to "touch" an other object so you can press on a button and the moving object is getting destroyed. After it got destroyed I want another to spawn in and keep that cycle going. There is my problem. I have the (moving) object as a prefab and added it as the public GameObject "RedTriangle". The object is getting spawned in and moves to the center of the screen but it doesn't change the layer of the new objects when I press the button (I guess because its not the same object as the "RedTriangle" object). I really don't know how to change the Layer of new spawned in objects and hope I can get help here. Thanks already for all responses.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Red : MonoBehaviour, IPointerClickHandler
{
public GameObject RedTriangle;
public GameObject FalseTriangle;
public Transform spawnPos;
public float spawnT;
private void Start()
{
GameObject newTriangle = Instantiate(RedTriangle, spawnPos.position, Quaternion.identity);
}
IEnumerator touchCD()
{
while (true)
{
yield return new WaitForSeconds(0.1f);
if (RedTriangle == null)
{
}
else if (RedTriangle != null)
{
Debug.Log("!= null");
RedTriangle.layer = 0;
}
}
}
public void Update()
{
if (RedTriangle == null)
{
spawnT = Random.Range(1, 4);
if (spawnT == 3)
{
GameObject newTriangle = Instantiate(FalseTriangle, spawnPos.position, Quaternion.identity);
}
else
{
GameObject newFalseTriangle = Instantiate(RedTriangle, spawnPos.position, Quaternion.identity);
}
}
}
public void OnPointerClick(PointerEventData eventData)
{
RedTriangle.layer = 7;
Debug.Log("button");
StartCoroutine(touchCD());
}
Assuming you want to change the layer of the object immediately after spawning, just do exactly that. For example:
GameObject newTriangle = Instantiate(FalseTriangle, spawnPos.position, Quaternion.identity);
newTriangle.layer = 0;
If you want to change the current (MonoBehaviour) object's own layer from its own attached component script e.g. when a certain event occurs, you don't need to keep the reference in your own variable as you can just use for example:
gameObject.layer = 0;
I am making a turret that shoots a bullet at a set rate, but when the timer is done it doesn't spawn a new bullet even though it doesn't say i have any errors. the bullet has a simple script where it moves at a set speed either left or right, and gets destroyed on impact with an object. the turret does not have a collider right now so I know that's not the problem.
Here is the code for shooting:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TurretShoot : MonoBehaviour
{
public GameObject bullet;
public int bullet_rate = 10;
public int timer;
public Transform SpawnPoint;
void Start()
{
timer = bullet_rate * 10;
}
// Update is called once per frame
void Update()
{
if (timer == 0)
{
Instantiate(bullet, SpawnPoint.transform);
timer = bullet_rate * 10;
}
else
{
timer -= 1;
}
}
}
Here is the bullet code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletMove : MonoBehaviour
{
public int moveDirection;
public int moveSpeed;
void Start()
{
}
// Update is called once per frame
void Update()
{
this.transform.position += new Vector3(moveDirection * moveSpeed, 0, 0);
}
void onCollisionEnter2D(Collider2D col)
{
if (col.GetComponent<Collider>().name != "turret_top")
{
Destroy(this);
}
}
}
Here is the inspector for the turret:
Probably what is happening is it get's destroyed when it spawns.
I don't have a collider on the turret
You aren't instantiating it at the turrent. You are simply setting the parent when you are instantiating it:
public static Object Instantiate(Object original, Transform parent);
Meaning it is probally spawning at Vector3.Zero and instantly gets de-spawn.
Rather use the overload method of:
public static Object Instantiate(Object original, Vector3 position, Quaternion rotation);
That way you are spawning it the location you want. This is how you would go about it:
var bulletObj = Instantiate(bullet, SpawnPoint.transform.position, Quaternion.Identity);
bulletObj.transform.parent = SpawnPoint.transform;
timer = bullet_rate * 10;
I have multiple empty game objects that serve as the spawn points that spawn the game objects and I want the spawned game objects to be destroyed and Instantiate a new one on same spawn point if the condition to be tested is true.
I have 2 separate scripts, the one attached on the spawn point objects and another for the game manager that has the condition in it.
The Condition on the Game manager script:
public void checkword()
{
wordBuilded = displayer.text.ToString();
LetterTiles[] tiles = FindObjectsOfType<LetterTiles>();
foreach (LetterTiles item in tiles)
{
if (txtContents.Contains(wordBuilded))
{
if (item.gameObject.CompareTag("clicked"))
{
Destroy(item.gameObject);
FindObjectOfType<letterSpawner>().refresh();
}
}
else
{
if (item.gameObject.CompareTag("clicked"))
item.GetComponent<Button>().interactable = true;
}
}
}
The script attached to the spawn point objects that Instantiates the objects
using UnityEngine;
public class letterSpawner : MonoBehaviour {
public GameObject[] letterTiles;
GameObject tiles;
Vector3 scale = new Vector3(0.8f, 0.8f, 0);
void Start () {
refresh();
}
public void refresh()
{
int rand = Random.Range(0, letterTiles.Length);
tiles = Instantiate(letterTiles[rand], transform.position, Quaternion.identity);
tiles.transform.SetParent(gameObject.transform);
tiles.transform.localScale = scale;
}
}
You can do that by making a small change to whatever you have, first change your refresh function into this one
public void refresh(Vector3 position)
{
int rand = Random.Range(0, letterTiles.Length);
tiles = Instantiate(letterTiles[rand], position, Quaternion.identity);
tiles.transform.SetParent(gameObject.transform);
tiles.transform.localScale = scale;
}
also in the same file add another default one that calls this with the default value that you had
public void refresh()
{
refresh(transform.position);
}
and then in your checkword function
if (item.gameObject.CompareTag("clicked"))
{
Vector3 pos = item.transform.position;
Destroy(item.gameObject);
FindObjectOfType<letterSpawner>().refresh(pos);
}
that should do it for you
When spawning a Prefab, I'm trying to have each individual GameObject that makes up the Prefab run its own respective scripts. Basically,
I want the Prefab to break after spawning; leaving individual game Objects.
I have the GameObjects in the Prefab as children of an Empty. Any suggestions.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CreateFab : MonoBehaviour
{
public Transform Spawnpoint;
public Rigidbody Prefab;
public void OnClick()
{
Rigidbody RigidPrefab;
RigidPrefab = Instantiate(Prefab, Spawnpoint.position, Spawnpoint.rotation) as Rigidbody;
}
public void DetachFromParent()
{
// Detaches the transform from its parent.
transform.parent = null;
}
}
Cube Script
using UnityEngine;
using UnityEditor;
using System.IO;
public class WallClick : MonoBehaviour
{
string path;
public MeshRenderer mRenderer;
public void OpenExplorer()
{
path = EditorUtility.OpenFilePanel("Overwrite with png", "", "png");
GetImage();
}
void GetImage()
{
if (path != null)
{
UpdateImage();
}
}
void UpdateImage()
{
byte[] imgByte = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(2, 2);
texture.LoadImage(imgByte);
mRenderer.material.mainTexture = texture;
}
}
If you spawn a prefab, give the spawned item a reference.
var obj = Instantiate(prefabGameobject);
You can then do whatever you like with the spawned object
var script = obj.AddComponent<YourScript>();
And you can then modify the variables of your script and so on.
Your prefab will not be touched.
The transform.parent you're using here refers to the transform of the gameobject your CreateFab.cs script is attached to, not the prefab's childrens (smaller cubes).
The correct way would be:
// Instantiate the prefab
RigidBody rigidPrefab = Instantiate(Prefab, Spawnpoint.position, Spawnpoint.rotation) as Rigidbody;
// Detach all children from the parent. Each child refers to the transform of a single cube.
foreach (Transform child in rigidPrefab.transform)
{
child.parent = null;
}
I am trying to instantiate a zombie prefab every time I call NewSpawn(), which is when reSpawn variable becomes 'true'(through inspector). However, once I instantiate one zombie it does an infinite loop of clones of the zombie. [Making clones of clones of clones] How do I limit it to one zombie instantiation per method call? (I'd like to make 10 zombies, not 10,000.
Thank you!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Zombie : MonoBehaviour {
public GameObject zombiePrefab;
public Transform zombieSpawnPoint;
private Transform[] spawnPositions;
public bool reSpawn = false;
private bool lastToggle = false;
// Use this for initialization
void Start () {
spawnPositions = zombieSpawnPoint.GetComponentsInChildren<Transform>();
}
private void NewSpawn() //spawn location of newZombie
{
Instantiate(zombiePrefab, transform.position, transform.rotation);
int i = Random.Range(1, spawnPositions.Length);
transform.position = spawnPositions[i].transform.position;
}
void Update () { //T-toggle
if (reSpawn != lastToggle)
{
NewSpawn();
reSpawn = false;
}
else
lastToggle = reSpawn;
}
}
Just call NewSpawn() in your button click event instead of setting reSpawn to true.
Besides that this doesn't make any sense:
else
{
lastToggle = reSpawn;
}
They are already equal.