Instantiate gameobjects as child of main object - c#

is it a way for instantiate gameobjects as child of main? This is my example of code
void MakeCubes ()
{
GameObject cubes = Instantiate (Cube) as GameObject;
cubes.AddComponent <CubeScript> ();
cubes.SetActive (true);
}
I'm invoking MakeCube() function every time when previous is destroyed. I ask this because I'm giving option in game that you can continue playing if you lost life. Current situation is that when you continue playing game, score isn't counting. For example. If I hit 5 cubes. I have score 5, then I lost "life". I press continue. I can hit cubes but they doesn't counting. When I hit 5 cubes it doesn't count to current score. But when I hit sixth cube it is counting from score 5 to 6.

Parent is a attribute of transform so you can play with transforms to get this. Well, in your case you can do something like,
void MakeCubes ()
{
GameObject cubes = Instantiate (Cube) as GameObject;
cubes.AddComponent <CubeScript> ();
// Replace YOUR_PARENT_GO from your parent GameObject
cubes.transform.parent = YOUR_PARENT_GO.transform;
cubes.SetActive (true);
}

You can sue transform.SetParent(). Unity docs: Transform.SetParent

You can set the parent for something that already exists in your hierarchy:
gameObject.transform.parent = GameObject.Find("Name of game object").transform;

Related

How can i clone an object one by one in unity

So basically i wanted to learn about instantiate and I have tried this code below:
public Transform spawnpos;// the position where i wanted to clone my sphere
void Update()
{
if (Input.GetKeyDown("q"))
{
Instantiate(gameObject, spawnpos.position, spawnpos.rotation);
Destroy(gameObject, 2);
}
}
the thing is, when i press "q" it does spawn a sphere and gone in about 2 secs, but if i continously press "q" the amount of clones spawned are getting bigger as i press and it wont be destroyed after 2 seconds.
In Conclusion, how can i spawn a sphere when i pressed "q", and it will spawn 10 if i pressed "q" 10 times
tysm for reading this far! have a nice day! :)
First thing's first, you can't instantiate the gameobject to which this script is attached through this script because:
If you instantiate a gameobject, there will be two gameobjects in the scene and both will be having this script. Hence if you press Q again, two gameobjects are instantiated.
Solution:
Create an empty gameobject in the scene and create a new script ObjectSpawner.cs and attach it to this empty gameobject.
public class ObjectSpawner : MonoBehaviour {
public Transform spawnpos;// the position where I wanted to clone my sphere
public GameObject sphere;// gameobject you want to spawn
void Update() {
if (Input.GetKeyDown("q")) {
GameObject obj = Instantiate(sphere, spawnpos.position, spawnpos.rotation);
Destroy(obj, 2);
}
}
}
In the above script as you can see there's a field for the sphere gameobject. Drag it to the slot in the inspector.

Arcade Coin Script for Unity

Hello!
For a school project, I have to create a 2d Arcade Game. And one of the things that I have to include is a coin system. Let me explain:
In the main menu you start out with 3 coins, and whenever you click play, one coin will be spent so you will have 2 coins. At the end of some levels, you can pick a coin up so it will refill in the main menu. Once you got no coins left you cant enter the game anymore.
I hope I explained it well enough. I do have the coin pickup part but I just can't wrap my head around the rest of what I have to do. Can someone maybe link me a tutorial that implements this system or maybe help me?
You should use a variable for the amount of coins. Call it coins. Also, make sure you aren’t loading new scenes, or it will erase the amount. So once the player hits play, take a coin away and start the game. Then, they can pick the coins up again. Write this in the script coin:
public int coins = 3;
bool pressedTheButton;
bool pickedUpCoin;
void Update(){
if (pressedTheButton){
coins -= 1;
pressedTheButton = false;
}
if (pickedUpCoin){
coins += 1;
pickedUpCoin = false;
}
}
You should change the variable called pressedTheButton when the player starts the game. Same with the pickedUpCoin. If you are changing scenes, then add a function to it called DontDestroyOnLoad(gameObject);
Add it to a Start(){} function of the script.
public int coins = 3;
bool pressedTheButton;
bool pickedUpCoin;
void Start(){
DontDestroyOnLoad(gameObject);
}
void Update(){
if (pressedTheButton){
coins -= 1;
pressedTheButton = false;
}
if (pickedUpCoin){
coins += 1;
pickedUpCoin = false;
}
}
What this does, is doesn’t destroy the game object when you load the scene for the game. Attach the script to any game object you don’t want to be destroyed when loading the new scene. For example you can add it to an empty game object, or something that won’t change.

