How to add Delay before finding GameObject - unity3d

I am trying to make a game in where you can stab an enemy, the enemy struggles for about a second and drops dead. (ragdoll);
i think its best to just show my script and you know what I mean:
In an on trigger enter script:
if(other.tag == "enemy"){
other.transform.parent.gameObject.name = ("enemy" + currentEnemy);
print(other.name);
gameObject.Find("enemy" + currentEnemy).GetComponent("RagdollOrNot").MakeKinematicFalse();
BloodParticle.emit = true;
Stabbed = true;
Character.GetComponent("MouseLook").enabled = false;
Character.GetComponent("CharacterMotor").enabled = false;
}
and in the update function:
if(Stabbed == true){
StopBleeding ++;
}
if(StopBleeding > 50){
Stabbed = false;
StopBleeding = 0;
currentEnemy ++;
Character.GetComponent("MouseLook").enabled = true;
Character.GetComponent("CharacterMotor").enabled = true;
BloodParticle.emit = false;
}
Now when my knife enters the collision of the enemy the enemy imediatly drops to the floor.
I tried putting the:
gameObject.Find("enemy" + currentEnemy).GetComponent("RagdollOrNot").MakeKinematicFalse();
in the update function in if(StopBleeding > 50).
if I do that I get an error of Null reverance exception becaus the script cand find the enemy. While it can I its in the trigger enter.
Basicly my question is: Is there any way to fix this error to give it a 50 frame delay (all the rest in StopBleeding works)?
Or is there any way I can put a simple delay in before the Ragdoll gets activated?
Thanks in advance

You can use StartCoroutine("DelayDeath"); where DelayDeath is the name of a method. See below.
if(other.tag == "enemy"){
other.transform.parent.gameObject.name = ("enemy" + currentEnemy);
print(other.name);
StartCoroutine("DelayDeath");
BloodParticle.emit = true;
Stabbed = true;
Character.GetComponent("MouseLook").enabled = false;
Character.GetComponent("CharacterMotor").enabled = false;
}
private IEnumerator DelayDeath()
{
//this will return...and one second later re-enter and finish the method
yield return new WaitForSeconds(1.0f);
gameObject.Find("enemy" + currentEnemy).GetComponent("RagdollOrNot").MakeKinematicFalse();
}

Since you're asking specifically about Unity JS and not C#, you'll use the yield keyword.
print("foo");
yield WaitForSeconds (5.0); // waits for 5 seconds before executing the rest of the code
print("bar");

On stabbing you could look up the enemy object but save it away in a variable instead of issuing the enemies dead. After the bleeding finishes you don't have to look up the enemy and can trigger the death on the saved one.
Another hint: Don't count frames as frames might be of different length. Add up time from Time.deltaTime until you reach let's say 2 seconds and then trigger the death.
Hope that helps.

Related

Unity 2D same state for different enemies issue

I'm making 2D platformer and im getting weird bug - when i hit one enemy, every one else of that type getting the same state. I mean i wanted them to enter "angry" state when my player hit one of them with sword.
Problem looks like this:
->Hit Enemy1 with sword,
->Enemy1 is getting damage and going to "angry" state,
->Enemy2/3/4/5 didn't get damage, but went in "angry" state.
If getting damage is individual for every one of them so why am i suffer that kind of situation. I think the cause is in my Damage Script. If anyone have an idea i would be glad to hear it. Thanks in advance.
public void DealDmg()
{
blob = FindObjectOfType<EnemyScript>();
if (attackPos.gameObject.activeSelf == true)
{
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
for (int i = 0; i < enemiesToDamage.Length; i++)
{
EnemyScript enemyScript = enemiesToDamage[i].GetComponent<EnemyScript>();
enemyScript.GetComponent<EnemyScript>().TakeDmg(damage);
if (gameObject.GetComponent<PlayerControls>().facingRight == true)
{
enemyScript.GetComponent<Rigidbody2D>().AddForce(new Vector2(30f, 20f), ForceMode2D.Impulse);
StartCoroutine("ResetValues");
blob.CalmLogic();
}
else if (gameObject.GetComponent<PlayerControls>().facingRight == false)
{
enemyScript.GetComponent<Rigidbody2D>().AddForce(new Vector2(-30f, 20f), ForceMode2D.Impulse);
StartCoroutine("ResetValues");
blob.CalmLogic();
}
}
attackPos.gameObject.SetActive(false);
}
}
public IEnumerator ResetValues()
{
gotHit = true;
blob.gotAngry = true;
yield return new WaitForSeconds(resetValuesDelay);
gotHit = false;
yield return new WaitForSeconds(resetValuesDelay);
blob.gotAngry = false;
}
Track enemy state inside the enemy
Right now it looks like your code is running on the player and the player is keeping track of enemy state. This is wrong. Your player script should never know anything about (much less modify!) the properties of your enemy. All the player should do is:
when the player successfully hits an enemy, the player tells the enemy "you've been hit!"
The enemy script then takes that information (such as how much damage, what damage type it was, etc) and deal with itself: reducing the damage ("am I wearing armor?"), enhancing the damage ("am I weak to fire?") and so on and so forth...like getting angry at the player and the resulting cooldown before its calm again.
Your player script does not need to know (and does not care!) about this information and any attempt to try and handle it here is folly. As soon as you change how many enemies there are, or create a new enemy type that does something ELSE you end up with a giant pile of useless junk you can't manage.

