Unity2D Problem: Enemy does not shoot but it moves - c#

I have a problem with an enemy on Unity2D.
The enemy should run to the player and if it's in the attackRange then it has to attack the enemy with a bullet, but the enemy follows my Player.
But there is a problem:
The enemy doesn't shoot with the bullet.
I changed the code, so when I press a button the enemy attacks too.
It worked only with the button.
Here's my code for the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class Enemy2 : MonoBehaviour
{
public Transform target;
public Transform firePoint;
public float speed = 200f;
public float nextWaypointDistance = 3f;
public float range = 10f; // the range at which the enemy will start moving towards the player
public float attackRange = 8f; // the range at which the enemy will attack the player
float distance;
public Transform enemyGFX;
private Transform player; // reference to the player's transform
public GameObject EnemyWeapon;
Path path;
int currentWaypoint = 0;
bool reachedEndOfPath = false;
Seeker seeker;
Rigidbody2D rb;
public Animator animator;
bool Stop = false;
public static float Enemy2Direction;
// Start is called before the first frame update
void Start()
{
seeker = GetComponent<Seeker>();
rb = GetComponent<Rigidbody2D>();
animator = GetComponentInChildren<Animator>();
player = GameObject.FindGameObjectWithTag("Player").transform;
InvokeRepeating("UpdatePath", 0f, .5f);
}
void UpdatePath()
{
if (seeker.IsDone())
{
seeker.StartPath(rb.position, target.position, OnPathComplete);
}
}
void OnPathComplete (Path p)
{
if (!p.error)
{
path = p;
currentWaypoint = 0;
}
}
// Update is called once per frame
void FixedUpdate()
{
if (Pause.IsPause == false)
{
if (path == null)
{
return;
}
if (currentWaypoint >= path.vectorPath.Count)
{
reachedEndOfPath = true;
return;
}
else
{
reachedEndOfPath = false;
}
Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] -rb.position).normalized;
Vector2 force = direction * speed * Time.deltaTime;
rb.AddForce(force);
float distance = Vector2.Distance(rb.position, path.vectorPath[currentWaypoint]);
if (distance < nextWaypointDistance)
{
currentWaypoint++;
}
//You can make look it differently, if you delete 'rb.velocity' and add 'force' instead.
if (rb.velocity.x >= 0.01f)
{
enemyGFX.transform.localScale = new Vector3(-1f, 1f, 1f);
Enemy2Direction = 1f;
}
else if (rb.velocity.x <= -0.01f)
{
enemyGFX.transform.localScale = new Vector3(1f, 1f, 1f);
Enemy2Direction = 0f;
}
if (distance < attackRange)
{
if (Stop = false)
{
StartCoroutine(Attack());
}
}
}
distance = Vector2.Distance(transform.position, player.position);
if (distance > range)
{
Destroy(gameObject);
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
animator.SetBool("Damage", true);
}
if (collision.gameObject.tag == "Bullet")
{
animator.SetBool("Damage", true);
}
}
void Update()
{
if (animator.GetBool("Damage"))
{
StartCoroutine(DamageAnimation());
}
if (Input.GetKeyDown(KeyCode.L))
{
StartCoroutine(Attack());
}
}
IEnumerator Attack()
{
Debug.Log("Attacked");
Stop = true;
yield return new WaitForSeconds(2.0f);
animator.SetBool("Attack", true);
Instantiate(EnemyWeapon, firePoint.position, firePoint.rotation);
yield return new WaitForSeconds(2.0f);
animator.SetBool("Attack", false);
StartCoroutine(Wait());
}
IEnumerator DamageAnimation()
{
yield return new WaitForSeconds(2.0f);
animator.SetBool("Damage", false);
}
IEnumerator Wait()
{
yield return new WaitForSeconds(2.0f);
Stop = false;
}
}
I don't know what's wrong with my code.
Can somebody please help me?

if(Stop == false)
Replace the = in when you check the Stop bool with ==, in C# you use == in order to check for equality
See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators for more detail.

Related

I'm having an issue properly having the proper particle effect play when I hold the left mouse button down

