Respawn an enemy prefab after its destroyed - unity3d

var respawn : Transform;
var dead : boolean = false;
function OnTriggerEnter(theCollision : Collider)
{
if(theCollision.gameObject.name=="Spotlight")
{
Destroy(gameObject);
Debug.Log("Dead");
dead = true;
}
}
function Respawn()
{
if(dead == true)
{
Instantiate(respawn, Vector3(0,0,0), Quaternion.identity);
}
}
I'm having trouble getting my enemies to re-spawn, at the moment I have just the one enemy following me around. I'm trying to re-spawn his after he collides with my spotlight.
I have a prefab Enemy that I want to use to create more instances of Enemy once it gets destroyed.
I'm pretty sure my code above is destroying the prefab itself and thus cannot create any more instances but I'm not sure how to just destroy an instance of a prefab. The code above is attached to my enemy.

I am pretty sure you are destroying the gameObject with the script.
if(theCollision.gameObject.name=="Spotlight")
{
Destroy(gameObject);
Debug.Log("Dead");
dead = true;
}
You should have there Destroy(theCollision.gameObject) instead.
And destroy at the end of the code block, not beginning.
Also Respawn function should be on Update or something for it to work, also you can call Respawn on the trigger function before destroying and it should spawn a new one every time.
Do not forget to reference the prefab from you Project window not Hierarchy.

As I said in my comment, you need to keep track of the time since the enemy died, and the best place to do that is in your respawner object. Here is an example implementation of it:
Respawner.js
#pragma strict
var enemyToSpawn : Enemy;
var respawnTime : int = 10; //In seconds.
private var dead : boolean = true;
private var deadTime : int = 0; //Time the enemy died, keep at 0
private var nextRespawn : int = 0;
private function Respawn() {
var enemy : GameObject = GameObject.Instantiate(enemyToSpawn.gameObject, transform.position, transform.rotation);
enemy.GetComponent(Enemy).respawner = this;
}
function Update() {
if (Time.time >= nextRespawn && dead) { //If the time is due and the enemy is dead
Respawn(); //create a new enemy
dead = false; //and tell our script it is alive
}
}
function EnemyDied(theEnemy : Enemy) {
dead = true;
deadTime = Time.time;
nextRespawn = Time.time+respawnTime;
GameObject.Destroy(theEnemy.gameObject);
}
Enemy.js
#pragma strict
public var respawner : Respawner; // The respawner associated with this enemy
function OnTriggerEnter(collision : Collider) {
if (collision.gameObject.name.Equals("Spotlight")) {
respawner.SendMessage("EnemyDied", this); //Tell the respawner to kill us
}
}
Of course your enemy class will have anything else necessary to be an actual enemy, and your respawner could have an effect. This is just an example and shouldn't be blindly copy-pasted.

Related

Destroying Prefabs Object After Spawn Using collision