Score increasing by 2 when it should be increased by 1

I have a bullet and when it hits a target it should increment the score by 1. but the score is increasing by 2. the bullet is a capsule with a collider and rigibody and the target is a cylinder with a collider and rigibody
the code on the bullet
public class Bullet : MonoBehaviour {
float lifespan = 2;
void Start()
{
// destroy the bullet
Destroy(gameObject, lifespan);
}
void OnTriggerEnter(Collider other) //collider event
{
if (other.gameObject.CompareTag("Score"))
{
Score.score = Score.score + 1;
}
}
}
the score code
public class Score : MonoBehaviour {
public static int score; // The player's score.
Text text; // Reference to the Text component.
void Start()
{
// Set up the reference.
text = GetComponent<Text>();
// Reset the score.
score = 0;
}
void Update()
{
// Set the displayed text to the score value.
text.text = "Score: " + score;
}
}
I've solved this exact problem before but I searched for it to mark this as a duplicate but couldn't find it. It's probably deleted by the OP.
There are 2 possible reasons why your score could update multiple times.
1.Your script (Bullet) is attached to your GameObject multiple times. This is very likely the problem. It is very likely that it is attached to random empty GameObject.
Fix:
A.Check that gameObject.AddComponent<Bullet>(); is not anywhere in any script in your project. The AddComponent will add new Bullet to your GameObject.
B.Search for duplicated script on GameObjects through the Editor.
Select your Bullet script, go to Assets --> Find References in Scene. It will show you every GameObject that has this script attached to it. Remove it from all of them except for your bullet GameObject.
2.You have more than one collider on the GameObject. Maybe a collider as a child. You must find a way to handle that. If this is the case, you can ignore the child colliders by putting them in a separate tag and checking it.
You are already checking the tags which is fine. Just change the tag of the child colliders to something else that is not "Score" so that other.gameObject.CompareTag("Score") will not be true.

SetDestination and active agent/NavMesh issue with Unity Game

I am working in unity 5 on a game and I am currently getting this error:
"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.NavMeshAgent:SetDestination(Vector3)
EnemyMovement:Update() (at Assets/Scripts/Enemy/EnemyMovement.cs:25)
My code for the enemyMovement script is:
using UnityEngine;
using System.Collections;
public class EnemyMovement : MonoBehaviour
{
Transform player;
PlayerHealth playerHealth;
EnemyHealth enemyHealth;
NavMeshAgent nav;
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player").transform;
playerHealth = player.GetComponent <PlayerHealth> ();
enemyHealth = GetComponent <EnemyHealth> ();
nav = GetComponent <NavMeshAgent> ();
}
void Update ()
{
if(enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0)
{
nav.SetDestination (player.position);
}
else
{
nav.enabled = false;
}
}
}
Now I know that there is almost an identical question here: Unity - "SetDestination" can only be called on an active agent that has been placed on a NavMesh. UnityEngine.NavMeshAgent:SetDestination(Vector3) However, the question does not seem to have a firm response and I have tried doing some of the responses and nothing appears to work. I will say that my game does work fine. However, I have added an ability that if the player presses 'B' then all of the enemies will die on the screen. When I press 'B' the enemies die but the system 'crashes' and I get that error message.
EnemyManager.cs:
public void Kill(int InstanceID)
{
if (EnemyManager.Instance.EnemyList.ContainsKey(InstanceID))
EnemyManager.Instance.EnemyList.Remove(InstanceID);
}
public void DeathToAll()
{
Dictionary<int, Object> TempEnemyList = new Dictionary<int, Object>(EnemyManager.Instance.EnemyList);
foreach (KeyValuePair<int, Object> kvp in TempEnemyList)
{
// kvp.Key; // = InstanceID
// kvp.Value; // = GameObject
GameObject go = (GameObject)kvp.Value;
go.GetComponent<EnemyHealth>().Death();
}
}
Enemyhealth.cs
public void Death ()
{
// The enemy is dead.
isDead = true;
// Turn the collider into a trigger so shots can pass through it.
capsuleCollider.isTrigger = true;
// Tell the animator that the enemy is dead.
anim.SetTrigger ("Dead");
// Change the audio clip of the audio source to the death clip and play it (this will stop the hurt clip playing).
enemyAudio.clip = deathClip;
enemyAudio.Play ();
// Kill the Enemy (remove from EnemyList)
// Get the game object associated with "this" EneymHealth script
// Then get the InstanceID of that game object.
// That is the game object that needs to be killed.
EnemyManager.Instance.Kill(this.gameObject.GetInstanceID());
}
The problem here is that while you're checking if enemyHealth.currentHealth > 0 before calling nav.SetDestination(), that value doesn't get changed when the enemies are killed by the player's ability. Instead, it seems that the flag isDead is set on the enemy, without affecting the actual health.
To ensure nav.SetDestination() doesn't get called when the enemy is dead (because it seems at that point, the enemy is no longer a valid active agent), just add an additional condition to your if statement:
if(enemyHealth.currentHealth > 0 && !enemyHealth.isDead && playerHealth.currentHealth > 0)
{
nav.SetDestination (player.position);
}
Hope this helps! Let me know if you have any questions. (You may need to make isDead public for this to work.)
An alternative solution is to make a property IsDead which returns whether enemyHealth.currentHealth > 0, and kill enemies by setting their health to 0. Then you don't need to have a health tracker and a separate isDead flag that must be explicitly set. That's more of a design decision though as it won't affect the functionality.
I was having a similar issue where my navmesh agent was not able to reach the setdestination() point ,the navmesh agent just stopped so what i was doing wrong was that my setdestination() point was bit high from navmesh and that point was becoming out of range the agent.
So I created a foot empty gameobject that was near to the navmesh "in height".
and my agent was then able to reach the point

