- Home /
Spawning enemies randomly without collisions
So i found this script where you send an invisable object to detect if there is a collision and if their isnt then you spawn your enemy.
the first is for the invisable object
// -- TeleportTester.js -- var allClear = true;
function OnCollisionEnter() { allClear = false; }
The second one is the actual enemy
var testerPrefab : TeleportTester; // drag tester prefab into this var var wizardPrefab : Enemy;
function TeleportTester( targetPos : Vector3 ) : Enemy {
// test whether the target area is all clear:
var tester = Instantiate( testerPrefab, targetPos, Quaternion.identity );
yield new WaitForFixedUpdate();
if (tester.allClear) {
// all clear for wizard to appear!
var wizard = Instantiate( wizardPrefab, targetPos, Quaternion.identity );
return wizard ;
}
else {
// maybe the calling function should pick a new spot and try again
return null;
} }
whenever I try this though I get an error that tells me Enemy is not a known type in the enemy script at the teleporttester function. can anyone help?
your post could really use a touch-up. Please consider putting all the code in the code blocks and the text outside of it. Use the previewer to check while posting or editing such things please. It helps you get better answers ( or any ) and makes reading it for any 3rd parties much easier aswell. Thanks in advance!
Answer by cidmodder · Dec 05, 2010 at 09:11 PM
So i've got a functional script now that will spawn enemies randomly within whatever range. It still needs some tweaking but it works.
var allClear = true; var teleporter= gameObject; var range= 10; var player= transform; var wait = 5;
InvokeRepeating("ZombieSpawn",1,5);
function ZombieSpawn() { var i= Random.value* range; var j= Random.value* range; var k=Random.value* range; var pos=Vector3(i,j,k)+player.position;
Instantiate (teleporter, pos, Quaternion.identity);
} function OnCollisionEnter() { allClear = false; }
Answer by skovacs1 · Dec 02, 2010 at 07:16 PM
As The_r0nin said, Enemy is not a type/class within the context of your project. The solution they provided is not entirely correct however because "Just change these to GameObject" doesn't quite capture what I assume they mean to describe.
As was said, in order for Enemy to be a type/class, you must define it as such either by declaring class Enemy or by naming one of your javascripts to be Enemy.js (which Unity will implicitly declare a class for). Enemy would be a MonoBehaviour
.
The problem not addressed entirely is that your function TeleportTester
is trying to return something of type Enemy, but you do not return objects of type Enemy. You try to return the value from Instantiate
or a null
. Object.Instantiate
returns an Object
and if your function tries to return the result as type Enemy
, it will try to cast the Object
to the type Enemy
. Instantiate
will not really let you Instantiate a MonoBehaviour
as a MonoBehaviour
must be attached to something. Also, you cannot set a reference to a script instance in the editor through your variable wizardPrefab.
Additionally, you have a type TeleportTester
and a function TeleportTester
. This may still compile, but is a bad idea. You should consider renaming the function to TeleportTest
.
The simple fact of the matter is that what you are trying to do is very wrong and it would seem you misunderstand the concept of types and how prefabs work, so I will summarize the key points you seem to be missing:
- Prefabs are pre-built
GameObject
s with already defined attributes. You set them up in the editor. - Just because you named a prefab "Enemy", it is still a
GameObject
, just one with the name "Enemy". - When you
Instantiate
, it will create theObject
you pass it, if it is possible. Generally you willInstantiate
aGameObject
or someComponent
of aGameObject
.Instantiate
will still instantiate theGameObject
, but if you passed it a givenComponent
, it will get theComponent
from theGameObject
it just instantiated and return that. - If you want to
Instantiate
a prefab with a script attached, you merely need to attach the script to the prefab and the instantiated instance of the prefab will have it too. - If you want to add a script to something, you would need an instance of the
GameObject
or one of it's attachedComponent
s and would then callinstanceName.AddComponent(scriptType);
- If you want a reference to an instance of a script attached to something, you would need an instance of the
GameObject
or one of its attachedComponent
s and would then callinstanceName.GetComponent(scriptType);
That said, what The_r0nin likely meant was something like:
- change
wizardPrefab
to typeGameObject
- if you want to return an Enemy script attached to the
wizardPrefab
you just instantiated, you wouldreturn wizard.GetComponent(Enemy);
otherwise, change your function to return typeGameObject
and wherever you call it, adjust your code appropriately.
Thanks for this it does clear up some stuff. However I'm still haveing trouble on how to change the types. It still tells me gameObject is not a valid type and I'm not sure what I am missing
the Type GameObject has an upper-case g, whereas the derived variable gameObject refers to the GameObject instance that the thing in question either is or is attached to. Note how the upper-case one is a Type, while the other is a variable. This is the kind of thing that happens when you have things with the exact same or very similar names (hence my note about TeleportTester).
Ok so i've goten the type fixed except it tells me that UnityEngine.GameObject cannot be used in a generator. I'm really confused by this as well and Where do I put this script? I was going to put it on one already placed enemy. Is that right?
I've never seen that error myself, but I would guess that it is because you are trying to return a value from a co-routine. Your function is a co-routine because of the yield statement, but co-routines do not return values, co-routines return an IEnumerator, meaning that you either have a co-routine that does something or a function that returns your instance, but not both.
If you wanted to maintain the co-routine as a co-routine, you might consider setting some public variable outside of the function to be your instance. To avoid needing it to be a co-routine, you could ensure that it is only ever called in FixedUpdate.
Answer by The_r0nin · Dec 02, 2010 at 02:24 PM
"Enemy" is a class name (you can see this because your prefab is declared as that type: var wizardPrefab : Enemy;). This means that you need a script on your enemy items named "Enemy" or a separate class you declare in a script called "Enemy". Just like "GameObject" or "int" are types, "Enemy" is a typr that you haven't defined in your code, so it's telling you that you can't declare or return variables of type "Enemy". Just change these to GameObject and see if your scripts work...
I get this error when I change it to Game
Assets/Enemy Stuff/Zombie Spawn Script.js(4,50): BCE0101: Return type 'UnityEngine.GameObject' cannot be used on a generator. Did you mean 'IEnumerator'? You can also use 'System.Collections.IEnumerable' or 'object'.