I currently have some objects spawning from a prefab and am attempting to destroy only one of the spawned items of that prefab. I was searching online and I found tons of different examples but I have been unable to get any of them to work. I tried setting up an instance of the Instantiate and destroying that instance but I am unable to get it to work. The spawn/collision script is attached to the main camera if that matters. Collision with other items in my game work and the prefab does have a box collider set to isTrigger. Again, I know there are plenty of examples explaining this etc, but I can't get it to work and maybe I am not understanding what I actually should be doing.
Spawner code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bloodVialSpawner : MonoBehaviour
{
public GameObject vialOfBlood;
private GameObject vialss;
private int hunger =10;
public int numOfVials;
public int minSpawnRange, maxSpawnRange;
public int minSpawnRange2, maxSpawnRange2;
// Start is called before the first frame update
float timeSpawns = 2;
List<GameObject> vialsInstantiated = new List<GameObject>();
void Start()
{
StartCoroutine(becomeHungry());
InvokeRepeating("SpawnVials", timeSpawns, timeSpawns);
}
private void Update()
{
if (hunger == -1)
{
Debug.Log("sigh");
}
}
void SpawnVials()
{
for (int i = 0; i < numOfVials; i++)
{
vialsInstantiated.Add(Instantiate(vialOfBlood, SpawnPosition(), Quaternion.identity) as GameObject);
}
}
Vector3 SpawnPosition()
{
int x, y, z;
y = 59;
x= UnityEngine.Random.Range(minSpawnRange, maxSpawnRange);
z = UnityEngine.Random.Range(minSpawnRange2, maxSpawnRange2);
return new Vector3(x, y, z);
}
IEnumerator becomeHungry()
{
while (true)
{
hunger -= 1;
yield return new WaitForSeconds(1);
Debug.Log(hunger);
}
}
}
Spawner Script is on the Main Camera. Player used is the First Person Player Unity provides.
Code for destroying spawned object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class destroyVial : MonoBehaviour
{
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "vials")
{
Destroy(col.gameObject);
Debug.Log("yell");
}
}
}
Destroy code is on prefab. Note prefab is not in hierarchy as it should not be.
Firstly,
I see that you're spawning things in a for-loop and overwriting the vialss variable every time:
for (int i = 0; i < numOfVials; i++)
{
vialss = Instantiate(vialOfBlood,
SpawnPosition(),
Quaternion.identity) as GameObject;
}
And then, on collision, you're Destroying vialss, which in this case will be the latest spawned object. And if you collide with anything after 1 collision, vialss will already be deleted and probably throw an exception. Maybe that's fine in your game, but the logic looks a bit flawed.
Also, I'm assuming you want to destroy the object you're colliding with? Does something like this not work?
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "vials")
{
Destroy(col.gameObject); // <== Remove colliding object
Debug.Log("yell");
}
}
If you, for some unrelated reason, need a list of all your spawned vials, maybe you'd like to convert that to a list instead:
List<GameObject> spawnedVials = new List<GameObject>();
void SpawnVials()
{
for (int i = 0; i < numOfVials; i++)
{
var vial = Instantiate<GameObject>(vialOfBlood,
SpawnPosition(),
Quaternion.identity)
spawnedVials.Add(vial);
}
}
Finally,
make sure that the collision detection is working. You're saying that the script is attached to your camera. please make sure you have a Collider on the camera. But you're saying that other colliders are working, so I'm guessing you have this under control.
I'd guess your issue lies in the flawed logic I initially described.
OnTriggerEnter needs to be on a script attached to the object it's colliding with, or the vial itself. It can't be on the main camera as OnTriggerEnter will never get called.
I would recommend you to keep scripts to one job, you should split that script into a Spawn script and a Collider script. And create a empty GameObject with the sole purpose of spawning prefabs.
Also there's some errors in your code:
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "vials")
{
Destroy(col.gameObject); // Destroy the gameObject you're colliding with
Debug.Log("yell");
}
}
Also the variable vialss isn't doing what you're expecting, vialss is only referencing to the last instantiated vial, so better save all vials in a List:
List<GameObject> vialsInstantiated = new List<GameObject>();
And then:
void SpawnVials()
{
for (int i = 0; i < numOfVials; i++)
{
vialsInstantiated.Add(Instantiate(vialOfBlood, SpawnPosition(), Quaternion.identity) as GameObject);
}
}

Infinite & Random environment spawn