I'm working on a third person shooter and as the title states I'm having an issue having the particle effect for the muzzle flash play when I hold the left mouse button down. Even though I'm using Input.GetButton the particle effect only seems to play whenever I let go of the mouse. The basic shooting works correctly and I've tried using another particle effect which only led to the same issue so I believe the problem is somewhere within the code. This code is mostly from Brackeys' tutorial on Shooting with Raycasts if that narrows down the issue. I'd also appreciate alternatives to implementing a muzzle flash effect with the particle system.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class FullAuto : MonoBehaviour
{
public int damage = 10;
public float range = 100f;
public float impactForce = 30f;
public float fireRate = 15f;
public int maxAmmo = 10;
public int currentAmmo;
public float reloadTime = 1f;
private bool isReloading = false;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
private float nextTimeToFire = 0f;
public Text ammoCount;
public Animator animator;
void Start()
{
currentAmmo = maxAmmo;
}
void OnEnable()
{
isReloading = false;
animator.SetBool("Reloading", false);
}
void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0 || Input.GetKeyDown(KeyCode.R))
{
StartCoroutine(Reload());
return;
}
if (Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
muzzleFlash.Play();
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
ammoCount.text = "Ammo: " + currentAmmo.ToString();
}
IEnumerator Reload()
{
isReloading = true;
Debug.Log("Reloading...");
animator.SetBool("Reloading", true);
yield return new WaitForSeconds(reloadTime - .25f);
animator.SetBool("Reloading", false);
yield return new WaitForSeconds(.25f);
currentAmmo = maxAmmo;
isReloading = false;
}
void Shoot()
{
currentAmmo--;
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Enemy enemy = hit.transform.GetComponent<Enemy>();
if (enemy != null)
{
enemy.TakeDamage(damage);
}
if (hit.rigidbody != null)
{
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
GameObject impactGO = Instantiate(impactEffect, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactGO, 2f);
}
}
}
Not sure but afaik Play has only an effect if the particle system was stopped/paused before → It doesn't actually restart the particle effect.
If the Particle System has been paused, then this resumes playing from the previous time.
If the Particle System has stopped, then the system starts from time 0, and, if it is relevant, the startDelay is applied.
I think you could rather use Emit and pass in how many particles to spawn each time
Emit count particles immediately
public float particleAmount = 20;
void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0 || Input.GetKeyDown(KeyCode.R))
{
StartCoroutine(Reload());
return;
}
if (Input.GetButton("Fire1"))
{
nextTimeToFire -= Time.deltaTime;
if(nextTimeToFire <= 0)
{
muzzleFlash.Emit(particleAmount);
nextTimeToFire = 1f / fireRate;
Shoot();
}
}
ammoCount.text = "Ammo: " + currentAmmo.ToString();
}
IEnumerator Reload()
{
isReloading = true;
Debug.Log("Reloading...");
animator.SetBool("Reloading", true);
yield return new WaitForSeconds(reloadTime - .25f);
animator.SetBool("Reloading", false);
yield return new WaitForSeconds(.25f);
currentAmmo = maxAmmo;
isReloading = false;
nextTimeToFire = 0;
}

Using Unity: Scripting Enemy AI - Follow Player

