How do I get the boss to attack again 10 seconds after the last attack? - c#

I'm new in unity and all the programing language so I don't know How do I get the bossPattern to starts again after 10 seconds when the boss pattern is over. could you can give how to make that?
I want to make sure that the pattern starts again after 10 seconds when the boss pattern is over.

You can implement a simple timer and after 10 seconds start your "StartBossPattern" and reset your timer:
float timer = 0f;
void Update()
{
timer -= Time.deltaTime;
if (timer <= 0f)
{
//Start Boss Pattern
timer = 10f;
}
}
But this is only one way to do it.

method 1:
float lastAttackTime=0;
float attackTimeGap=10;
void update()
{
if (Time.time-lastAttackTime>attackTimeGap)
{
//attack
lastAttackTime = Time.time;
}
}
method 2:
void update()
{
startCoroutine(Attack());
}
IEnumerator Attack()
{
//attack
yeild return new WaitForSeconds(10);
startCoroutine(Attack());
}

Related

Cooldown for Slowmo

I know the problem is simple, but I'm new to Unity and don't understand how to do it. I would like for there to be a delay between the ability to cause time dilation and the deceleration itself to last no more than a certain time.
{
void Start ()
{
}
void FixedUpdate ()
{
if (Input.GetKey (KeyCode.Mouse1))
{
Time.timeScale = 0.1f;
Time.fixedDeltaTime = Time.timeScale * 0.01f;
}
else
{
Time.timeScale = 1f;
}
}
}
By looking at your code i would totally suggest you to watch and study more tutorials on unity. I will still write down a simple delay logic with comments.
private float _lastTimeAbilityUsed;
private float _abilityCooldown = 2f; // cooldown for 2 seconds
private void Update()
{
if(_lastTimeAbilityUsed < Time.time - _abilityCooldown) return; // if not enough time has passed, returning
if (Input.GetKey (KeyCode.Mouse1))
{
_lastTimeAbilityUsed = Time.time; // saving the time when ability is used
}
}

Setting a fire rate for a weapon in Unity

I am trying to set a fire rate in Unity so that when I hold down up arrow, I will shoot a projectile up every 1 second. Currently my code is shooting a projectile every frame update, even though I have a Coroutine set up.
public GameObject bulletPrefab;
public float bulletSpeed;
public float fireRate = 1f;
public bool allowFire = true;
void Update()
{
//shooting input
if (Input.GetKey(KeyCode.UpArrow) && allowFire == true)
{
StartCoroutine(Shoot("up"));
}
}
IEnumerator Shoot(string direction)
{
allowFire = false;
if (direction == "up")
{
var bulletInstance = Instantiate(bulletPrefab, new Vector3(transform.position.x, transform.position.y, transform.position.z + 1), Quaternion.identity);
bulletInstance.GetComponent<Rigidbody>().AddForce(Vector3.forward * bulletSpeed);
}
yield return new WaitForSeconds(fireRate);
allowFire = true;
}
Coroutine
You can use the coroutine, but since you're calling it in an Update loop you much wait for it to finish before starting another one.
Coroutine currentCoroutine;
if(currentCoroutine == null)
currentCoroutine = StartCoroutine(DoShoot());
IEnumerator DoShoot() {
// Shoot.
yield return new WaitForSeconds(1f);
currentCoroutine = null;
}
Timestamp
You can also use a timestamp for when cooldown is ready. It's basically current time plus some duration.
float cooldown = 1f;
float cooldownTimestamp;
bool TryShoot (Vector2 direction) {
if (Time.time < cooldownTimestamp) return false;
cooldownTimestamp = Time.time + cooldown;
// Shoot!
}
I usually end up doing something like:
Variables
[Serializefield] float shootDelay = 1f;
float T_ShootDelay
Start()
T_ShootDelay = shootDelay;
Update()
if(T_ShootDelay < shootDelay)
T_ShootDelay += Time.deltaTime;
ShootInput()
if(T_ShootDelay >= shootDelay)
{
T_ShootDelay = 0;
Shoot();
}
What this does is:
Check if the shootDelay timer is less than the shootDelay.
Add up the timer by 1 per second.
Check the timer's status every time you want to shoot.
Set the timer to 0 after shooting
Considering a M4 AR that fires at least 700 rounds per minute.
700 rounds / 60 (seconds) ~= 11,66 rounds per second
1 second / 11 rounds ~= 0,085 seconds of delay between each round
You could simply try this:
yield return new WaitForSeconds(1 / (fireRate / 60f));

Prevent a player from spamming a key in C# (Unity)