I am trying to achieve an endless runner that Instantiates tiled (modular) models randomly onto one another as you run along.
Here is the code attached to the model, when it triggers with "Player", it instantiates a new model randomly from an array. However, I want it to spawn in at exactly -90x from the previous model so that they tile. At the moment, it instantiates into world space at -90, 0 , 0.
function OnTriggerEnter (hit : Collider) {
//obstacles spawn
if(hit.gameObject.tag == "Player") {
var toSpawn : GameObject = obstacles[Random.Range(0,obstacles.Length)];
var spawnPosition = new Vector3 (-90,0,0);
var Spawn = Instantiate (toSpawn, spawnPosition), Quaternion.identity;
}
}
You could keep a count of how many tiles have already been placed, and use it as a multiplier.
private int tileCount = 1;
and in your OnTriggerEnter() method:
var offset = new Vector3 (-90 * tileCount,0,0);
tileCount++;
you need to cache the old tile then or find it somehow
GameObject lastSpawn;
function OnTriggerEnter (hit : Collider)
{
//obstacles spawn
if(hit.gameObject.tag == "Player")
{
var toSpawn : GameObject = obstacles[Random.Range(0,obstacles.Length)];
var offset = new Vector3 (-90,0,0);
var spawn = Instantiate (toSpawn, lastSpawn.transform.position + offset), Quaternion.identity) as GameObject;
lastTile = spawn;
}
}
now this one will allow for variable tile sizes (not tested):
GameObject lastSpawn;
function OnTriggerEnter (hit : Collider)
{
//obstacles spawn
if(hit.gameObject.tag == "Player")
{
var toSpawn : GameObject = obstacles[Random.Range(0,obstacles.Length)];
var offset = lastSpawn.GetComponent<MeshRenderer>().bounds.extents + gameObject.GetComponent<MeshRenderer>().bounds.extents;
offset.y = 0f;
var spawn = Instantiate (toSpawn, lastSpawn.transform.position + offset), Quaternion.identity) as GameObject;
lastTile = spawn;
}
}

unity3d how can i delete enemy :S and not the animator