Destroying Clone in Unity

Hi everyone Im a bit stuck here. I have my gameObject Enemy Spawn at a random time. But the thing is that I only want the Enemy to be in the game for say 5 seconds. The trouble is that I can't destroy the object at all. Here I wrote this code to try and destroy the Enemy Object:
public class SpawnManager : MonoBehaviour {
public GameObject Enemy;
public float mytimer;
public float enemyHealth = 5.0f;
void Start()
{
GameObject player = GameObject.Find("Player");
}
void spawnEnemy() {
Transform enemy;
GameObject enemySpawnPoint = GameObject.Find("EnemySpawn");
enemy = Instantiate(Enemy,enemySpawnPoint.transform.position,enemySpawnPoint.transform.rotation) as Transform;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "EnemyTrigger") {
mytimer = Random.Range(0,10);
//Debug.Log("Now Destroying");
Invoke("spawnEnemy", mytimer);
Debug.Log("Spawn Normal");
if(Enemy.name == "BloodyMary(Clone"){
Destroy(Enemy, enemyHealth);
Debug.Log("Now Destroying");
}
}
}
}
Everytime I run into the trigger it spawns a "BloodyMary(Clone)" which I am trying to destroy. Any advice?
In my eyes it would make more sense for the enemy to handle its own destruction. This would mean that an enemy is responsible for its own duration which I feel would make more sense if you're having possibly a ton of enemies on the scene at any time.
I would create a co-routine which would simply wait for 5 seconds and then call the Destroy(gameObject) function to destroy itself. It may look a little like this:
IEnumerator DeathTimer(float duration)
{
yeild return new WaitForSeconds(duration);
Destroy(gameObject);
}
Then inside your 'Start()' method I would then call the co-routine (not done as a normal method). This would be done using something like this:
void Start()
{
// calls the coroutine to start
StartCoroutine("DeathTimer", duration);
}
Note: By calling a co-routine using a string (like above) you can then call "StopCoroutine("MethodName");" which will stop the coroutine at any time. This would be better than passing in a method parameter into the StartCoroutine().
This means your spawner is now purely responsible for spawning the enemies and they are responsible for their own death if they last for too long. Then you're not trying to manage multiple enemies on the spawner and you don't need to worry about tracking them in there.
I had a friend ask a very similar question the other day and he used this and it worked a treat.
The code that says:
Invoke ("spawnEnemy", myTimer);
Is calling your spawnEnemy() function, which creates anther Enemy clone. It also does the call with a delay timer.
If you don't want another Enemy just remove that part of the code.
Also you are destroying with a timer. You can Destroy instantaneously with Destroy(Enemy).
I see a typo, as you missed a closing parethesis on the name check. the reason that the linter didnt pick this up was because the parenthesis is in the string, so to the program it seems perfectly reasonable to check for "bloodymary(clone" instead of "bloodymary(clone)".
Solution is straight forward.
use Destroy(gameobject,5); after u initiate that gameobject.
example
<-- line initiate gameobject -->
Destroy(gameobject,5);
which 5 is target second before gameobject will destroy.

Categories

Resources