so the main problem is that the Patrol() method is not getting called, its my fist time working with inheritance and I suppose theres something wrong with how Currentstate gets set. My idea was that I write the method in the base class, check the CurrentState in its update method and then just set CurrentState in my enemy - child - scripts but it doesnt seem to work. Can somebody help?
using Assets.Code.Enemy.Enemies;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using UnityEngine;
public class EnemyBase : MonoBehaviour
{
[Header("Base values")]
private int _health = 0;
private int _damage = 0;
private int _speed = 0;
private EnemyState _currentState;
[Header("Movement elements")]
protected bool playerInRange = false;
[SerializeField] protected CapsuleCollider2D SpotRange; // the range the enemy will be able to see the player
[SerializeField] protected Transform PlayerTransform;
[SerializeField] protected Transform EnemyFirstPosition, EnemySecondPosition;
protected GameObject CurrentEnemy;
virtual protected int Speed
{
get => _speed;
set => _speed = value;
}
virtual protected EnemyState CurrentState
{
get => _currentState;
set => _currentState = value;
}
virtual protected int Health
{
get => _health;
set => _health = value;
}
virtual protected int Damage
{
get => _damage;
set => _damage = value;
}
// Update is called once per frame
void Update()
{
switch (CurrentState)
{
case EnemyState.Patrol:
StartCoroutine(Patrol());
break;
case EnemyState.Chase:
MoveTowardsPlayer();
break;
case EnemyState.Attack:
Attack();
break;
}
}
public virtual void TakeDamage(int damageTotake)
{
Health -= damageTotake;
}
protected virtual void MoveTowardsPlayer()
{
}
protected virtual void Attack() { } //Empty, will be set in each enemy class individually
protected virtual IEnumerator Patrol()
{
Transform nextTargetPoint = EnemyFirstPosition;
while (true)
{
if (nextTargetPoint != null)
{
Debug.Log("move enemy");
CurrentEnemy.transform.position = Vector2.MoveTowards(
CurrentEnemy.transform.position,
nextTargetPoint.transform.position,
Speed * Time.deltaTime
);
if ((CurrentEnemy.transform.position - nextTargetPoint.transform.position).magnitude < 0.1f) //check if the distance between the enemy and the first target point is low, same as Vector.Distance()
{
yield return new WaitForSeconds(1);
nextTargetPoint = (nextTargetPoint == EnemyFirstPosition) ? EnemySecondPosition : EnemyFirstPosition;
}
}
else if (nextTargetPoint == null)
{
nextTargetPoint = EnemyFirstPosition.transform;
}
}
}
protected virtual void Rest()
{
}
protected virtual void Die()
{
Destroy(this.gameObject);
}
protected virtual void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
playerInRange = true;
}
}
protected virtual void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
playerInRange = false;
}
}
}
using Assets.Code.Enemy.Enemies;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LunaticCultistBase : EnemyBase
{
private Animator _enemyAnimator;
private Rigidbody2D _enemyRigidbody;
private SpriteRenderer _enemySpriteRenderer;
// Start is called before the first frame update
void Start()
{
_enemyAnimator = GetComponent<Animator>();
_enemyRigidbody = GetComponent<Rigidbody2D>();
_enemySpriteRenderer = GetComponent<SpriteRenderer>();
base.Health = 20;
base.Damage = 10;
base.Speed = 10;
base.CurrentEnemy = this.gameObject;
base.CurrentState = EnemyState.Patrol;
CurrentEnemy = this.gameObject;
}
// Update is called once per frame
void Update()
{
if (base.Health <= 0)
Die();
if (playerInRange)
{
if (PlayerTransform.position.x < this.gameObject.transform.position.x)
{
_enemySpriteRenderer.flipX = true;
}
else
{
_enemySpriteRenderer.flipX = false;
}
}
}
//hit and damage logic
public override void TakeDamage(int damageTotake)
{
_enemyRigidbody.bodyType = RigidbodyType2D.Static;
base.TakeDamage(damageTotake);
Invoke("SetAnimationAndBodyType", 0.1f);
}
private void SetAnimationAndBodyType()
{
_enemyAnimator.SetTrigger("Hit");
_enemyRigidbody.bodyType = RigidbodyType2D.Dynamic;
}
//death logic
protected override void Die()
{
_enemyAnimator.SetTrigger("Death");
Invoke("InvokeDie", 1f);
}
private void InvokeDie()
{
base.Die();
}
}
public enum EnemyState
{
Patrol,
Chase,
Attack
}
so the main problem is that the Patrol() method is not getting called, its my fist time working with inheritance and I suppose theres something wrong with how Currentstate gets set. My idea was that I write the method in the base class, check the CurrentState in its update method and then just set CurrentState in my enemy - child - scripts but it doesnt seem to work. Can somebody help?
using Assets.Code.Enemy.Enemies;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using UnityEngine;
public class EnemyBase : MonoBehaviour
{
[Header("Base values")]
private int _health = 0;
private int _damage = 0;
private int _speed = 0;
private EnemyState _currentState;
[Header("Movement elements")]
protected bool playerInRange = false;
[SerializeField] protected CapsuleCollider2D SpotRange; // the range the enemy will be able to see the player
[SerializeField] protected Transform PlayerTransform;
[SerializeField] protected Transform EnemyFirstPosition, EnemySecondPosition;
protected GameObject CurrentEnemy;
virtual protected int Speed
{
get => _speed;
set => _speed = value;
}
virtual protected EnemyState CurrentState
{
get => _currentState;
set => _currentState = value;
}
virtual protected int Health
{
get => _health;
set => _health = value;
}
virtual protected int Damage
{
get => _damage;
set => _damage = value;
}
// Update is called once per frame
void Update()
{
switch (CurrentState)
{
case EnemyState.Patrol:
StartCoroutine(Patrol());
break;
case EnemyState.Chase:
MoveTowardsPlayer();
break;
case EnemyState.Attack:
Attack();
break;
}
}
public virtual void TakeDamage(int damageTotake)
{
Health -= damageTotake;
}
protected virtual void MoveTowardsPlayer()
{
}
protected virtual void Attack() { } //Empty, will be set in each enemy class individually
protected virtual IEnumerator Patrol()
{
Transform nextTargetPoint = EnemyFirstPosition;
while (true)
{
if (nextTargetPoint != null)
{
Debug.Log("move enemy");
CurrentEnemy.transform.position = Vector2.MoveTowards(
CurrentEnemy.transform.position,
nextTargetPoint.transform.position,
Speed * Time.deltaTime
);
if ((CurrentEnemy.transform.position - nextTargetPoint.transform.position).magnitude < 0.1f) //check if the distance between the enemy and the first target point is low, same as Vector.Distance()
{
yield return new WaitForSeconds(1);
nextTargetPoint = (nextTargetPoint == EnemyFirstPosition) ? EnemySecondPosition : EnemyFirstPosition;
}
}
else if (nextTargetPoint == null)
{
nextTargetPoint = EnemyFirstPosition.transform;
}
}
}
protected virtual void Rest()
{
}
protected virtual void Die()
{
Destroy(this.gameObject);
}
protected virtual void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
playerInRange = true;
}
}
protected virtual void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
playerInRange = false;
}
}
}
using Assets.Code.Enemy.Enemies;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LunaticCultistBase : EnemyBase
{
private Animator _enemyAnimator;
private Rigidbody2D _enemyRigidbody;
private SpriteRenderer _enemySpriteRenderer;
// Start is called before the first frame update
void Start()
{
_enemyAnimator = GetComponent<Animator>();
_enemyRigidbody = GetComponent<Rigidbody2D>();
_enemySpriteRenderer = GetComponent<SpriteRenderer>();
base.Health = 20;
base.Damage = 10;
base.Speed = 10;
base.CurrentEnemy = this.gameObject;
base.CurrentState = EnemyState.Patrol;
CurrentEnemy = this.gameObject;
}
// Update is called once per frame
void Update()
{
if (base.Health <= 0)
Die();
if (playerInRange)
{
if (PlayerTransform.position.x < this.gameObject.transform.position.x)
{
_enemySpriteRenderer.flipX = true;
}
else
{
_enemySpriteRenderer.flipX = false;
}
}
}
//hit and damage logic
public override void TakeDamage(int damageTotake)
{
_enemyRigidbody.bodyType = RigidbodyType2D.Static;
base.TakeDamage(damageTotake);
Invoke("SetAnimationAndBodyType", 0.1f);
}
private void SetAnimationAndBodyType()
{
_enemyAnimator.SetTrigger("Hit");
_enemyRigidbody.bodyType = RigidbodyType2D.Dynamic;
}
//death logic
protected override void Die()
{
_enemyAnimator.SetTrigger("Death");
Invoke("InvokeDie", 1f);
}
private void InvokeDie()
{
base.Die();
}
}
public enum EnemyState
{
Patrol,
Chase,
Attack
}
Share
Improve this question
edited Mar 10 at 19:30
derHugo
91.3k9 gold badges91 silver badges135 bronze badges
asked Mar 8 at 19:13
JULUXX JULUXJULUXX JULUX
1
1 Answer
Reset to default 0Your subtype LunaticCultistBase
is hiding Update
meaning it has it's own implementation and the Update
of EnemyBase
might not get called! That's because these Unity built-in event message methods are invoked by Unity's event loop system and not like "normal" methods. And that event system is probably going by the most specific type.
So to be sure you should rather make those Unity methods always protected virtual
in base types so you can then safely overwrite/extend them in subtypes!