How would I delete an enemy on the enemyprefab but not the enemanim animator?
#pragma strict
var enemy : GameObject;
var speed : float = 1.0;
var enemanim : Animator;
function Start() {
this.transform.position.x = 8.325;
this.transform.position.y = -1.3;
enemanim = this.GetComponent(Animator);
enemanim.SetFloat("isdead", 0);
}
function OnCollisionEnter2D(coll: Collision2D) {
if (coll.gameObject.CompareTag("distroy")) {
Destroy(this.gameObject);
}
}
function enemstruck() {
enemanim.SetFloat("isdead", 1);
}
function FixedUpdate() {
this.transform.Translate(Vector3(Input.GetAxis("Horizontal") * speed * Time.deltaTime, 0, 0));
this.rigidbody2D.velocity = Vector2(-5, 0);
}
This is my enemy prefab code i am instantiating it in my main
These 2 var:
var enemytrans : Transform;
var enemy : GameObject;
function Start () {
while (true) {
yield WaitForSeconds (Random.Range(3, 0));
enemy = Instantiate(enemytrans).gameObject;
}
I think you cannot delete GameObject and save one of its components. Every component needs to be attached to some GameObject and you cannot move them to other GameObjects either.
What you can do is to remove other components from your GameObject and you will get the same result.
You can remove a component with following script:
Destroy(gameObject.GetComponent(yourComponent));
It is possible to save the Component and Destroy the GameObject. Although I can only think of very few special cases when this would be done with logic (not out of madness).
For example, you might have different enemies, when one dies, its special power transfers over to another enemy via the Component.
So this is how I would do it, using the example above (code is C# because UnityScript lacks power):
public void die()
{
Component c = GetComponent<TheType>();
// Send component.
BroadcastMessage("setComponent", c);
// Destroy.
Destroy(gameObject);
}
Then whatever object is listening to setComponent will handle it:
public void setComponent(Component c)
{
gameObject.AddComponent<c>();
}
I have never done this before, but it came out so awesome that now I am going to add it to one of my games

unity destroy enemy destroying wrong one confused

i have tried everything to get the destroy to work Destroy(enemytrans) Destroy(enemy) Destroy(enemy.gameObject..... ect all abbreviations wont work.
can someone please help ???
i can coll with all objects and they do destroy but if 2 enemies are on screen i hit the one closest to me the other one will die because it was last spawned how can i destroy the one i jump on ?? mind efukd. :(
var Player : GameObject;
var Gravity:float = 2;
var speed:float = 2;
var enemytrans : Transform;
var enemy: GameObject;
public var jumped = false;
var anim : Animator;
function Start () {
while (true) {
yield WaitForSeconds (Random.Range(3, 0));
enemy = Instantiate(enemytrans).gameObject;
}
anim = GetComponent(Animator);
// Instantiate the prefab and put the gameObject into "theCube"
}
function Update () {
Player.transform.position.x = -4.325;
//the gravity function
if (jumped == false){
anim.SetFloat("hf",0.0);
}
if (Input.GetButtonDown("Fire1") && jumped==false){
fire();
jumped = true;
}
if(jumped==true){
anim.SetFloat("hf",1);
}
}
function OnCollisionEnter2D(coll: Collision2D) {
if(coll.gameObject.CompareTag("ground")){
anim.SetFloat("hf",0.0);
jumped=false;
}
if(coll.gameObject.CompareTag("enemy") && jumped==true){
fire();
jumped=true;
Destroy(enemy,1);***********************************************this line************
}
if(coll.gameObject.CompareTag("enemy") && jumped==false){
Destroy(Player);
}
}
function fire(){
Player.transform.Translate(Vector3(Input.GetAxis("Vertical") * speed * Time.deltaTime, 0, 0));
Player.rigidbody2D.velocity = Vector2(0,10);
}
Problem
You are destroying the last spawned GameObject, which you keep a reference to in the enemy variable.
Solution
You should destroy what you hit. Unity3D already gives you who you collided against so just use that information.
function OnCollisionEnter2D(coll: Collision2D)
{
if(coll.gameObject.CompareTag("enemy") && jumped==true)
Destroy(coll.gameObject);
}

unity 2d animation calling enemy animator through main script

i have added a animator to the enemy prefab and i want to make the animation change when i hit it
in the collision ( its **** out ) please can someone help me:(
i tried to make a new var eanim : Animator.... and call it in the start ect... but wont let me drag the ememy animator into the slot
how can i fix this please.
outline what i want to do i want to coll with the enemy and have the enemy that i hit change to death animation.
var Player : GameObject;
var Gravity:float = 2;
var speed:float = 2;
var enemytrans : Transform;
var enemy: GameObject;
public var jumped = false;
var anim : Animator;
function Start () {
while (true) {
yield WaitForSeconds (Random.Range(3, 0));
enemy = Instantiate(enemytrans).gameObject;
}
anim = GetComponent(Animator);
}
function Update () {
Player.transform.position.x = -4.325;
if (jumped == false){
anim.SetFloat("hf",0.0);
}
if (Input.GetButtonDown("Fire1") && jumped==false){
fire();
jumped = true;
}
if(jumped==true){
anim.SetFloat("hf",1);
}
}
function OnCollisionEnter2D(coll: Collision2D) {
if(coll.gameObject.CompareTag("ground")){
anim.SetFloat("hf",0.0);
jumped=false;
}
*********if(coll.gameObject.CompareTag("enemy") && jumped==true){ **
fire();
jumped=true;
anim.SetTrigger("isdead"); <<<<<<<<<<<<<----- this is what i need help with ------
}
if(coll.gameObject.CompareTag("enemy") && jumped==false){
Destroy(Player);
}
}
function fire(){
Player.transform.Translate(Vector3(Input.GetAxis("Vertical") * speed * Time.deltaTime, 0, 0));
Player.rigidbody2D.velocity = Vector2(0,10);
}
If you do anim.SetTrigger(..) in unity, you also need to setup that inside the Animator window for the corresponding gameobject.
So select your gameobject and go to window -> animator, add a trigger parameter (in your case with the name of "isdead") - and setup the transitions from the different states. So for example I create an empty state and set that as default, and then drag between that and my animation state in order to get the transitions.
Inside the transitions you just set default -> anim state to use the "isdead" parameter under the conditions. And on anim state -> default you set exit time as the condition.