I am currently doing the tutorial learn with code from unity, in this section there are bonus challenges, that do not help you in resolving it. It says that i have to prevent the player from spamming the spacebar key to spawn dogs.
I am new to C#, i started to looking online but i see something about CoRoutines and i still dont know what that is, is there a simple way to do this, searching online i found something like this, but i cant make it work.
I also tried to make some conditional like canSpawn but i do not know how to implement it well, and Unity gives me an error that i cant use && between a bool and a keypress event
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
public float time = 2.0f;
public float timer = Time.time;
// Update is called once per frame
void Update()
{
timer -= Time.deltaTime;
if (timer > time)
{
// On spacebar press, send dog
if (Input.GetKeyDown(KeyCode.Space))
{
spawnDog();
}
timer = time;
}
void spawnDog()
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
}
You were close. One thing that might make it easier to understand the logic, is to just count up instead of trying to count down. So, in your case, the code would look like this:
void Update ( )
{
timer += Time.deltaTime;
if ( timer >= time )
{
if ( Input.GetKeyDown ( KeyCode.Space ) )
{
spawnDog ( );
timer = 0;
}
}
}
void spawnDog ( )
{
Instantiate ( dogPrefab, transform.position, dogPrefab.transform.rotation );
}
The timer keeps being added to, and when it's greater than your time value (in this case 2.0f), it allows you to press a key. IF a key is then pressed, the timer is reset to 0, and the player needs to wait time time (2.0f) before being able to press the space key again.
I used Coroutines for this task, it has a little bit more code but it works nicely.
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
private bool isCoolDown = false;
private float coolDown = 1f;
private void Update( )
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (isCoolDown == false)
{
SpawnDog( );
StartCoroutine(CoolDown( ));
}
}
}
IEnumerator CoolDown( )
{
isCoolDown = true;
yield return new WaitForSeconds(coolDown);
isCoolDown = false;
}
private void SpawnDog( )
{
Instantiated(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
}
I am using my phone. I am sorry if i made some syntax error.
bool isReadyForInstantiate;
void Start(){
isReadyForInstantiate = true;
}
void Update(){
if(isReadyForInstantiate && Input.GetKeyDown(KeyCode.Space)){
StartCoroutine(PreventSpam());
Instantiate(dogPrefab, transform.position, Quaternion.identity);
}
}
IEnumerator PreventSpam(){
isReadyForInstantiate = false;
yield return new WaitForSeconds(2);
isReadyForInstantiate = true;
}
here my solution based on a StopWatch:
using UnityEngine;
using System.Diagnostics; // hides UnityEngine.Debug. if needed use qualified call
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
public double dogDelayMillis = 2000d;
private Stopwatch stopWatch;
private void Start()
{
stopWatch = new Stopwatch();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (stopWatch.IsRunning)
{
if (stopWatch.Elapsed.TotalMilliseconds > dogDelayMillis)
{
stopWatch.Reset();
SpawnDog();
}
}
else
{
SpawnDog();
}
}
}
private void SpawnDog()
{
stopWatch.Start();
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
}
Another example just for fun
public GameObject dogPrefab;
[Range(0f,2f)]
private float timer = 1.0f;
private float waitTime = 1.0f;
// Update is called once per frame
void Update()
{
// Delay Input Timer - only execute the spacebar command if timer has caught up with waitTime
if (timer < waitTime)
{}
// On spacebar press, send dog
else if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
// Resets Timer
timer = 0;
}
// Run Timer every frame
timer += Time.deltaTime;
Debug.Log(timer);
}
}
I was stuck on the same exact thing, thank you. The code below is what I went with because it's short and sweet.
public GameObject dogPrefab;
[Range(0f,2f)]
private float timer = 1.0f;
private float waitTime = 1.0f;
// Update is called once per frame
void Update()
{
// Delay Input Timer - only execute the spacebar command if timer has caught up with waitTime
if (timer < waitTime)
{}
// On spacebar press, send dog
else if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
// Resets Timer
timer = 0;
}
// Run Timer every frame
timer += Time.deltaTime;
Debug.Log(timer);
}
}

How to Damage Player after each Second if he is on Spikes?

I got Spikes and the bool onSpikes, which tells if the player is onSpikes or not.
Currently the health goes Down constantly, if the player is onSpikes.
if(onSpikes)
{
health -= 0.01f;
}
But I think this it isn't a good solution, cause I'm in void Update(), and I anyways wanted the Health to drop in bigger pieces ( like -0.2f each second).
I've already tried building an Method and use Invoke, but like this my player didn't lost health at all.
Code:
private void Update(){
Debug.Log("Player on Spikes: "+SpikeDMG.onSpikes);
bar.localScale = new Vector3(health,1f);
if(SpikeDMG.onSpikes)
{
Invoke("doDmg",1);
}
//Wenn leben unter 0 fällt ==> starte szene neu
if(health <=0){
int scene = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(scene, LoadSceneMode.Single);
Time.timeScale = 1;
SpikeDMG.onSpikes = false;
}
}
void doDmg(){
health -= 10/100;
}
}
Thanks to everyone who can help!
What you want to do is use some kind of time stamp, when your next action should be executed. It is also described here and here.
private float spikeDamageAt= 0.0f;
void update() {
if(onSpikes && Time.time >= spikeDamageAt) {
health -= 0.01f;
spikeDamageAt= Time.time + 1.0f; // for 1 seconds
}
}