I am trying to have my enemy Follow my player when in range, otherwise the enemy is Wandering. I'm quite new to C-Sharp so have been piecing bits of other tutorials code together.
Currently the enemy Wanders back and forth between the trigger box collider I have set. The enemy switches state to Follow when the player is within range, however the enemy will only move towards the player if the player is on the left hand side of the enemy, if I am on the right side of the enemy it is stuck until I am out of range, then it resumes Wandering. Also the enemy does not flip to face the enemy when Following.
Any help would be appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum EnemyState
{
Wander,
Follow,
Die,
};
public class EnemyController : MonoBehaviour
{
GameObject player;
public EnemyState currState = EnemyState.Wander;
public Transform target;
Rigidbody2D myRigidbody;
public float range = 2f;
public float moveSpeed = 2f;
void Start()
{
player = GameObject.FindGameObjectWithTag("Player");
myRigidbody = GetComponent<Rigidbody2D>();
target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
}
void Update()
{
switch (currState)
{
case (EnemyState.Wander):
Wander();
break;
case (EnemyState.Follow):
Follow();
break;
case (EnemyState.Die):
// Die();
break;
}
if(IsPlayerInRange(range) && currState != EnemyState.Die)
{
currState = EnemyState.Follow;
}
else if(!IsPlayerInRange(range)&& currState != EnemyState.Die)
{
currState = EnemyState.Wander;
}
}
private bool IsPlayerInRange(float range)
{
return Vector3.Distance(transform.position, player.transform.position) <= range;
}
bool isFacingRight()
{
return transform.localScale.x > 0;
}
void Wander()
{
{
if (isFacingRight())
{
myRigidbody.velocity = new Vector2(moveSpeed, 0f);
}
else
{
myRigidbody.velocity = new Vector2(-moveSpeed, 0f);
}
}
}
void OnTriggerExit2D(Collider2D collision) //this is to flip the sprite when it reaches the end of its path - a box 2d collider trigger
{
transform.localScale = new Vector2(-(Mathf.Sign(myRigidbody.velocity.x)), 1f);
}
void Follow()
{
if (isFacingRight())
{
myRigidbody.velocity = new Vector2(-moveSpeed, 0f);
transform.position = Vector2.MoveTowards(transform.position, new Vector2(target.position.x, transform.position.y), moveSpeed * Time.deltaTime);
}
/* else //this seems to have no effect on the code
{
myRigidbody.velocity = new Vector2(moveSpeed, 0f);
transform.position = Vector2.MoveTowards(transform.position, new Vector2(target.position.x, transform.position.y), -moveSpeed * Time.deltaTime);
}*/
}
}
ok I figured out my own issues, here is the working script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum EnemyState
{
Wander,
Follow,
Die,
};
public class EnemyController : MonoBehaviour
{
GameObject player;
public EnemyState currState = EnemyState.Wander;
public Transform target;
Rigidbody2D myRigidbody;
public float range = 2f;
public float moveSpeed = 2f;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindGameObjectWithTag("Player");
myRigidbody = GetComponent<Rigidbody2D>();
target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
switch (currState)
{
case (EnemyState.Wander):
Wander();
break;
case (EnemyState.Follow):
Follow();
break;
case (EnemyState.Die):
// Die();
break;
}
if(IsPlayerInRange(range) && currState != EnemyState.Die)
{
currState = EnemyState.Follow;
}
else if(!IsPlayerInRange(range)&& currState != EnemyState.Die)
{
currState = EnemyState.Wander;
}
}
private bool IsPlayerInRange(float range)
{
return Vector3.Distance(transform.position, player.transform.position) <= range;
}
bool isFacingRight()
{
return transform.localScale.x > 0;
}
void Wander()
{
{
if (isFacingRight())
{
myRigidbody.velocity = new Vector2(moveSpeed, 0f);
}
else
{
myRigidbody.velocity = new Vector2(-moveSpeed, 0f);
}
}
}
void OnTriggerExit2D(Collider2D collision)
{
transform.localScale = new Vector2(-(Mathf.Sign(myRigidbody.velocity.x)), 1f);
}
void Follow()
{
if (transform.position.x > target.position.x)
{
//target is left
transform.localScale = new Vector2(-1, 1);
myRigidbody.velocity = new Vector2(-moveSpeed, 0f);
transform.position = Vector2.MoveTowards(transform.position, new Vector2(target.position.x, transform.position.y), moveSpeed * Time.deltaTime);
}
else if (transform.position.x < target.position.x)
{
//target is right
transform.localScale = new Vector2(1, 1);
myRigidbody.velocity = new Vector2(moveSpeed, 0f);
transform.position = Vector2.MoveTowards(transform.position, new Vector2(target.position.x, transform.position.y), moveSpeed * Time.deltaTime);
}
}
}

unity prefab resizes prefab in game mode when in another scene

