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

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
}
}

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
}
}

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

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());
}

Unity Inputs Keeps Pressed

This is my shooting script, I set these in fixed update method, as it should be, but my mouse inputs keeps pressed, I am trying to make an fps game but my mouse input keeps pressed, anyone can help me? This also happens in keyboard inputs.
void FixedUpdate()
{
if(isReloading)
{
return;
}
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
if(Input.GetKey(KeyCode.R))
{
Debug.Log("R key was pressed.");
StartCoroutine(Reload());
return;
}
if(Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shooting();
}
}
IEnumerator Reload()
{
isReloading = true;
UIController.instance.reloadMSG.gameObject.SetActive(true);
Debug.Log("reloading");
yield return new WaitForSeconds(reloadTime);
currentAmmo = maxAmmo;
isReloading = false;
UIController.instance.reloadMSG.gameObject.SetActive(false);
}
private void Shooting()
{
currentAmmo--;
Debug.Log("Current Ammo:" + currentAmmo);
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
GameObject bulletImpactObject = Instantiate(bulletImpact, hit.point + (hit.normal * 0.002f), Quaternion.LookRotation(hit.normal, Vector3.up));
Destroy(bulletImpactObject, 10f);
}
UIController.instance.ammoTXT.text = (currentAmmo + " / " + maxAmmo).ToString();
}
A few years ago I did a top-down shooter, and I had a similar problem. Try changing this:
if(Input.GetButton("Fire1") && Time.time > nextTimeToFire)
{
nextTimeToFire = Time.time + fireRate;
Shooting();
}
Removing the '=' from the comparison, and just adding the fire rate instead of dividing. That's how I did back then.
Also, are you planning to do something while the gun is reloading? Because if not and it's just checking if it's reloading, you can just do this:
if !(isReloading)
{
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
if(Input.GetKey(KeyCode.R))
{
Debug.Log("R key was pressed.");
StartCoroutine(Reload());
return;
}
if(Input.GetButton("Fire1") && Time.time > nextTimeToFire)
{
nextTimeToFire = Time.time + fireRate;
Shooting();
}
}
Here is GunController script that does what you want. Added is a weapon recoil
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunController : MonoBehaviour
{
public GameObject bulletPrefab; // Prefab of the bullet
public Transform bulletSpawn; // Spawn point for the bullet
public float fireRate = 0.5f; // Rate of fire in seconds
public float recoil = 10f; // Recoil force applied to the player
public int magazineSize = 6; // Size of the magazine
public float reloadTime = 1.5f; // Time it takes to reload the gun
private int currentAmmo; // Current ammo in the magazine
private bool isReloading; // Flag to check if the gun is being reloaded
private float nextFire = 0.0f; // Time when the player can fire again
void Start()
{
// Initialize the current ammo to the size of the magazine
currentAmmo = magazineSize;
}
void Update()
{
// Check if the player has pressed the fire button and if it's time to fire again
if (Input.GetButton("Fire1") && Time.time > nextFire && !isReloading && currentAmmo > 0)
{
// Set the time when the player can fire again
nextFire = Time.time + fireRate;
// Create a bullet at the spawn point
var bullet = (GameObject)Instantiate(bulletPrefab, bulletSpawn.position, bulletSpawn.rotation);
// Add force to the bullet
bullet.GetComponent<Rigidbody>().AddForce(bullet.transform.forward * 500);
// Apply recoil force to the player
GetComponent<Rigidbody>().AddForce(-transform.forward * recoil, ForceMode.Impulse);
// Decrement the current ammo
currentAmmo--;
}
// Check if the player has pressed the reload button and if the gun is not being reloaded
if (Input.GetKeyDown(KeyCode.R) && !isReloading)
{
// Set the reload flag to true
isReloading = true;
// Start the reload coroutine
StartCoroutine(Reload());
}
}
IEnumerator Reload()
{
// Wait for the reload time
yield return new WaitForSeconds(reloadTime);
// Set the current ammo to the size of the magazine
currentAmmo = magazineSize;
// Set the reload flag to false
isReloading = false;
}
}
This script should be attached to the game object that represents the gun. The script has several public variables that you can customize:
bulletPrefab is the prefab of the bullet that will be fired.
bulletSpawn is the transform component of the game object that represents the spawn point for the bullet.
fireRate is the rate of fire in seconds. This determines how often the gun can be fired.
recoil is the recoil force applied to the player when the gun is fired.
magazineSize is the size of the magazine. This determines how many bullets the gun can hold.

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;
}
}

Unity power-up is not working as intended

First off, I am quite new to scripting so there's probably going to be a few flaws in my script.
So basically, I've made a script for the power up, but once my shot or the player touches the power up coin the fire rate does increase however it won't go back to the normal fire rate after 5 seconds... I have no idea what might be the cause, any advice would be helpful!
using UnityEngine;
using System.Collections;
public class FireRatePowerUp : MonoBehaviour {
private bool isPowerUp = false;
private float powerUpTime = 5.0f;
private PlayerShoot playerShoot;
private void Start()
{
playerShoot = PlayerShoot.FindObjectOfType<PlayerShoot>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player" || collision.gameObject.tag == "Projectile")
{
StartCoroutine(PowerUpTime());
isPowerUp = true;
Destroy(gameObject);
if (collision.gameObject.tag == "Projectile")
{
Destroy(collision.gameObject);
}
}
}
IEnumerator PowerUpTime()
{
playerShoot.fireRate -= 0.13f;
yield return new WaitForSeconds(powerUpTime);
playerShoot.fireRate += 0.13f;
}
}
I think the issue here is that you're destroying the gameobject this script is attached to (the coin) and by so doing, the script itself is destroyed, therefor its code, coroutine or otherwise won't execute.
StartCoroutine(PowerUpTime());
isPowerUp = true;
Destroy(gameObject); //oops, our script has been destroyed :(
You would have to do this very differently, basically moving the bulk of the code to the PlayerShoot class.
Something like this (this being in PlayerShoot.cs)
public void ActivatePowerupFireRate(float time, float amt) {
StartCoroutine(DoActivatePowerupFireRate(time, amt));
}
public IEnumerator ActivatePowerupFireRate(float time, float amt) {
fireRate -= amt;
yield return WaitForSeconds(time);
fireRate += amt;
}
IEumerator is definately one of the ways you can solve this issue.
However I'm not a fan of them here's my solution if you have a timer in game.
public int timePassed = 0;
public int gotPowerUp = 0;
void Start(){
InvokeRepeating("Timer", 0f, 1.0f);
//Starting at 0 seconds, every second call Timer function.
}
void Timer(){
timePassed++; // +1 second.
}
That way when you obtained the powerup you can set gotPowerUp = timePassed. So you have the exact time when powerup is activated.
then you do something like
if( (gotPowerUp + 5) == timePassed ){
//5 seconds have passed.
//deactivate powerup here
}

Categories