Multiple GameObjects with the same Script are sharing the same bool values when they shouldn't.
Hello everyone. I looked around similar topics, but could not learn what I needed. As the title says, I have a Script called StandardEnemyScript that holds the functions that all enemies share. One of these functions, FreezeEnemy(), is meant to freeze the enemy whenever it gets hit by a Freeze Arrow. It does it using a bool called canMove. The problem is that other enemies are sharing this bool value, so they also stop their movement.
I made the Script division because having the same functions for every king of enemy I created sounded like a bad idea, but now they are not working properly. Am I missing something important?
I'm posting the StandardEnemyScrip and another script called MeleeEnemyController, which holds the other functions that my melee enemies execute.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StandardEnemyScript : MonoBehaviour
{
[Header("Enemy Movement")]
[SerializeField] bool canMove = true;
[SerializeField] float freezeMovementTime = 1f;
[SerializeField] float freezeEnemyTime = 1f;
private Color nativeColor;
private Color freezeColor;
private bool arrowFrozen;
[Header("Enemy Health")]
[SerializeField] float enemyHealth = 1f;
[Header("Enemy Damage on Contact")]
[SerializeField] Transform targetPlayer;
[SerializeField] int enemyDamage = 1;
// General Cached References
LootDrop lootDrop;
void Start()
{
lootDrop = FindObjectOfType<LootDrop>();
targetPlayer = GameObject.FindGameObjectWithTag("Player").transform;
nativeColor = GetComponent<SpriteRenderer>().color;
freezeColor = Color.blue;
}
public void DamageEnemy(float incomingDamage)
{
enemyHealth -= incomingDamage;
if (enemyHealth <= 0)
{
Destroy(gameObject);
lootDrop.GetLootDrop();
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Player") && !arrowFrozen)
{
targetPlayer.GetComponent<PlayerController>().DamagePlayer(enemyDamage);
StartCoroutine(FreezeMovement());
}
else if (collision.CompareTag("Player"))
{
targetPlayer.GetComponent<PlayerController>().DamagePlayer(enemyDamage);
}
}
IEnumerator FreezeMovement()
{
canMove = false;
yield return new WaitForSeconds(freezeMovementTime);
canMove = true;
}
public void FreezeEnemy()
{
StartCoroutine(FreezeEnemyCoroutine());
}
IEnumerator FreezeEnemyCoroutine()
{
arrowFrozen = true;
GetComponent<Animator>().enabled = false;
GetComponent<SpriteRenderer>().color = freezeColor;
canMove = false;
yield return new WaitForSeconds(freezeEnemyTime);
GetComponent<Animator>().enabled = true;
canMove = true;
GetComponent<SpriteRenderer>().color = nativeColor;
arrowFrozen = false;
}
public bool CanEnemyMove()
{
return canMove;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeleeEnemyController : MonoBehaviour
{
[Header("Enemy Movement")]
[SerializeField] float enemyMoveSpeed = 1f;
private bool canMove;
[Header("Enemy Damage")]
[SerializeField] Transform targetPlayer;
// Cached References
StandardEnemyScript standardEnemyScript;
// Start is called before the first frame update
void Start()
{
targetPlayer = GameObject.FindGameObjectWithTag("Player").transform;
standardEnemyScript = FindObjectOfType<StandardEnemyScript>();
}
// Update is called once per frame
void Update()
{
ControllEnemyMovement();
}
private void ControllEnemyMovement()
{
canMove = standardEnemyScript.CanEnemyMove();
if (targetPlayer && canMove)
{
transform.position = Vector2.MoveTowards(transform.position, targetPlayer.position, enemyMoveSpeed * Time.deltaTime);
}
}
}
Thanks a lot for your help!
you have only one instance of the script for all the enemies?
@xxmariofer, no, every Enemy has this Script attached to it. I just found the answer to my problem, I'm posting it in a few $$anonymous$$utes.
Answer by lucassivolella · Aug 18, 2020 at 02:00 PM
So, after a night of sleep I found the solution for the problem. The issue resided not on the StandardEnemyScript but actually on the MeleeEnemyController (and the other variants that I did not post in here).
On the Melee Script, Line 22, I had written:
standardEnemyScript = FindObjectOfType<StandardEnemyScript>();
This was not working properlly, I believe, because FindObjectOfType was just looking for any object in the Scene that had the StandardEnemyScript attached to it, no matter if it was the very Object that was hit or some other Object that existed in the Scene. I changed the code to:
standardEnemyScript = GetComponent<StandardEnemyScript>();
And the problem was gone, because now the Script is very specific that it is accessing the very Object it belongs. Of course, this is my theoretical explanation for the situation. I'm pretty amateur and lack experience with programming, C# and Unity, but this kind of situation feels like a game changer to me, because I am able to overcome some challenges and try some new and interesting stuff.
Your answer
Follow this Question
Related Questions
How can I display two elements of two list? 1 Answer
How can i scale a cube from one side only on x only ? 2 Answers
UnityEditor.Animations API in a build 2 Answers
Im not sure whats wrong here could someone help me out? Unexpected symbol "thirst" 26,8 1 Answer
How can I check if a object in the hierarchy have been destroyed using EditorWindow type script ? 1 Answer