if Statement Acting Up

This is within the Update function. Excuse the brakeTorque stuff, that's just a bandaid for now. This is a drag racing game, and Staged means ready to go. Once both cars are staged, and the race hasn't started yet, then there should be a delay of 5 seconds then the words "GO 1" should appear (I added stupidCounter as a debugging tool). Then it sets the start time. Then it sets Racing to true in order to keep it from jumping back into this if statement again.
The issue is that it keeps jumping back in the if statement every frame; printing: GO1 GO2 GO3 etc.
The word "GO" is not mentioned anywhere else in any other script.
The "Racing" boolean is not mentioned anywhere else in any script.
Here's my code:
if(Staged && OtherCarStaged() && !Racing)
{
RearRightWheel.brakeTorque = 10000;
RearLeftWheel.brakeTorque = 10000;
FrontRightWheel.brakeTorque = 10000;
FrontLeftWheel.brakeTorque = 10000;
yield WaitForSeconds(5);
stupidCounter += 1;
Debug.Log("GO " + stupidCounter);
mainTimerStart = Time.realtimeSinceStartup;
Racing = true;
}
I'm assuming your function is a coroutine. The issue in your code is probably because you are calling the coroutine in every update frame. You either need to add a check to call the coroutine only once, or use your own timer to handle this instead of a coroutine.
Based on your mentioned requirement I think your code should go like this
var timeLeft : float = 5;
function Update()
{
StartCountdown();
}
function StartCountdown()
{
if(Staged && OtherCarStaged() && !Racing)
{
// your stuff
timeLeft -= Time.deltaTime;
if(timeLeft <= 0)
{
Debug.Log("GO");
mainTimerStart = Time.realtimeSinceStartup;
Racing = true;
}
}
}
Or, if you want to go with Coroutines, it would go like this
function Update()
{
if(!countdownStarted && Staged && OtherCarStaged())
StartCoroutine(StartCountdown(5));
}
var countdownStarted : bool = false;
function StartCountdown(float time)
{
countdownStarted = true;
yield WaitForSeconds(time);
Debug.Log("GO ");
mainTimerStart = Time.realtimeSinceStartup;
Racing = true;
}

Unity: GameObject.FindGameObjectWithTag isn't working and I don't know why

