Spawning Enemy issue - c#

I'm trying to have my game spawn enemies when ever the player reaches a way point.
Right now, I have this functionality working. When my player gets to the first way, the enemies spawn. He only moves on once he has killed all of the enemies on the screen are dead. However, when he gets to the second way point, no enemies spawn.
Right now, in my collision class I call the following line of code:
Destroy(gameObject)
Whilst this work for the first way point, the second one wont spawn anything as the game object my collision class has been attached to has been destroyed. However, all of my enemies are prefabs and I thought the destroy function would only destroy that instance of the prefab. No matter when you called the instantiate method, it would only destroy that instance.
I'm spawning my enemies with the following method:
public GameObject SpawnEnemies()
{
Vector3 _position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
// instantiate particel system
Instantiate(_particle, _position, Quaternion.identity);
_clone = (GameObject)Instantiate(_enemy, _position, transform.rotation);
_ai = _clone.GetComponent<HV_BaseAI>();
_ai._waypoints = _wayPoints;
return _clone;
}
Then I'm finding out how many of the enemies are still alive with the following code in my collision method:
GameObject g, f; // enemies I want to spawn
g = GameObject.FindGameObjectWithTag("SectionController");
f = GameObject.FindGameObjectWithTag("SectionController");
HV_SectionController tempSectionControllerGroundEnemies, tempSectionControllerFlyingEnemies;
tempSectionControllerGroundEnemies = g.GetComponent<HV_SectionController>();
tempSectionControllerFlyingEnemies = f.GetComponent<HV_SectionController>();
tempSectionControllerGroundEnemies._numberOfGroundEnemies.Remove(gameObject); // remove enemies from list
tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Remove(gameObject);
//Destroy(gameObject);
_numberOfGroundEnemies = tempSectionControllerGroundEnemies._numberOfGroundEnemies.Count;
_numberOfFlyingEnemies = tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Count;
Then when I want to move on I do the following check:
if (_groundEnemiesRemaining == 0)
{
MoveToNextSection();
_sectionStartTime = Time.time;
}
i know the above line is checking only one type of enemy at the moment, but its the ground enemies I'm having issues with at the moment.
Does anyone know how I can delete the enemy prefab I'm spawning from my first section, once they've been hit, then have it respawn at the next section without the error:
The object of type 'GameObject' has been destroyed but you are still
trying to access it.

My guess would be that the gameobjects are being "destroyed" by two different collision events. First one destroys it, second throws the error.
What I've done in similar situations is put the Destroy code within the object being destroyed. Then from within your collision class, use gameObject.SendMessage(string) to send a message to the actual object, which destroys it.
Without seeing further code I can't speculate as to the origin of the error, but the above is my best guess. SendMessage can also take a DontRequireReceiver parameter, so it won't pop an error if two collision events try to send it a message.

Instead of destroying them u can just disable them using gameObject.SetActive() !

Related

