Shooting cooldown for enemy in unity2d - c#

I'm doing a top-down shooter in unity, I'm trying to make the enemy shoot when it sees the player. So far, this is my code:
public class EnemyShooting : MonoBehaviour
{
public Transform firePoint;
public GameObject bulletPrefab;
public float bulletForce = 20f;
public FieldOfView _fieldofview;
void Start()
{
_fieldofview = FindObjectOfType<FieldOfView>();
}
// Update is called once per frame
void Update()
{
if(_fieldofview.canSeePlayer)
{
Shoot();
}
}
void Shoot()
{
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb2d = bullet.GetComponent<Rigidbody2D>();
rb2d.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
}
However, when the player is detected it just spams the bullets due it doesn't has a cool down timer. I've tried with a Coroutine and the Invoke method but it doesn't works. Any ideas?

The following code defines two times. The current cooldown and shoot cooldown. Add the bottom and your problem will be solved.
public float shootCooldown = 5; // 5sec for e.g.
private float currentCooldown;
void Update()
{
if (currentCooldown > 0) // If shoot not in cooldown
{
currentCooldown = shootCooldown; // Set current cooldown time to shootCooldown
if(_fieldofview.canSeePlayer) Shoot();
}
else currentCooldown -= Time.deltaTime; // Reduce cooldown over time
}

Related

Sprite not Appearing in Unity 2D Game

I'm creating a 2D Top Down game for practice and I need a little bit of help. For context, it's a 2D Top Down Shooter game, where you can move and shoot enemies. The enemies have a basic radius system where if the player gets within the radius, it'll approach the player.
Now I'm making a game mechanic where the player can hide in a cardboard box, the player can press 'E' and he'll suddenly become a cardboard box, where if the player is in the cardboard box, the enemy doesn't detect him even if the player's within the radius. Yes, just like in Metal Gear. Now I've created the prefabs and everything and functionality-wise, it works perfectly. If you press 'E' the enemy cannot detect you.
Now the small problem is that the cardboard box didn't appear, so it's just the player disappearing entirely. I do not know what caused this problem.
For context, these are my scripts. Feel free to read them, or not :)
PlayerController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public GameObject bulletPrefab;
public GameObject player;
private Rigidbody2D rb2d;
private Vector2 moveDirection;
[SerializeField] private Camera cam;
[SerializeField] private GameObject gunPoint;
public bool isHiding = false;
[SerializeField] private GameObject cardboardBox;
[SerializeField] private GameObject gunSprite;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
cardboardBox.SetActive(false); // Hide the cardboard box when the game starts
gunSprite.SetActive(true); // Show the gun sprite when the game starts
}
// Update is called once per frame
void Update()
{
CheckCursor();
ProcessInputs();
// Make the camera follow the player
cam.transform.position = new Vector3(player.transform.position.x, player.transform.position.y, cam.transform.position.z);
// Check if player pressed the "E" key to toggle the cardboard box
if (Input.GetKeyDown(KeyCode.E))
{
isHiding = !isHiding; // Toggle the isHiding variable
cardboardBox.SetActive(isHiding); // Show/hide the cardboard box accordingly
// If player is hiding, stop player movement
if (isHiding)
{
moveDirection = Vector2.zero;
player.GetComponent<SpriteRenderer>().enabled = false;
cardboardBox.GetComponent<SpriteRenderer>().enabled = true;
gunSprite.SetActive(false); // Hide the gun sprite when the player is hiding
}
else
{
player.GetComponent<SpriteRenderer>().enabled = true;
cardboardBox.GetComponent<SpriteRenderer>().enabled = false;
gunSprite.SetActive(true); // Show the gun sprite when the player is not hiding
}
}
}
private void FixedUpdate()
{
if (!isHiding) // Only allow player to move if they are not hiding in the cardboard box
{
Movement();
}
}
private void CheckCursor()
{
Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
Vector3 characterPos = transform.position;
if (mousePos.x > characterPos.x)
{
this.transform.rotation = new Quaternion(0, 0, 0, 0);
}
else if (mousePos.x < characterPos.x)
{
this.transform.rotation = new Quaternion(0, 180, 0, 0);
}
}
private void Movement()
{
// TODO : Implementasi movement player
rb2d.velocity = new Vector2(moveDirection.x * moveSpeed, moveDirection.y * moveSpeed);
}
private void ProcessInputs()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
moveDirection = new Vector2(moveX, moveY);
if (Input.GetMouseButtonDown(0))
{
Shoot();
}
}
private void Shoot()
{
Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
Vector3 gunPointPos = gunPoint.transform.position;
Vector3 direction = (mousePos - gunPointPos).normalized;
GameObject bullet = Instantiate(bulletPrefab, gunPointPos, Quaternion.identity);
bullet.GetComponent<Bullet>().Init(direction);
}
}
EnemyController script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public Transform player;
public float moveSpeed = 5f;
public float detectionRadius = 5f;
public int maxHealth = 1;
private int currentHealth;
private Rigidbody2D rb2d;
private Vector2 movement;
private void Start()
{
rb2d = this.GetComponent<Rigidbody2D>();
currentHealth = maxHealth;
}
private void Update()
{
float distanceToPlayer = Vector2.Distance(transform.position, player.position);
if (player != null && distanceToPlayer <= detectionRadius && !player.GetComponent<PlayerController>().isHiding)
{
Vector3 direction = player.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
rb2d.rotation = angle;
direction.Normalize();
movement = direction;
}
else
{
movement = Vector2.zero;
}
}
void FixedUpdate()
{
moveCharacter(movement);
}
private void moveCharacter(Vector2 direction)
{
rb2d.MovePosition((Vector2)transform.position + (direction * moveSpeed * Time.deltaTime));
}
public void DestroyEnemy()
{
Destroy(gameObject);
}
}
Bullet script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
// Start is called before the first frame update
[SerializeField] private float speed;
[SerializeField] private Vector3 direction;
public void Init(Vector3 direction)
{
this.direction = direction;
this.transform.SetParent(null);
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg);
}
// Update is called once per frame
void Update()
{
this.transform.position += transform.right * speed * Time.deltaTime;
}
// TODO : Implementasi behaviour bullet jika mengenai wall atau enemy
private void OnTriggerEnter2D(Collider2D other)
{
switch(other.gameObject.tag)
{
case "Wall":
Destroy(gameObject);
break;
case "Enemy":
Destroy(gameObject);
other.gameObject.GetComponent<EnemyController>().DestroyEnemy();
break;
}
}
}
I've tried tinkering my scripts, I've tried checking if there are any missing components in the cardboard box game object but to no avail. Although I might be wrong on the Unity part since I'm fairly certain that the script isn't the problem here, again might be wrong.
I appreciate all the help I can get, thank you for reading until here