i've been having this problem with my 2d sprites (enemies characters in my case) where if I have a prefab already made from one scene that works just fine, and use that prefab in another scene, the size is not the same, but it behaves the same if it runs into a wall or something (it turns the other direction). It's not the script because the movement script is attached to other gameobjects that as of now behave the same way and those prefabs get imported to other scenes just fine. Does anyone know if this is a Unity bug or something? It's not a script issue I'm sure. In fact I know it isn't because it's happened with other enemies with different scripts. Sometimes this issue only happens in one scene, sometimes several, sometimes all of them, as long as it's not the original scene the game object and prefab was created in.
I should also mention that when I build the actual game, the game objects work as they should. It's only when I'm in the unity program itself that this is happening. But I can't properly test some scenes unless I were to build the game scene over and over which would be very counterproductive.
here's the script attached to the enemy for those insistent.
using UnityEngine;
using System.Collections;
public class foeHP : MonoBehaviour {
public GameObject deathFlamePrefab;
Rigidbody2D erb;
public float Walk= 2.5f;
private float idle = 0f;
public float move = 2.5f;
public float hp = 3f;
private slicer slicy;
Animator anim;
private bool alive = true;
private bool damager = false;
private float invuln = 0f;
private bool nothurt = true;
public float wallCheckRadius;
public LayerMask whatIsWall;
private bool wallHit;
private bool goRight;
private bool atEdge = false;
public bool spotted;
public float xScale;
public float yScale;
public Transform wallCheck;
public Transform edgeCheck;
public GameObject bonePrefab;
public Transform boneSpawn;
public float fireDelay = 0.5f;
public float coolDownTimer = 0f;
public float timer3 = 0.75f;
private bool damagePlayed = false;
void Start ()
{
anim = GetComponent<Animator>();
erb = GetComponent<Rigidbody2D> ();
}
void Update ()
{
invuln -= Time.deltaTime;
Recover ();
HandleMovement ();
notHurting ();
// Born ();
damagePlayed = false;
}
public void takeDamage (float amount)
{
hp -= amount;
damager = true;
if (!damagePlayed && alive && hp <= 0)
{
Instantiate (deathFlamePrefab, transform.position, transform.rotation);
Destroy (gameObject);
}
if (alive && hp > 0) {
anim.SetTrigger ("damaged");
invuln = 0.5f;
gameObject.layer = 14;
Invoke ("layerReturn", timer3);
}
if (alive && hp > 0 && !damagePlayed) {
soundManager.PlaySFX ("enemyHit");
damagePlayed = true;
}
}
void layerReturn()
{
gameObject.layer = 12;
}
public void HandleMovement()
{
if (wallCheck == null) {
return;
} else {
wallHit = Physics2D.OverlapCircle (wallCheck.position, wallCheckRadius, whatIsWall);
atEdge = Physics2D.OverlapCircle (edgeCheck.position, wallCheckRadius, whatIsWall);
if (wallHit || !atEdge)
goRight = !goRight;
if (goRight) {
transform.localScale = new Vector3 (-xScale, yScale, 1f);
erb.velocity = new Vector2 (move, erb.velocity.y);
anim.SetFloat ("walk", Mathf.Abs (move));
} else {
transform.localScale = new Vector3 (xScale, yScale, 1f);
erb.velocity = new Vector2 (-move, erb.velocity.y);
anim.SetFloat ("walk", Mathf.Abs (move));
}
}
Physics2D.IgnoreLayerCollision (12, 12);
}
public void Recover ()
{
if (invuln <= 0)
gameObject.layer = 12;
nothurt = false;
if (invuln <= 0)
anim.SetLayerWeight (1, 0);
nothurt = true;
}
public void notHurting()
{
if (invuln > 0)
erb.velocity = Vector2.zero;
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Player")
spotted = true;
else
spotted = false;
}
/* void Born ()
{
coolDownTimer -= Time.deltaTime;
if (spotted && coolDownTimer <= 0)
{
coolDownTimer = fireDelay;
anim.SetTrigger ("Throw");
Instantiate (bonePrefab, boneSpawn.position, boneSpawn.rotation);
if (!spotted)
fireDelay = 0;
}
}
*/
}