Getting more than one possition though code (unity c#)

i made a "turret" in unity that shoots automatically on enemies it works with one enemy but when i put 2 it shoots in the midle of then dont know why it does that
public transform enemy;
public void Update() {
enemy = Gameobject.FindgameObjectWithTag("Enemy").getComponent<Transform>;
//just put the getting the possition part because the shooting works just fine
}
Your script is refreshing the enemy position every Update() iteration.
Try to have the turret stick to the enemy until it gets out of range, or until it is dead. Before doing your variable assignation, check if enemy != null, if it is the case, then you can write :
enemy = Gameobject.FindgameObjectWithTag("Enemy").getComponent<Transform>;
Also, try to avoid refreshing every Update() call, instead, use a different function that you call every half second.
I recommend you checking this project by Brackeys, that handles the situation perfectly. Here
GLHF

Insinuated gameObject won't get destroyed after OnCollideEnter?

I want gameObject1 to get destroyed after it collides with gameObject2.
gameObject1 is a non-kinematic rigid body and a nav agent with its destination being gameObject2, while gameObject2 is an empty object. Both of them have box colliders, and neither has Is Trigger on. gameObject1 succeeds in going towards gameObject2; however, they don't seem to be colliding. Instead of being destroyed, gameObject1 doesn't stop moving. What went wrong?
void OnCollideEnter(Collision col)
{
if (col.gameObject.tag == "deleter")
{
Debug.Log("triggerdel"); //this doesn't show up on console.
Destroy(gameObject);
}
}
Commenters have suggested using OnCollisionEnter, which is a Unity Message that is called whenever things collide. What you have now is not a Unity Message so it will never be called.
As an aside, it's a good idea to use OnCollisionStay instead. OnCollisionStay is called every single frame the object is being collided with, so in case of any bug the object will destroy in the next frame. OnCollisionEnter is only called for one frame, so if something goes wrong (which is very unlikely), the object will try to be destroyed again in the next frame.

Unity / Cloned Enemies don't work as intended / C#

I have a terrain with two enemies that I placed and a plane that I have given a script to spawn enemies continuously (basically wave defence without towers)
The two enemies I placed work as intended, killing them will give experience and coming into contact with them cost the player some health.
But the ones spawned by my scripted plane don't grant experience on a kill, the only reason they do health damage on contact is because I set the collision to look for a tag of "Enemy" which they have.
# THE SCRIPT FOR THE ENEMY-SPAWNING PLANE
IEnumerator Spawner()
{
yield return new WaitForSeconds(startWait);
while(!stop)
{
randEnemy = Random.Range(0, 2);
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), 2, Random.Range(-spawnValues.z, spawnValues.z));
Instantiate(enemies[randEnemy], spawnPosition + transform.TransformPoint(0, 0, 0), gameObject.transform.rotation);
yield return new WaitForSeconds(spawnWait);
}
}
# THE SCRIPT WHICH CALLS FOR EXPERIENCE TO BE GIVEN (Enemy as GameObject)
void Dead()
{
_characterXP.GainExp(120);
Destroy(gameObject);
}
# THE SCRIPT WHICH GIVES THE PLAYER EXPERIENCE (CharacterXP as GameObject)
public void GainExp(float expThatWasGained)
{
CurrentExp += expThatWasGained;
}
I'm still pretty new to Unity and C# so if there is anything else that's needed I can provide it, I have checked all relevant objects to make sure the relevant things are connected correctly, and if they didn't work then it would affect the original enemies, the issue is only in regards to the spawned enemies that get named ENEMY(Clone)
EDIT
The Prefab ^
The Pre-Spawned Enemy Mid-Game^
The Clone Enemy Mid-Game^
You cannot assign scene objects to prefab property fields. You can only assign other prefab (or assets) into the prefab property slots.
To assign a scene object to your enemy script, you need to find it at runtime.
In your enemy's Start method, find the fpscontroller
void Start()
{
_characterXP = GameObject.FindObjectOfType<FPSController>();
}
I think this will solve your problem
Not the most intelligent way of doing this, but I was on a tight schedule and the method works.
I created two prisons outside of the playable area and put one of each enemy inside of it and then referred to these two trapped individuals in my Monster Spawner (The Plane) instead of the prefabs and now I gain the right amount of exp per kill.

Unity 2D c# scripting, Spawnobject at mouseposition when down