I have a enemy AI script and a small part of the code isn't working. It's supposed to search for a game object with the Player tag when the target no longer exists. So, when the player collects a power up and a new player prefab spawns in its place it will search. However, it is not finding one and I don't know why.
Here is the part of the code that doesn't work:
IEnumerator SearchForPlayer (){
GameObject sResult = GameObject.FindGameObjectWithTag ("Player");
if (sResult = null) {
yield return new WaitForSeconds (0.5f);
StartCoroutine (SearchForPlayer ());
}
else {
target = sResult.transform;
searchingForPlayer = false;
StartCoroutine (UpdatePath());
return false;
}
}
I know that my prefab has got the correct tag and that it is definitely getting to that part of the script. Does any one have any ideas why it's not working?
if (sResult = null) {
Should be
if (sResult == null) {
Single = is an assignment operator so you are setting the result to null instead of checking if it is null.

How to change a sprite to another and then back after 1 second

I'm developing a simple game in Unity2D, in which several monsters eat things that are dragged to them. If the right object is dragged to the monster, the score goes up by one and the monster should make a happy face, otherwise, score goes down and makes a sad face. This is the code I'm using for that (minus the transitions to happy/sad):
if (transform.name.Equals ("yellow")){
if (collinfo.name.Equals ("plastic(Clone)")) {
Debug.Log ("+1");
audio.Play ();
GameSetup.playerScore += 1;
gs.GetComponent<GameSetup>().removeit(aux);
}
else {
Debug.Log ("-1");
audio.Play ();
if (GameSetup.playerScore == 0)
{}
else
{
GameSetup.playerScore -= 1;
}
gs.GetComponent<GameSetup>().removeit(aux);
}
The audio played is just a 'munching' sound.
I want the monster to change sprites to happyFace (via GameObject.GetComponent ().sprite = happyFace), wait one second and then switch back to it's normal sprite, but don't know how to implement that waiting period.
Any and all help would be much appreciated.
This can be implemented several ways, however, I would use a method that returns an IEnumerator like so…
This assumes you have a variable in your script that has a reference to the SpriteRenderer that is attached to the GameObject with this script.
SpriteRenderer sr = GetComponent <SpriteRenderer> ();
I also assume you have an original sprite and the possible sprites to change to as variables too.
public Sprite originalSprite;
public Sprite happyFaceSprite;
public Sprite sadFaceSprite;
public IEnumerator ChangeFace (Sprite changeToSprite)
{
sr.sprite = changeToSprite;
yield return new WaitForSeconds (1.0f);
sr.sprite = originalFaceSprite;
}
You would then call this function with the applicable sprite as the variable.
if (happy)
StartCoroutine (ChangeFace (happyFaceSprite);
else
StartCoroutine (ChangeFace (sadFaceSprite);
Because the ChangeFace method returns an IEnumerator, we must call that function with the StartCoroutine function. The method will run until it reaches the yield return new WaitForSeconds (1.0f) function, then wait for 1.0f seconds and then resume where it stopped last time.
Understand?
Note
I haven't tested this but I don't see why it wouldn't work.
Put a floating point variable in your monster controller, call it happyTimer or something. It should start at zero.
Then in your Update function you should check happyTimer is above zero. If it is, then subtract Time.deltaTime and check again. If happyTimer is zero or below for the second check, then call your function that resets the sprite.
When you set the sprite to "happy face", also set happyTimer = 1. This will begin the countdown starting with the next Update call.
The relevant part of Update would look like this:
if(happyTimer > 0) {
happyTimer -= Time.deltaTime;
if(happyTimer <= 0) {
resetSprite();
}
}

When pausing game(using a bool and time.timescale) it doesn't pause the score counter

this will be my first question so go on easy on me please ;)
I'm building my first game in Unity using my limited knowledge, tutorials and troubleshooting on google but i can't seem to fix this issue
i have a script that counts score(with a GUIText) and another one to pause the game(using timescale) and you probably guessed it already but when i pause the game it doesn't pause the score.
Script for Pausing:
var isPaused : boolean = false;
function Update()
{
if(Input.GetKeyDown("p"))
{
Pause();
}
}
function Pause()
{
if (isPaused == true)
{
Time.timeScale = 1;
isPaused = false;
}
else
{
Time.timeScale = 0;
isPaused = true;
}
}
Script for Score:
var Counter : int = 100000;
var Substractor : int = 0;
var Score : int = Counter - Substractor;
function Update (
) {
Score--;
guiText.text = "Score: "+Score;
}
the score script is attached to a gameobject with a gui text and the script for pausing the game is attached to the player
another issue is that when i'm moving(using the arrow keys) then press pause and then unpause the player moves faster and unpredictable for a splitsecond but this is only when i press pause while pressing the arrow buttons when i only press pause there is no issue, this is a small bugg that i'l try to fix myself, just thought i'd add it here for those that have an easy answer to this issue aswell
I only know this problem from other game frameworks and I've got no experiance with unity. But it should work the same way for unity as it does in other frameworks. You have two options:
Update is called after every rendering frame! So your timescale doesn'T influence how often update is called. Instead you have to find some dt or deltaT (don't know how it is called in unity and how to get it, but I mean the time, since unities the last call to update, please tell me in the comments, so I can edit this answer).
Then don't calculate your score like:
Score--;
but use something like:
Score -= 1 * dt
or
Score -= 1 * dt * Time.timeScale
(depending how exactly unity works)
alternatively you can sourround your update-block with some if-statement:
in Score:
function Update (
) {
if (! isPaused()) { // not sure how this function / property is called in unity
Score--;
guiText.text = "Score: "+Score;
}
}