unity onCollisionEnter2D is not working, how can I get it to work?

my bird is colliding with the clouds but it only moves them and doesn't trigger it
my character
public float jumpForce = 5f;
public float gravity = -9.81f;
public GameObject gus;
public Transform rotation_checker;
public Transform chekced;
float velocity;
void Start()
{
}
// Update is called once per frame
void Update()
{
gameObject.transform.eulerAngles = new Vector2(0,0);
velocity += gravity * Time.deltaTime;
if (Input.GetKeyDown(KeyCode.W))
{
velocity = jumpForce;
}
rotation_checker.position = chekced.position;
transform.Translate(new Vector2(0, velocity) * Time.deltaTime);
}
private void OnTriggerExit2D(Collider2D collider)
{
Debug.Log(collider.gameObject);
if(collider.gameObject.name == "skybluscene")
{
Destroy(gameObject);
}
}
private void onCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "cloud")
{
Destroy(gameObject);
}
}
the cloud
float x = -4f;
void Start()
{
}
// Update is called once per frame
void Update()
{
gameObject.transform.Translate(new Vector2(x, 0) * Time.deltaTime);
}
void OnTriggerExit2D(Collider2D collider)
{
if ( collider.gameObject.tag == "scene")
{
Destroy(gameObject);
}
}
cloud works just fine, it destroys itself when it leaves the scene but bird doesn't destroy itself when it collides with the cloud
both bird and cloud have dynamic rigidbody2d and a collider
First of all: On your character script, your onCollisionEnter2D is misspelled. It needs to start with a capital letter.
Second: all your other methods use tags to identify what GameObject they collided with, but "skybluscene" (which also looks like a typo) is identified by its gameObject name.
Third: I'm not sure, but I find it odd that you're using both triggers and collisions in the same script.

unity3D, enemy following issue