I'm fairly new to C#(basically first time using, having to script for this project), I'm trying to teleport (from off screen to on) an object in my game(i'm using a cube for a simple object, in which I will use inkscape to create a 'better' object in its place when it works)will add cube2 later, just focusing on getting this working.
The aim is to teleport an object to where to my 'Bumber' prefab (the floor), based upon the player clicking a position on the 'Bumber' and spawn where the mouse position was on that 'Bumber' and if not on the 'Bumber' don't spawn at all(haven't go to bumber check yet), which will trigger an event, causing the player to lose.
When I was playing the game before, when I clicked, the cube would only despawn and then throw an error at me and not spawn in at the cursors position
I have my 'cube' prefab (dragged from hierarchy into Resources folder, which has the spawn script component). When I go back into unity, I get the error:
(32, 37) the name 'cube' doesn't exist in current context
(32,25) The best overloaded method match for `UnityEngine.Object.Instantiate(UnityEngine.Object, UnityEngine.Vector3, UnityEngine.Quaternion)' has some invalid arguments
(32, 25) Argument #1' cannot convertobject' expression to type `UnityEngine.Object'
I've tried for hours to fix this script, looking at unity database and to no avail.
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour {
public int trapCount;
void Start ()
{
trapCount = 0;
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
}
void Update ()
{
if (Input.GetMouseButtonDown (0))
{
Spawner ();
trapCount++;
}
}
void Spawner()
{
Vector3 mousePosition = Input.mousePosition;
transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(trapCount == 0)
{
Instantiate(cube, transform.position, Quaternion.identity); //getting error here, I don't care about rotation value, don't want to rotate at all, but doesn't like it, if it doesn't have anything there.
}
else if (trapCount >= 1)
{
Debug.Log("Trap limit reached!");
}
}
}
C# please, also, if you could, explain what you're doing, thank you kindly!
Always (well, almost always) believe what the error messages tell you.
(32, 37) the name 'cube' doesn't exist in current context
You get this for the line
Instantiate(cube, transform.position, Quaternion.identity);
At that point there is no cube anywhere within the scope of the method. You have your
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
in your Start() method, but it only exist within that method. It's not a member of the class for example. Making it a member would solve that problem.
And that is more than likely also the cause of the subsequent errors. If it doesn't know what a cube is, it has no idea what to do with it as an argument of Instantiate().
If you're entirely new to C# the biggest favour you could do yourself is to pick up a good book. Unity will allow you to get pretty far by hacking away at it, but there will be a point where there's simply no substitute for learning the language. It will help you tremendously.
Good luck.

Why aren't my projectiles drawn on the screen?

So I am developing a simple C# program that allows you to move around a graphic and have it fire bullets that travel from the player to the position of the mouse at the time of the mouse click. I'm still new to C# but have some experience with Java and Python.
I am fully able to move my character with the WASD but unable to get the bullets to be drawn let alone get them to move as they update.
Where might the bug be?
The projectile object's draw method?
The Game1 class's update method for the user input?
The projectile's object's direction setting?
Here is the full code:
http://pastebin.com/j5QVLKU3
I left the player class out, but it has nothing more then a few player variables like health.
For start, could you move
mouseStateCurrent = Mouse.GetState();
if (mouseStateCurrent.LeftButton == ButtonState.Pressed)
{
if (mouseStatePrevious.LeftButton != ButtonState.Pressed)
{
AddProjectile(player.positionPlayer);
mouseStatePrevious = mouseStateCurrent; //<-- This line
}
}
//<-- Here
Once you press your button, you're never gonna enter that if again.
Edit 1
Furthermore, this in your Projectile
Player playerObject = new Player();
Game1 gameObject = new Game1();
has to look like:
Player playerObject;
Game1 gameObject;
public Projectile(Player player, Game1 game)
{
playerObject = player;
gameObject = game;
}
Since you're using those only to get the origin and destination for the bullet, it would be better if you just calculated those outside, and passed them with the initialize. (because it would remove Projectile's need to know what Game1 and Player objects looked like)
You could also completely remove the Initialize method and just use Projectile's constructor, that seems more natural. (if you use the constructor for this, then you know that any time you have an instance, you can use it without having to call additional methods)
Slight edit
I don't think you really need the bulletOrigin in your Projectile class, you could just use the position, and move it from there to the bulletDestination.
Also, Vector2 class is made with operator overloaded methods, so you could use
positionBullet += directionLine*velocity;
instead of
positionBullet = Vector2.Add(positionBullet, directionLine * velocity);
Other than those, your code seems fine! Tell me if it still doesn't work after these changes. Also, use your debugger to step into it, see if you can find anything interesting. :)

Categories