I am trying to make my character pickup and drop with the same key "space" in unity but since void update happens so fast then when I drop a monster then it instantly picks it up.
void Update() {
if (Input.GetKeyDown("space") /*( || Input.GetMouseButtonDown(1))*/) {
if (map.selectedUnit.GetComponent<Unit>().carrying) {
print("DROP space");
map.selectedUnit.GetComponent<Unit>().carrying = false;
}
// pick up monster while on top of it
else {
for(int i = 0; i < map.monsterList.Count; i++) {
if (map.monsterList[i].GetComponent<Monsters>().tileX == map.selectedUnit.GetComponent<Unit>().tileX &&
map.monsterList[i].GetComponent<Monsters>().tileY == map.selectedUnit.GetComponent<Unit>().tileY &&
map.occupationArray [map.monsterList[i].GetComponent<Monsters>().tileX, map.monsterList[i].GetComponent<Monsters>().tileY] == true) {
print("PICKUP space");
map.selectedUnit.GetComponent<Unit>().carrying = true;
}
}
}
}
}
Is there a way to fix this or do I have to put pickup key as other key. I have been thinking if I add 1 second between each "space" key. So you can press space only once in one second and it could somehow fix this.
How about using GetKeyUp instead.
GetKeyUp is called only once when you released key.
See this doc
https://docs.unity3d.com/ScriptReference/Input.GetKeyUp.html
I end up using seconds methods in my code. This means that it waits 0.25 sec before you can pick up or drop again. Now this prevents it to loop all the time. If someone else has better solution then please provide it. For now I am using this.
void Update() {
// there is 0.25 second between that player can PickUp again or Drop again
if (!map.selectedUnit.GetComponent<Unit>().carrying) {
timeLeftToPressAgain -= Time.deltaTime;
timeLeftToPressAgain = Mathf.Max(timeLeftToPressAgain, -0.25f);
}
else {
timeLeftToPressAgain += Time.deltaTime;
timeLeftToPressAgain = Mathf.Min(timeLeftToPressAgain, 0.25f);
}
if (Input.GetKeyDown("space") /*( || Input.GetMouseButtonDown(1))*/) {
// while carrying the time builds up for player to Drop and vice versa in PickUp
if (map.selectedUnit.GetComponent<Unit>().carrying && timeLeftToPressAgain > 0) {
map.selectedUnit.GetComponent<Unit>().carrying = false;
timeLeftToPressAgain = 0.25f;
}
// pick up monster while on top of it
else if (!map.selectedUnit.GetComponent<Unit>().carrying && timeLeftToPressAgain < 0) {
for(int i = 0; i < map.monsterList.Count; i++) {
if (map.monsterList[i].GetComponent<Monsters>().tileX == map.selectedUnit.GetComponent<Unit>().tileX &&
map.monsterList[i].GetComponent<Monsters>().tileY == map.selectedUnit.GetComponent<Unit>().tileY &&
map.occupationArray [map.monsterList[i].GetComponent<Monsters>().tileX, map.monsterList[i].GetComponent<Monsters>().tileY] == true) {
map.selectedUnit.GetComponent<Unit>().carrying = true;
timeLeftToPressAgain = -0.25f;
}
}
}
}
}
Just to complete it: You could have done something like this:
bool pressedSpace = false;
void Update() {
pressedSpace = true; // Only called once
if (!pressedSpace && Input.GetKeyDown("space") /*( || Input.GetMouseButtonDown(1))*/) {
if (map.selectedUnit.GetComponent<Unit>().carrying) {
print("DROP space");
map.selectedUnit.GetComponent<Unit>().carrying = false;
}
// pick up monster while on top of it
else {
for(int i = 0; i < map.monsterList.Count; i++) {
if (map.monsterList[i].GetComponent<Monsters>().tileX == map.selectedUnit.GetComponent<Unit>().tileX &&
map.monsterList[i].GetComponent<Monsters>().tileY == map.selectedUnit.GetComponent<Unit>().tileY &&
map.occupationArray [map.monsterList[i].GetComponent<Monsters>().tileX, map.monsterList[i].GetComponent<Monsters>().tileY] == true) {
print("PICKUP space");
map.selectedUnit.GetComponent<Unit>().carrying = true;
}
}
}
}
}
And then after a little wait you can reset pressedSpace to false.
Related
i have a strange problem. My Code works fine. Everything works as it should until it goes the last time through a foreach loop. The code:
public List<string> waveInput = new List<string>(); //die Eingabe der Welle als Zeichenfolge
public List<GameObject> enemyTyps = new List<GameObject>();
public List<Vector3> path = new List<Vector3>();
public GameObject tempPathStart;
public int currentWave = 0;
public int currentAmountOfEnemies;
private int spawnAmountOfEnemies;
private double spawnDelay;
private List<GameObject> enemyToSpawn = new List<GameObject>();
void Start() {
path.Add(tempPathStart.transform.position);
StartCoroutine(function());
}
IEnumerator function() {
while(waveInput.Capacity >= currentWave) {
if(waveInput[currentWave] == "" && currentAmountOfEnemies <= 0) {
currentWave++;
enemyToSpawn.Clear();
spawnAmountOfEnemies = 0;
} else if(currentAmountOfEnemies <= 0) {
string _substring = waveInput[currentWave].Substring(0, waveInput[currentWave].IndexOf(";") + 1);
ManageSubstring(_substring);
for(int i = 0; i < spawnAmountOfEnemies; i++) {
foreach(GameObject element in enemyToSpawn) {
this.SpawnEnemy(element);
yield return new WaitForSeconds((float)spawnDelay);
}
}
}
}
}
void ManageSubstring(string _substring) {
string _tempStringAmount = "";
string _tempStringDelay = "";
string _tempStringType = "";
bool _switchAmountDelay = false;
for(int i = 0; i < _substring.Length; i++) {
char c = _substring[i];
if(c >= '0' && c <= '9') {
if(_switchAmountDelay) {
_tempStringDelay += c;
} else {
_tempStringAmount += c;
}
} else if(c == ';') {
} else if(c == '.') {
_tempStringDelay += c;
} else {
_switchAmountDelay = true;
_tempStringType += c;
}
}
spawnDelay = double.Parse(_tempStringDelay);
spawnAmountOfEnemies = int.Parse(_tempStringAmount);
foreach(char c in _tempStringType) { //die Buchstaben in GameObjekte / Gegner umwandeln
int _tempConvertedInt = TranslateStringToInt(c);
enemyToSpawn.Add(enemyTyps[_tempConvertedInt]);
}
}
int TranslateStringToInt(char pToConvertChar) {
List<char> _alphabet = new List<char>() {'a','b','c','d','e','f','g','h','i','j','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
return _alphabet.IndexOf(pToConvertChar);
}
void SpawnEnemy(GameObject prefab) {
currentAmountOfEnemies++;
GameObject e = Instantiate(prefab) as GameObject;
e.transform.position = path[0];
}
the very strange thing as i already said is: the code works, even the line works fine until it goes through the last time. Then Unity crashes and i have no idea what i should do. If some more code is needed for context just say.
Thanks for every answer!
I just pulled your script into the debugger and stepped through the last iteration:
When the iteration is over, it goes back into the while() loop which encloses the whole body of function().
The while condition remains true since waveInput.Capacity is greater than the currentWave (still zero).
The if(waveInput[currentWave] == "" && currentAmountOfEnemies <= 0) is false since the waveInput[] array has an element zero which is not "", and the enemycount was not reset yet.
the else if(currentAmountOfEnemies <= 0) condition is also false since the current amount was not reset.
nothing more in the while-loop, nothing chagned, you have an endless-loop, which never hits a yield return. This locks up the Update() cycle of Unity and only allow killing.
I have a Unity game where a character punches. I have 3 punch animations and when I press F, punch 1 animation plays, and counter goes up. Then next time player pressed F, punch 2 animation plays and counter goes up. Again, next time player pressed F, punch 3 animation plays and counter goes back to 0. However, each animation has different play time and when punch 1 plays, player can quickly press F button and counter will go up to 3 and then to 0 and only 1 or 2 animations will play.
I've tried using coroutines, counter goes up by that amount of time, but the animation isn't playing.
Coroutine code:
{
isPunching = Input.GetKeyDown(KeyCode.F);
if(isPunching == true && punchCounter == 0)
{
StartCoroutine("waitTime");
}
else if (isPunching == true && punchCounter == 1)
{
punchCounter = 2;
}
else if (isPunching == true && punchCounter == 2)
{
punchCounter = 3;
}
else if (punchCounter == 3)
{
punchCounter = 0;
}
}
IEnumerator waitTime()
{
yield return new WaitForSeconds(0.2f);
punchCounter = 1;
}
Original code:
{
isPunching = Input.GetKeyDown(KeyCode.F);
if(isPunching == true && punchCounter == 0)
{
punchCounter = 1;
}
else if (isPunching == true && punchCounter == 1)
{
punchCounter = 2;
}
else if (isPunching == true && punchCounter == 2)
{
punchCounter = 3;
}
else if (punchCounter == 3)
{
punchCounter = 0;
}
}
I want to make a waiting time for when F is pressed, that animation will play and then counter will go to 2, even though player pressed the button more than 1. There is a chance player will be bashing buttons.
Check out animation event here:
https://docs.unity3d.com/ScriptReference/AnimationEvent.html
and Youtube tutorial from here:
https://www.youtube.com/watch?v=-IuvXTnQS4U
Place the event to the animation call method when you want player to be able to punch again.
public bool isAnimating;
public void AnimationEvent()
{
isAnimating = false;
}
void Update()
{
isPunching = Input.GetKeyDown(KeyCode.F);
if(isAnimating == false && isPunching && punchCounter == 0)
{
punchCounter = 1;
isAnimating = true;
}
else if (isAnimating == false && isPunching && punchCounter == 1)
{
punchCounter = 2;
isAnimating = true;
}
else if (isAnimating == false && isPunching && punchCounter == 2)
{
punchCounter = 3;
isAnimating = true;
}
else if (punchCounter == 3)
{
punchCounter = 0;
}
}
I have code elsewhere that puts a pointer in a position based on the AttackInfo.Target value. I also have code that determines whether my characters are dead, using the Stats[lifeStatus] array reference, where 0 is dead and 1 is alive.
I want the Target to skip over the values of dead characters so you can only select living characters to attack. However, it seems to have no effect.
Why does it not work?
else if (state == CHARACTER1TARGETCHOICE) {
attackButton.enabled = false;
abilitiesButton.enabled = false;
itemButton.enabled = false;
defendButton.enabled = false;
fleeButton.enabled = false;
if (pointer.GetComponent<SpriteRenderer> ().enabled == false) {
pointer.GetComponent<SpriteRenderer> ().enabled = true;
}
if (Input.GetKeyDown (KeyCode.UpArrow)) {
character1AttackInfo.Target -= 1;
bool checkTargetAlive = false;
while (checkTargetAlive) {
if (enemy1Stats [lifeStatus] == 0 && character1AttackInfo.Target == 1) {
character1AttackInfo.Target -= 1;
} else if (enemy2Stats [lifeStatus] == 0 && character1AttackInfo.Target == 2) {
character1AttackInfo.Target -= 1;
} else if (enemy3Stats [lifeStatus] == 0 && character1AttackInfo.Target == 3) {
character1AttackInfo.Target -= 1;
} else if (enemy4Stats [lifeStatus] == 0 && character1AttackInfo.Target == 4) {
character1AttackInfo.Target -= 1;
} else if (character1AttackInfo.Target == 0) {
character1AttackInfo.Target = 4;
} else {
checkTargetAlive = false;
}
}
}
In this part of the script, the lower the enemy's number, the higher they are on the screen. Therefore, when the up arrow is pressed, the target's number goes down so the cursor will move up. The cursor moving to the different places above the characters already works perfectly. The target just wont skip for some reason. Once an enemy dies and so enemy1Stats == 0 is true and the Target is 1 also, it still doesn't skip.
That block of code isn't called:
bool checkTargetAlive = false;
followed by
while (checkTargetAlive)
As a general comment, I don't quite understand how your game logic is supposed to work, but that block in the question has some definite code smell. That can't possibly be the cleanest way to implement your game logic.
So I just accidentally set checkTargetAlive to false ahead of time. That made it so the while loop never ran, which made the cursor not work correctly. Just setting it to true ahead of time made it work like a charm:
else if (state == CHARACTER1TARGETCHOICE) {
attackButton.enabled = false;
abilitiesButton.enabled = false;
itemButton.enabled = false;
defendButton.enabled = false;
fleeButton.enabled = false;
if (pointer.GetComponent<SpriteRenderer> ().enabled == false) {
pointer.GetComponent<SpriteRenderer> ().enabled = true;
}
if (Input.GetKeyDown (KeyCode.UpArrow)) {
character1AttackInfo.Target -= 1;
bool checkTargetAlive = true;
while (checkTargetAlive) {
if (enemy1Stats [lifeStatus] == 0 && character1AttackInfo.Target == 1) {
character1AttackInfo.Target -= 1;
} else if (enemy2Stats [lifeStatus] == 0 && character1AttackInfo.Target == 2) {
character1AttackInfo.Target -= 1;
} else if (enemy3Stats [lifeStatus] == 0 && character1AttackInfo.Target == 3) {
character1AttackInfo.Target -= 1;
} else if (enemy4Stats [lifeStatus] == 0 && character1AttackInfo.Target == 4) {
character1AttackInfo.Target -= 1;
} else if (character1AttackInfo.Target == 0) {
character1AttackInfo.Target = 4;
} else {
checkTargetAlive = false;
}
}
}
i have a form with more than one NumericUpDown as controls to input answer. i want every input is true for an operation (multiplication, sum etc), NumericUpDown for that operation will be disable. i have used the code below (just for sum operation), but i think its not efficient because i have to make a method to check every operation.
private void IsSumTrue() {
if (add1 + add2 == sum.Value)
{
sum.Enabled = false;
}
}
private void IsDifferenceTrue()
{
if (add1 - add2 == difference.Value)
{
difference.Enabled = false;
}
}
private void IsProductTrue()
{
if (add1 * add2 == product.Value)
{
product.Enabled = false;
}
}
private void IsQuotientTrue()
{
if (add1 / add2 == quotient.Value)
{
quotient.Enabled = false;
}
}
anyone have idea how to make it more efficient with just a method for all operation?
below is my idea, but to check the value is true for every NumericUpDown i don't know how.
private void DisableIfValueIsTrue()
{
foreach(Control control in this.Controls)
{
NumericUpDown value = control as NumericUpDown;
// if(value [NEED HELP]
}
}
Considering your situtaion, you can set a tag for each NumericUpDown in design mode like this:
sum.Tag=1;
square.Tag=2;
etc
Then define some int variables:
int iSum=add1+add2;
int iSquare= //Whatever you want
etc
And finally loop through your controls this way:
foreach (NumericUpDown control in this.Controls.OfType<NumericUpDown>())
{
int intCondition = Convert.ToInt32(control.Tag) == 1
? iSum
: Convert.ToInt32(control.Tag) == 2
? iSquare
: Convert.ToInt32(control.Tag) == 3
? i3
: i4; //You should extend this for your 8 controls
control.Enabled = intCondition == control.Value;
}
OK! Second way I offer
Since you will have to always check 8 different conditions, you could simply forget about looping through the controls and just change your method like this:
private void DisableIfValueIsTrue()
{
sum.Enabled = add1 + add2 != sum.Value;
difference.Enabled= add1 - add2 != difference.Value;
product.Enabled= add1 * add2 != product.Value;
quotient.Enabled= (add2 !=0) && (add1 / add2 != quotient.Value);
//etc
}
I came across this while doing some research and would like to give my solution I used for my situation and hope it helps people. I needed minimum and maximum numbers for a calculation, so mine are named appropriately and I correlated these with some CheckBoxes. I used null in beginning of minimum and end of maximum to account for empty. I also had to create an event handler SubscribeToEvents() shown below.
In my load event for my form:
SubscribeToEvents();
_checkBoxs = new[] { cbXLight, cbLight, cbMedium, cbHeavy, cbXHeavy, cbXXHeavy, cbXXXHeavy };
_minimumsNumericUpDowns = new[] { null, nLightMin, nMediumMin, nHeavyMin, nXHeavyMin, nXXHeavyMin, nXXXHeavyMin };
_maximumsNumericUpDowns = new[] { nXLightMax, nLightMax, nMediumMax, nHeavyMax, nXHeavyMax, nXXHeavyMax, null };
then I created a method:
private void DisableNumericUpDowns()
{
// disable everything:
foreach (var n in _minimumsNumericUpDowns)
{
if (n != null)
n.Enabled = false;
}
foreach (var n in _maximumsNumericUpDowns)
{
if (n != null)
n.Enabled = false;
}
}
The event handler:
private bool _eventsSubscribed;
private void SubscribeToEvents()
{
if (_eventsSubscribed)
return;
_eventsSubscribed = true;
cbXXHeavy.CheckedChanged += CheckBox_NumericState;
cbXHeavy.CheckedChanged += CheckBox_NumericState;
cbXLight.CheckedChanged += CheckBox_NumericState;
cbHeavy.CheckedChanged += CheckBox_NumericState;
cbLight.CheckedChanged += CheckBox_NumericState;
cbMedium.CheckedChanged += CheckBox_NumericState;
cbXXXHeavy.CheckedChanged += CheckBox_NumericState;
}
Now I can used this to check when they are enabled and if they are greater than or less than 0 if needed in the method CheckBox:
private void CheckBox_NumericState(object sender, EventArgs e)
{
// disable everything
DisableNumericUpDowns();
// see if more than one checkbox is checked:
var numChecked = _checkBoxs.Count((cb) => cb.Checked);
// enable things if more than one item is checked:
if (numChecked <= 1) return;
// find the smallest and enable its max:
var smallest = -1;
for (var i = 0; i < _checkBoxs.Length; i++)
{
if (!_checkBoxs[i].Checked) continue;
if (_maximumsNumericUpDowns[i] != null)
{
_maximumsNumericUpDowns[i].Enabled = true;
}
smallest = i;
break;
}
// find the largest and enable its min:
var largest = -1;
for (var i = _checkBoxs.Length - 1; i >= 0; i--)
{
if (!_checkBoxs[i].Checked) continue;
if (_minimumsNumericUpDowns[i] != null)
{
_minimumsNumericUpDowns[i].Enabled = true;
}
largest = i;
break;
}
// enable both for everything between smallest and largest:
var tempVar = largest - 1;
for (var i = (smallest + 1); i <= tempVar; i++)
{
if (!_checkBoxs[i].Checked) continue;
if (_minimumsNumericUpDowns[i] != null)
{
_minimumsNumericUpDowns[i].Enabled = true;
}
if (_maximumsNumericUpDowns[i] != null)
{
_maximumsNumericUpDowns[i].Enabled = true;
}
}
}
So I can check each state as required:
I want to check if Extra Light is check:
// Extra Light
if (!cbXLight.Checked) return;
if (nXLightMax.Enabled == false)
{
_structCategoryType = XLight;
CheckStructureSheets();
}
else
{
if (nXLightMax.Value > 0)
{
_dMax = nXLightMax.Value;
_structCategoryType = XLight;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Extra Light Max cannot be zero (0)");
}
}
and next light checks both:
// Light
if (cbLight.Checked)
{
if (nLightMin.Enabled == false && nLightMax.Enabled == false)
{
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
if (nLightMin.Enabled && nLightMin.Value > 0)
{
if (nXLightMax.Enabled && nLightMin.Enabled && nLightMax.Enabled == false)
{
_dMin = nLightMin.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
if (nLightMax.Value > 0)
{
_dMin = nLightMin.Value;
_dMax = nLightMax.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Light Max cannot be zero (0)");
return;
}
}
}
else if (nLightMin.Enabled == false && nLightMax.Enabled)
{
if (nLightMax.Value > 0)
{
_dMax = nLightMax.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Light Max cannot be zero (0)");
}
}
else
{
MessageBox.Show(#"Light Min cannot be zero (0)");
return;
}
}
}
Hope this helps someone.
Tim
thanks for #AlexJoliq and #BrettCaswell. just want to inform that before Alex edited his answer from using "==" to "!=", i (thought) already solved the problem. but i don't know where is the more effective and efficient way, alex's or mine.
below is my code for DisableIfValueIsTrue():
if (add1 + add2 == sum.Value) sum.Enabled = false;
if (add1 - add2 == difference.Value) difference.Enabled = false;
if (add1 * add2 == product.Value) product.Enabled = false;
if (add1 / add2 == quotient.Value) quotient.Enabled = false;
The game i am working on has a player that needs to jump and duck under obstacles. I already have it coded in C# to have an random generator. The only thing is, i want to have a sequence of obstacles to spawn that i have in mind. For example, instead of the random, obstacle1, 5, 2, 3, etc. I want obstacle1,2,3,4,5,6,7,8, and so on, to spawn in the order i would like it to. Not sure on how to start the code for this, can anyone point me in the right direction? Thanks in advance!
Here is my random example code.
private void Creation()
{
for(int i = 0; i < numberOfObjects; i++)
{
cObst = Random.Range(0,100);
if(cObst <= obstL)
{
obstacleQueue.Enqueue((Transform) Instantiate(obstHPrefab.transform));
if(i == 0 && start)
{
nextPos = highPos;
}
}
else if(cObst <= obstH && cObst > obstL)
{
obstacleQueue.Enqueue((Transform) Instantiate(obstLPrefab.transform));
if(i == 0 && start)
{
nextPos = lowPos;
}
}
else if(cObst <= obstC && cObst > obstH)
{
obstacleQueue.Enqueue((Transform) Instantiate(obstCPrefab.transform));
if(i == 0 && start)
{
nextPos =cPos;
}
}
else if(cObst <= obstC && cObst > obstC)
{
obstacleQueue.Enqueue((Transform) Instantiate(obstCPrefab.transform));
if(i == 0 && start)
{
nextPos =cPos;
}
}
else
{
Debug.Log ("BREAK");
}
}
}
private void Recycle(float extraZ = 0f)
{
Transform o = obstacleQueue.Dequeue();
if(o.name == obstH.name+"(Clone)")
{
nextPos = new Vector3(highPos.x,highPos.y,nextPos.z);
}
else if(o.name == obstLPrefab.name+"(Clone)")
{
nextPos = new Vector3(lowPos.x,lowPos.y,nextPos.z);
}
else
{
nextPos = new Vector3(carPos.x,carPos.y,nextPos.z);
}
nextPos += new Vector3(
0f,
0f,
Random.Range((0-minZ)+extraZ, (0-maxZ)+extraZ));
Vector3 position = nextPos;
o.localPosition = position;
obstacleQueue.Enqueue(o);
}
void Update()
{
if(curQue <= numberOfObjects && !nextCreate)
{
waitCreate = true;
if(obstacleQueue.Peek().localPosition.z - recycle > char.position.z)
{
Destroy(GameObject.Find (obstacleQueue.Peek().name));
obstacleQueue.Dequeue();
curQue++;
}
}
else
{
nextCreate = true;
StartCoroutine(Wait(0.5f));
curQue = 1;
}
}
private void GameStart()
{
nextPos = transform.localPosition;
for(int i = 0; i < numberOfObjects; i++)
{
Recycle();
}
}
IEnumerator Wait(float duration)
{
if(waitCreate)
{
waitCreate = false;
yield return new WaitForSeconds(duration); //Wait
Creation();
for(int i = 0; i < numberOfObjects; i++)
{
if(i == 0)
{
Recycle(-25f);
}
else { Recycle(); }
}
nextCreate = false;
}
}
}
You could just assign all of the numbers which represent your obstacles in a List. You can just order them sequentially in the List and iterate through one at a time.
List<int> Obstacles = new List<int>();
Assign them using the following,
Obstacles.Add(1);
Obstacles.Add(3);
Obstacles.Add(7);
Then you can reference them by replacing,
CObst = Random.Range(0,100);
Use,
CObst = List[i];
I see you're using Unity. I think your real problem is not about lists or randomness, but how to spawn objects in order without spawning them all at the same time. The easiest way to do this will be for your spawner script to be a prefab or a scene object, coupled with a Coroutine to delay/prolong execution. The script will have a list of objects. These objects will be set in the inspector.
public List<GameObject> objectsToSpawn;
Then your spawning logic will spawn one at a time, probably waiting for something in between:
void Start()
{
StartCoroutine(SpawnAll());
}
public IEnumerator SpawnAll()
{
foreach (GameObject obj in objectsToSpawn)
{
GameObject instance = Instantiate(obj) as GameObject;
// wait for object, see below
}
}
For the delay/wait, you can either use time, or wait for the object to become inactive (if it self-deactivates, like an enemy that will eventually be killed):
yield return new WaitForSeconds(20);
or:
while (instance.activeSelf)
yield return null;