- Home /
How can i delete an item from an array after being used? (So, it won't be repeated)
Hi, this is my first question in Unity Answers.
Recently a pair of good users helped me in giving me the base code for a script to spawn gameObjects in a list of places, and those places are transforms of other gameObjects i put in my scene, so the script spawn a deffined object (in the case of my game, a page the player needs to collect later) in one of the places i setup in the array via inspector...and the place is selected randomly by the script.
It just works fine, but...only one problem, the thing is that the script sometimes decides to use the same place again to spawn the new object, this causes sometimes the spawning of a seconf, third object and beyond...in the same place..., and this unfortunately doesn't look good for anyone.
Then i was researching a bit, to know ways of preventing this: build a script to check and remove the duplicates if these are were spawned in the same place? and leave only 1 at that place? and respawn or move the deleted duplicates to some of the other places?(maybe too difficult and the same result)
So i thought about making my script to delete the entries of the array with the places transforms as it uses them, in other words:
Spawn an object in one of the listed places/transforms , and then, delete temporarily just the place that was used...so in the next spawn, the script won't use that place again...
So, that's it!, i only need this and the script would be perfect
I'll leave you the code in Javascript:
import System.Collections.Generic;
var numberOfItems: int;
var newLevel: boolean;
static var loadedLevelName : String;
private var i : int;
var possibleSpawnPositions: Transform[];
var objectTypeToSpawn: GameObject;
function SpawnNewObject()
{
var spawnPointReference: Transform = GetSpawnPointReference();
var newObject: Transform = Instantiate(objectTypeToSpawn,
spawnPointReference.position, spawnPointReference.rotation) as Transform;
}
function GetSpawnPointReference():Transform
{
var randomIndex: int = Random.Range(0, possibleSpawnPositions.Length);
return possibleSpawnPositions[randomIndex];
}
function Start ()
{
if(newLevel)
{
switch(Application.loadedLevelName)
{
case "Mundo Alternativo":
numberOfItems = 8;
break;
default:
Debug.Log("Something is wrong here");
break;
}
for(i=0; i < numberOfItems; i++)
{
SpawnNewObject();
}
newLevel = false;
}
}
function Update ()
{
}
Thanks in advance!
Thanks guys!, well, i tried all the methods, i couldn't use pickle chips' because i don't know anything about C#, i'm pretty sure it only requires a little adaptation to do the work but i don't know where, i'm just getting started in javascript, sorry
I tried a couple of games using $$anonymous$$ukabr code which gave me no errors and it was excelent
Now, although i have solved my problem, i'll try using robertbu suggestions because i want to learn how to it myself for next time hehe, but thanks to all anyway!
Now i can sleep in peace : P, thanks a lot seriously!
Answer by Mukabr · Jun 10, 2013 at 04:28 AM
Try not using Arrays in c# and Javascript, use lists.
This should work, i'm saving the randomised Transform, and than i'm removing it from the list. Than, i return that Transform that we saved in the toReturn variable.
import System.Collections.Generic;
var numberOfItems: int;
var newLevel: boolean;
static var loadedLevelName : String;
private var i : int;
var possibleSpawnPositions : List.< Transform >;
var objectTypeToSpawn: GameObject;
function SpawnNewObject()
{
var spawnPointReference: Transform = GetSpawnPointReference();
var newObject: Transform = Instantiate(objectTypeToSpawn,
spawnPointReference.position, spawnPointReference.rotation) as Transform;
}
function GetSpawnPointReference():Transform
{
var randomIndex: int = Random.Range(0, possibleSpawnPositions.Count);
var toReturn:Transform = possibleSpawnPositions[randomIndex];
possibleSpawnPositions.RemoveAt(randomIndex);
return toReturn;
}
function Start ()
{
if(newLevel)
{
switch(Application.loadedLevelName)
{
case "Mundo Alternativo":
numberOfItems = 8;
break;
default:
Debug.Log("Something is wrong here");
break;
}
for(i=0; i < numberOfItems; i++)
{
SpawnNewObject();
}
newLevel = false;
}
}
function Update ()
{
}
Hey $$anonymous$$ukabr, sorry for disturbing again, but know i know a bit more about the process, i was thinking that i would need also to get the objects to spawn from a list, and don't repeat eventually, i tried to make that reusing the spawnpoints reference, but according to unity, i'm making the wrong use of Instantiate, it tells me:
BCE0023: No appropriate version of 'UnityEngine.Object.Instantiate' for the argument list '(System.Collections.Generic.List., UnityEngine.Vector3, UnityEngine.Quaternion)' was found.
And this is how the script looks like now:
import System.Collections.Generic;
var numberOfItems: int;
var newLevel: boolean;
static var loadedLevelName : String;
private var i : int;
var possibleSpawnPositions : List.< Transform >;
//var objectTypeToSpawn: GameObject;
var possibleObjectsToSpawn : List.< GameObject >;
function SpawnNewObject()
{
var spawnPointReference: Transform = GetSpawnPointReference();
//var newObject: Transform = Instantiate(objectTypeToSpawn, spawnPointReference.position, spawnPointReference.rotation) as Transform;
var objectsReference: GameObject = GetObjectsReference();
var newObjects: GameObject = Instantiate(possibleObjectsToSpawn, spawnPointReference.position, spawnPointReference.rotation) as Transform;
}
function GetObjectsReference():GameObject
{
var randomIndex: int = Random.Range(0, possibleObjectsToSpawn.Count);
var toReturn:GameObject = possibleObjectsToSpawn[randomIndex];
possibleObjectsToSpawn.RemoveAt(randomIndex);
return toReturn;
}
function GetSpawnPointReference():Transform
{
var randomIndex: int = Random.Range(0, possibleSpawnPositions.Count);
var toReturn:Transform = possibleSpawnPositions[randomIndex];
possibleSpawnPositions.RemoveAt(randomIndex);
return toReturn;
}
function Start ()
{
if(newLevel)
{
switch(Application.loadedLevelName)
{
case "$$anonymous$$undo Alternativo":
numberOfItems = 8;
break;
/*default:
Debug.Log("Something is wrong here");
break;*/
}
for(i=0; i < numberOfItems; i++)
{
SpawnNewObject();
}
newLevel = false;
}
}
function Update ()
{
}
Ok, hope you can help me again, thanks!
I believe it's because in the Instantiate function, you have a List where you should have a Gameobject:
var newObjects: GameObject = Instantiate(possibleObjectsToSpawn, spawnPointReference.position, spawnPointReference.rotation) as Transform;
possibleObjectsToSpawn is a list, so you probably just need to add the index after it (possibleObjectsToSpawn[index])so it references the gameobject.
However, I could be wrong, because I'm not very familiar with lists in javascript, since, again, I'm more familiar with c#
Answer by robertbu · Jun 10, 2013 at 04:21 AM
If you want to solve your problem by using a list and removing random entries, you can use a .NET generic List. There was a post yesterday that used a List to pull out random numbers. Your implementation would be similar but you would use:
var randomTransforms = new List.<Transform>();
And then you would need to add all the elements from your possibleSpawnPositions array.
http://answers.unity3d.com/questions/471420/how-to-generate-random-number-that-will-not-be-rep.html
But I think you are assigning the transforms in the Inspector. It might be easier to shuffle the transforms and then pull them out in order. The easiest shuffle algorithm is to just swap random elements a number of times. Some example code here:
http://answers.unity3d.com/questions/199051/how-to-shuffle-numbers.html
Then you keep an index of the next element to process and increment it when you "remove" and element. When the index is equal to the length of the array, all elements will have been removed.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
how do i make an object spawn randomly in an area? 1 Answer
Random spawn of object on trigger 3 Answers