C# Unity project, Freezing when ran

I have been working on a Unity2d project for a while now and I recently implemented a method of which my "Enemy" housed in the GreyGuardController script would fire a bullet in the direction of which it would be facing, using the animator and
otherAnimator = otherObject.GetComponent<Animator>();
for this.
Every time I now run my code, my game freezes but doesn't crash (I think it is stuck in a loop but there are no real loops in my program). It isn't my instantiation of the bullet before anyone starts accusing that as the loop of it freezing as I have commented this out and changed things around over and over again.
public class HurtPlayer : MonoBehaviour {
public float timeToShoot;
private float timeToShootCounter;
private bool shot;
private Vector3 moveDirection;
public float timeBetweenShot;
public float timeBetweenShotCounter;
public Transform firePoint;
public GameObject Bullet;
// Use this for initialization
void Start()
{
shot = false;
timeToShootCounter = timeToShoot;
timeBetweenShotCounter = timeBetweenShot;
}
IEnumerator ExecuteAfterTime(float time)
{
yield return new WaitForSeconds(time);
}
// Update is called once per frame
void Update () {
if (shot == true)
{
timeBetweenShot -= Time.deltaTime;
timeToShoot -= Time.deltaTime;
if (timeBetweenShot <= 0f)
{
shot = false;
timeToShoot = timeToShootCounter;
timeBetweenShot = timeBetweenShotCounter;
}
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.gameObject.tag == "player")
{
if(shot == false)
{
if (timeToShoot >= 0f)
{
shot = true;
while(shot == true)
{
Instantiate(Bullet, firePoint.position, firePoint.rotation);
if (timeBetweenShot <= 0f)
{
shot = false;
timeToShoot = timeToShootCounter;
timeBetweenShot = timeBetweenShotCounter;
}
}
}
}
}
}
This here is my code attached to my guard which instantiates a bullet as well as trying to use variables "TimeToShoot" as a counter for how long the enemy has left to shoot for and "TimeBetweenShoot" as a counter for how long the enemy has in between shots.
This doesn't work and neither does the Enumerator delay.
As an amateur I am obviously doing something clearly wrong but I have no idea what I'm doing wrong or where and would greatly appreciate your help.
while(shot == true)
this will freeze the editor if the body is never left
if (timeBetweenShot <= 0f)
{
shot = false;
if this is not executed in the first iteration, it won't be in the second because you never change the value of "timeBetweenShot" in that loop
It is important to understand that your update function needs to terminate for the game frame to continue with the next game object's update etc, until the end of the frame is reached, before the next update is called on this game object in the next game frame, so
void Update () {
if (shot == true)
{
timeBetweenShot -= Time.deltaTime;
is never executed while your while loop goes rogue
EDIT:
try something like:
// Update is called once per frame
void Update()
{
if (timeToShoot >= 0f) // if we are shooting at all
{
timeToShootCounter -= Time.deltaTime; // make sure we'll stop shooting after the given amount of time (decrease countdown until negative
timeBetweenShotCounter -= Time.deltaTime; // decrease countdown until next shot (after some intervall)
if (timeBetweenShotCounter <= 0f) // if intervall since last shot expired
{
Instantiate(Bullet, firePoint.position, firePoint.rotation); // shoot
timeBetweenShotCounter += timeBetweenShot; // add the time to wait for the next shot to the intervall (so that we don't shoot anymore in the following frames, until this time expired again (by becoming negative))
}
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.gameObject.tag == "player")
{
timeToShootCounter = -1f; // initialise as expired (start shooting immediately)
timeBetweenShotCounter = timeBetweenShot; // shoot in intervalls for this amount of time
}
}
this way, when the collision event is triggered, you reset the counters to their initial values. After that the update function makes sure to fire after intervals of time, and stops once the overall shooting time is over.
Of course you can further improve this code to handle edge cases (if overall time expires and intervals time also expires at the same time, do we shoot a last bullet or not? etc)
hope this helps.
If you appreciate my efforts, please give them a thumbs up =)
Here is your loop: you increase timeBetweenShot on each frame but your while have to be executed in one frame, this means your code executes this while until you enter the if statement but you will never do since timeBetweenShot will change value only in next frame
while(shot == true)// here is your loop budy
{
// shot = false; // try this row here you will problably stop having the trouble
Instantiate(Bullet, firePoint.position, firePoint.rotation);
if (timeBetweenShot <= 0f)//
{
shot = false;
timeToShoot = timeToShootCounter;
timeBetweenShot = timeBetweenShotCounter;
}
}

Categories