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

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

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

Destroy a game object after it leaves the view of the camera in Unity

I'm currently making a game in Unity where I'm trying to get destroy the clones of a prefab only after they leave the view of the camera only after they already entered the view of the camera in the first place. However, for some reason, my code is instantly destroying the clones as soon as their instantiated. Does anyone know how I could solve this problem?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InteractControl : MonoBehaviour
{
Rigidbody2D rb;
GameObject target;
float moveSpeed;
Vector3 directionToTarget;
// Use this for initialization
void Start()
{
target = GameObject.Find("White Ball");
rb = GetComponent<Rigidbody2D>();
moveSpeed = 3f;
}
// Update is called once per frame
void Update()
{
MoveInteract();
OnBecameVisible();
}
/*void OnTriggerEnter2D(Collider2D col)
{
switch (col.gameObject.tag)
{
case "ColouredBall Highress":
BallSpawnerControl.spawnAllowed = false;
Destroy(gameObject);
target = null;
break;
case "Star":
Collision collision = new Collision();
break;
}
} */
void MoveInteract()
{
if (target != null)
{
if(ScoreScript.scoreValue > 3)
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
else
{
directionToTarget = new Vector3(0, -1, 0);
rb.velocity = new Vector2(0, directionToTarget.y * moveSpeed);
}
}
else
rb.velocity = Vector3.zero;
}
void OnBecameInvisible()
{
if (gameObject.tag == "ColouredBall Highress")
{
Destroy(gameObject);
}
if (gameObject.tag == "Star")
{
Destroy(gameObject);
}
}
void OnBecameVisible()
{
if (gameObject.tag == "ColouredBall Highress" || gameObject.tag == "Star")
{
OnBecameInvisible();
}
}
}
I tried to solve the problem by first requiring the objects to become visible in order for them to be able to get destroyed when out of view of the camera. In short I'm looking for the OnExit collider version for on OnBecameInvisible. I guess I could make the whole screen a collider and use on Exit collider on it. Does someone possibly also know how I could make a collider that covers the camera view?
It is because you call OnBecameInvisible() from OnBecameVisible. So when they are visible they get destroyed.
Also your code is doing so many redundant things you also call OnBecameVisiblefrom Updateetc.
You can simply use this instead:
Renderer m_Renderer;
void Start()
{
m_Renderer = GetComponent<Renderer>();
}
void Update()
{
//It means object is NOT visible in the scene if it is false is visible
if (!m_Renderer.isVisible)
{
Destroy(gameObject);
}
}
Note that: Destroying/Instantiating objects are not the best practices at this circumstance. Because it causes garbage collector to work a lot and it is expensive and can slow down your game. You can use object pooling instead. It basically puts object which are not in the field of view into an object pool and you keep their references and can use them later. Therefore, it is less costly than your method.
You are calling OnBecameVisible every frame, so basically the first frame the object destroys itself. Deleting it from Update should do the trick, Unity already calls it for you.

Unity child object sometimes jumps to vector3(0,0,0)

I have a very annoying bug, and I can't get rid of it.
The situation is, that I have a parent with the following script attached, and a trigger box2d collider. It has a child, with a rigidbody2d(kinematic, gravity=0, freeze position x, and rotation z), a sprite renderer and a polygon collider (with 4 edges).
My problem is, when the scene is loaded, sometimes my child objects (always random how much of them and which ones), jumps to transform.position 0,0,0.
I link the script, that is attached to the parent
using UnityEngine;
using System.Collections;
public class FallingSpikeHazard : MonoBehaviour
{
public GameObject spike;
private Rigidbody2D spikeRigidbody;
[SerializeField]
private Vector3 startPosition;
void Awake ()
{
startPosition = spike.transform.localPosition;
}
void Start ()
{
spikeRigidbody = spike.GetComponent<Rigidbody2D> ();
Helper.JustReset += ResetMe;
Invoke ("CheckPosition", Time.deltaTime);
}
void CheckPosition ()
{
if (spike.transform.localPosition != startPosition) {
Debug.LogError ("t1" + spike.transform.localPosition);
spike.transform.localPosition = startPosition;
Debug.LogError ("t2" + spike.transform.localPosition);
}
}
void OnDestroy ()
{
Helper.JustReset -= ResetMe;
}
void ResetMe ()
{
spikeRigidbody.gravityScale = 0;
spikeRigidbody.isKinematic = true;
if (startPosition != Vector3.zero) {
spike.transform.localPosition = startPosition;
}
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag.Equals ("Player")) {
spikeRigidbody.isKinematic = false;
spikeRigidbody.gravityScale = 1;
}
}
}
Events are not called, in other hand, if I disable the script, it keeps happening. Nothing have reference to these GameObjects. I don't have animations, or animator attached.
What could cause my problem?
You need to have a Rigidbody2D component in the parent GameObject in order for the OnTriggerEnter function to be called.

Respawn an enemy prefab after its destroyed

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.

Create a copy of an gameobject

How do you create a copy of an object upon mouse click in Unity3D?
Also, how could I select the object to be cloned during run-time? (mouse selection preferable).
function Update () {
var hit : RaycastHit = new RaycastHit();
var cameraRay : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast (cameraRay.origin,cameraRay.direction,hit, 1000)) {
var cursorOn = true;
}
var mouseReleased : boolean = false;
//BOMB DROPPING
if (Input.GetMouseButtonDown(0)) {
drop = Instantiate(bomb, transform.position, Quaternion.identity);
drop.transform.position = hit.point;
Resize();
}
}
function Resize() {
if (!Input.GetMouseButtonUp(0)) {
drop.transform.localScale += Vector3(Time.deltaTime, Time.deltaTime,
Time.deltaTime);
timeD +=Time.deltaTime;
}
}
And you'll want this to happen over course of many calls to Update:
function Update () {
if(Input.GetMouseButton(0)) {
// This means the left mouse button is currently down,
// so we'll augment the scale
drop.transform.localScale += Vector3(Time.deltaTime, Time.deltaTime,
Time.deltaTime);
}
}
The simplest way (in c#) would be something like this:
[RequireComponent(typeof(Collider))]
public class Cloneable : MonoBehaviour {
public Vector3 spawnPoint = Vector3.zero;
/* create a copy of this object at the specified spawn point with no rotation */
public void OnMouseDown () {
Object.Instantiate(gameObject, spawnPoint, Quaternion.identity);
}
}
(The first line just makes sure there is a collider attached to the object, it's required to detect the mouse click)
That script should work as is, but I haven't tested it yet, I'll fix it if it doesn't.
If your script is attached to a GameObject (say, a sphere), then you can do this:
public class ObjectMaker : MonoBehaviour
{
public GameObject thing2bInstantiated; // This you assign in the inspector
void OnMouseDown( )
{
Instantiate(thing2bInstantiated, transform.position, transform.rotation);
}
}
You give Instantiate( ) three parameters: what object, what position, how is it rotated.
What this script does is it instantiates something at the exact position & rotation of the GameObject this script is attached to. Oftentimes you will need to remove the collider from the GameObject, and the rigidbody if there is one. There a variations in ways you can go about instantiating things, so if this one doesn't work for you I can provide a different example. : )