Unity Player Movement Not Working

I have a script to move my character(player)
The script should be fine and it does not have any errors, although when I press play I try to use the arrows and it does not work and I don't know why.
Here is the code. I appreciate any help you can give me, thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
Direction currentDir;
Vector2 input;
bool isMoving = false;
Vector3 startPos;
Vector3 endPos;
float t;
public float walkSpeed = 3f;
// Update is called once per frame
void Update()
{
if (isMoving)
{
input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Mathf.Abs(input.x) > input.y)
input.y = 0;
else
input.x = 0;
if (input != Vector2.zero)
{
StartCoroutine(Move(transform));
}
}
}
public IEnumerator Move(Transform entity)
{
isMoving = true;
startPos = entity.position;
t = 0;
endPos = new Vector3(startPos.x + System.Math.Sign(input.x), startPos.y +
System.Math.Sign(input.y), startPos.z);
while (t < 1f)
{
t += Time.deltaTime * walkSpeed;
entity.position = Vector3.Lerp(startPos, endPos, t);
yield return null;
}
isMoving = false;
yield return 0;
}
enum Direction
{
North,
East,
South,
West
}
}
Change
void Update()
{
if (isMoving)
{
to
void Update()
{
if (!isMoving)
{
Otherwise, on each Update you check your isMoving variable and do nothing if it is false. The only place where isMoving could become true is your Move coroutine, but it could only be launched from Update, which does not do anything since isMoving is false.

void Start() not being called

I'm making a game in Unity 4.3 with 2D mode. But for some reason the void Start() function isn't being called on the start of the scene. I even attached a Debug.Log("Hello"); to the start function but it doesn't even do that so I know that the Start() function isn't being called. Although, the Update() function is called.
Here is the script.
private void Start()
{
this.animation.Stop();
Debug.Log("Hello");
}
You can see, there is an Update method which does work.
EDIT: Whole script:
public class Player : MonoBehaviour
{
public Vector2 jumpForce = new Vector2(0, 300);
public Vector2 moveForce = new Vector2(0, 300);
public Vector2 sideForce = new Vector2 (250, 0);
public GameObject obstacle;
public float scrollSpeed = 30;
public AnimationClip fly;
public GameObject player;
private float speed = 10.0f;
private void Start()
{
Debug.Log("hi!");
this.animation.Stop();
Debug.Log("Hello");
}
private void Update() {
onTouch();
int fingerCount = 0;
foreach (Touch touch in Input.touches) {
if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
fingerCount++;
}
/*if (fingerCount > 0)
{
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}*/
try
{
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}
catch(UnityException e)
{
Debug.Log("Fail");
}
if (Input.GetKeyDown ("right"))
{
player.rigidbody2D.velocity = Vector2.right;
player.rigidbody2D.AddForce (sideForce);
}
accelorometer();
}
// Die by collision
private void OnCollisionEnter2D(Collision2D other)
{
Die();
}
private void Die()
{
Application.LoadLevel(Application.loadedLevel);
}
private void accelorometer()
{
// Get the accelerometer data:
Vector2 acceleration = Input.acceleration;
// Get the forward value from one of the three channels in the acceleration data:
float translation = acceleration.x * speed;
// Make it move 10 meters per second instead of 10 meters per frame
translation *= Time.deltaTime;
// Move translation along the object's z-axis
player.transform.Translate (translation, 0, 0);
}
private void onTouch()
{
/*int fingerCount = 0;
foreach (Touch touch in Input.touches) {
if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
fingerCount++;
}
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce (moveForce);
}
if (fingerCount > 0)
{
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}*/
if(Input.GetKeyDown ("up"))
{
Debug.Log("ghjkl");
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}
//print("User has " + fingerCount + " finger(s) touching the screen");
}
You just copy the contents of that script and delete it. then create a new script with same code and attach it to the gameObject. It will resolve the issue.
I've been struggling with this also. I've managed to solve it by changing Logging* to Full in the bottom of Player Settings/Other Settings

Categories

Resources