I'm trying to make enemies follow my player when the player enters the radius area of an enemy, but make the enemy stop following when my bullet hits object or enters radiusArea.
See my gif for more detail:
Gif
script:
using UnityEngine;
using System.Collections;
public class FlyEnemyMove : MonoBehaviour
{
public float moveSpeed;
public float playerRange;
public LayerMask playerLayer;
public bool playerInRange;
PlayerController thePlayer;
// Use this for initialization
void Start()
{
thePlayer = FindObjectOfType<PlayerController>();
}
// Update is called once per frame
void Update()
{
flip();
playerInRange = Physics2D.OverlapCircle(transform.position, playerRange, playerLayer);
if (playerInRange)
{
transform.position = Vector3.MoveTowards(transform.position, thePlayer.transform.position, moveSpeed * Time.deltaTime);
//Debug.Log(transform.position.y);
}
//Debug.Log(playerInRange);
}
void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere(transform.position, playerRange);
}
void flip()
{
if (thePlayer.transform.position.x < transform.position.x)
{
transform.localScale = new Vector3(0.2377247f, 0.2377247f, 0.2377247f);
}
else
{
transform.localScale = new Vector3(-0.2377247f, 0.2377247f, 0.2377247f);
}
}
}
I hope someone can help me :(
Physics2D.OverlapCircle detects only the collider with the lowest z value (if multiple are in range). So you either need to change the z values so the player has the lowest or you need to work with Physics2D.OverlapCircleAll and check the list to find the player. Or you could change your layers so only the player itself is on that specific layer you feed into the overlap test.

Trying to launch a projectile towards a gameobject, doesn't move!=

I'm making a 2D Tower Defense game and want my towers to launch a prefab at minions. However it currently only spawns my desired prefab, but doesn't move it.
My two scripts:
public class Attacker : MonoBehaviour {
// Public variables
public GameObject ammoPrefab;
public float reloadTime;
public float projectileSpeed;
// Private variables
private Transform target;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider co){
if (co.gameObject.tag == "Enemy" || co.gameObject.tag == "BlockTower") {
Debug.Log("Enemy tag detected");
if(this.gameObject.tag == "Enemy" && co.gameObject.tag != "Enemy"){
Debug.Log("This is an Enemy");
// Insert for Enemey to attack Block Towers.
}
if(this.gameObject.tag == "Tower" && co.gameObject.tag != "BlockTower"){
Debug.Log("This is a Tower");
Tower Tower = GetComponent<Tower>();
Tower.CalculateCombatTime(reloadTime, projectileSpeed);
Transform SendThis = co.transform;
Tower.SetTarget(SendThis);
}
}
}
}
and
public class Tower : MonoBehaviour {
private Transform target;
private float fireSpeed;
private double nextFireTime;
private GameObject bullet;
private Attacker source;
// Use this for initialization
public virtual void Start () {
source = this.GetComponent<Attacker> ();
}
// Update is called once per frame
public virtual void Update () {
if (target) {
Debug.Log("I have a target");
//if(nextFireTime <= Time.deltaTime)
FireProjectile ();
}
}
public void CalculateCombatTime(float time, float speed){
Debug.Log("Calculate Combat Speed");
nextFireTime = Time.time + (time * .5);
fireSpeed = speed;
}
public void SetTarget(Transform position){
Debug.Log("Set Target");
target = position;
}
public void FireProjectile(){
Debug.Log("Shoot Projectile");
bullet = (GameObject)Instantiate (source.ammoPrefab, transform.position, source.ammoPrefab.transform.rotation);
float speed = fireSpeed * Time.deltaTime;
bullet.transform.position = Vector3.MoveTowards (bullet.transform.position, target.position, speed);
}
}
Basicly Attacker detects the object that collides with it, then if its tag is Tower it will send the information to Tower. My debug shows that every function works, even "Debug.Log("Shoot Projectile");" shows up.
However it doesn't move towards my target so I guess "bullet.transform.position = Vector3.MoveTowards (bullet.transform.position, target.position, step);" is never being executed?
Vector3.MoveTowards only moves the object once, it's just a instant displacement when the FireProjectile is called.
You need to create some kind of projectile script with an Update() function to make it move over time.
Here is an example:
public class Projectile : MonoBehaviour
{
public Vector3 TargetPosition;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, TargetPosition, speed * Time.DeltaTime);
}
}
Then right after your bullet instantiation, set the target:
bullet.GetComponent<Projectile>().TargetPosition = target.position;
Hope it helps.
You have to update the position of the bullet. You are only moving when you create the bullet.
Try to make a list of bullets and use the update function to change the position.

How to get a projectile to shoot towards a gameobject

Im currently working on a TurretAi. I have it so that when the enemy is within a certain range the turret targets the enemy but I'm unable to get the turret to shoot the projectiles toward the enemy. this is currently what i have this is turret class.
using UnityEngine;
using System.Collections;
public class Defence : MonoBehaviour {
public float DistanceFromCastle,CoolDown;
public GameObject enemy;
public GameObject Bullet;
public int protectionRadius,bulletSpeed;
// Use this for initialization
void Start ()
{
protectionRadius = 35;
bulletSpeed = 50;
CoolDown = 5;
}
// Update is called once per frame
void Update () {
enemy = GameObject.FindGameObjectWithTag("Enemy");
if(enemy != null)
{
DistanceFromCastle = Vector3.Distance(GameObject.FindGameObjectWithTag("Enemy").transform.position,GameObject.FindGameObjectWithTag("Defence").transform.position);
//print (DistanceFromCastle);
if(DistanceFromCastle <= protectionRadius)
{
attackEnemy();
}
}
}
void attackEnemy()
{
transform.LookAt(enemy.transform);
CoolDown -= Time.deltaTime;
if (CoolDown <= 0)
{
Debug.DrawLine(transform.position,enemy.transform.position,Color.red);
Instantiate(Bullet,Vector3.forward,Quaternion.identity);
print("attack Enemy");
CoolDown = 5;
}
}
}
I also already have a cool down var so that it only shoot every 5 second any help would be awesome.
You were fairly close, you need to change this line:
Instantiate(Bullet, Vector3.forward, Quaternion.identity);
To this:
private const int SPAWN_DISTANCE = 5;
Instantiate(Bullet, transform.position + SPAWN_DISTANCE * transform.forward, transform.rotation);
Quaternion.identity refers to:
This quaternion corresponds to "no rotation".

Categories