I want to display a UI text message that appears while a certain function is being called. I have an enemy state system in my game and the UI text reflects whichever state the enemy is currently in. At the moment, this is working, but with my attack state there are two different functions inside that are called depending on how close the player is to the enemy when they attack. The two methods are Shoot (for long distance attacks) and Lunge (for close range attacks). At the moment for the attack state the text display says “Enemy is attacking” as expected but I want it to be more specific as to which method is being called, so it will say either “Enemy is shooting” or “Enemy is attacking at close range” depending on these methods. I feel I’m close to getting it to work, via searching online for answers, but it keeps throwing errors at me. At the moment it’s saying: Assets/Scripts/StatePatternEnemy.cs(112,26): error CS0019: Operator ==' cannot be applied to operands of type IEnemyState’ and `void. Is there something I’ve forgotten to add or am I doing it all wrong? I’ll post the relevant scripts here for you to check out. I appreciate any help.
The code in question is happening in StatePatternEnemy.cs and in the Update() method.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class StatePatternEnemy : MonoBehaviour {
//Sets speed for enemy turning while searching for the player
public float searchingTurnSpeed = 120f;
//The amount of time the enemy spends looking for the player
public float searchingDuration = 4f;
//The range in which the enemy can detect or see the player
public float sightRange = 20f;
//This sets up waypoints for the enemy to follow
public Transform[] wayPoints;
public Transform eyes;
public Vector3 offset = new Vector3 (0f,0.5f,0f);
//Indicates what state the enemy is in
public MeshRenderer meshRendererFlag;
//Stores reference to bullet prefab
public GameObject bulletPrefab;
//Stores reference to text from message box UI component
public Text messageBoxText;
//Set location for bullet spawn location
public Transform bulletSpawn;
//UPDATE: 31/03/17: Enemy model cannot currently be animated due to errors from imported model
//Get reference for Animator to control animations
//Animator anim;
//Reference to the audio source.
public AudioSource enemyAudio;
//The sound to play when the enemy dies.
public AudioClip deathClip;
//The sound to play when the enemy is wounded.
public AudioClip damagedClip;
//Gets a reference to each of the three enemies
public GameObject enemyType1;
public GameObject enemyType2;
public GameObject enemyType3;
public GameObject enemyCharacter;
//These variables are hidden from the Inspector as they don't need to be edited
//Locates the enemy's current chase target (the player)
[HideInInspector] public Transform chaseTarget;
//Variable for enemy's current state
[HideInInspector] public IEnemyState currentState;
//Variable for the chase state
[HideInInspector] public ChaseState chaseState;
//Variable for the alert state
[HideInInspector] public AlertState alertState;
//Variable for the patrol state
[HideInInspector] public PatrolState patrolState;
//Variable for the dead state
[HideInInspector] public DeadState deadState;
//Variable for the attack state
[HideInInspector] public AttackState attackState;
//Variable for enemy health
[HideInInspector] public EnemyHealth enemyHealth;
//Reference to NavMeshAgent component that allows AI to move around scene automatically
[HideInInspector] public NavMeshAgent navMeshAgent;
private void Awake()
{
chaseState = new ChaseState (this);
alertState = new AlertState (this);
patrolState = new PatrolState (this);
deadState = new DeadState (this);
attackState = new AttackState (this);
//Gets the NavMeshAgent component before the game starts to run
navMeshAgent = GetComponent<NavMeshAgent> ();
enemyAudio = GetComponent<AudioSource> ();
//Get Shoot and Lunge functions from AttackState class so the text can be changed depending on which of these are active
enemyCharacter.GetComponent<AttackState>().Lunge();
enemyCharacter.GetComponent<AttackState>().Shoot();
}
void Start()
{
//When the game starts to run, the default state for the enemy will be patrol
currentState = patrolState;
//Get message box text component when scene runs
//messageBoxText = GetComponent<Text> ();
//Get Animator component
//anim = GetComponent<Animator> ();
}
public string GetCurrentState()
{
return currentState.GetType ().ToString ();
}
void Update()
{
//Update the current state of the enemy
currentState.UpdateState ();
//Updates message box text depending on enemy state
//UPDATE 31/03/17. This if statement is what I tried to do to get the text to update but it didn't work. I was trying to get the current state.
if (currentState == patrolState)
messageBoxText.text = "Enemy is patrolling";
else if (currentState == chaseState)
messageBoxText.text = "Enemy is chasing";
else if (currentState == alertState)
messageBoxText.text = "Enemy is searching";
else if (currentState == attackState)
messageBoxText.text = "Enemy is attacking";
else if (currentState == deadState)
messageBoxText.text = "Enemy is dead";
else if (currentState == AttackState.Instance.Shoot())
messageBoxText.text = "Enemy is shooting";
else if (currentState == AttackState.Instance.Lunge())
messageBoxText.text = "Enemy is attacking at close range";
else
messageBoxText.text = "Unknown state";
}
void OnCollisionEnter(Collision col)
{
//If a bullet collides with an enemy and their health is more than 0...
if (col.gameObject.tag == "Bullet" && enemyHealth.currentHealth > 0)
{
//Play the audio clip of the enemy being hurt
enemyAudio.clip = damagedClip;
enemyAudio.Play ();
}
}
private void OnTriggerEnter (Collider other)
{
currentState.OnTriggerEnter (other);
}
}
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class AttackState : IEnemyState {
//Reference to StatePatternEnemy script
private readonly StatePatternEnemy enemy;
//Whether player is within the trigger collider
bool playerInRange;
public static AttackState Instance;
public AttackState(StatePatternEnemy statePatternEnemy)
{
enemy = statePatternEnemy;
}
void Awake()
{
Instance = this;
}
//Regularly updates Look and Search functions
public void UpdateState()
{
Shoot ();
Lunge ();
}
public void OnTriggerEnter (Collider other)
{
//If the entering collider is the player...
if (other.CompareTag ("Player"))
{
//...the player is in range.
playerInRange = true;
Lunge();
enemy.navMeshAgent.Stop();
}
}
public void OnTriggerExit (Collider other)
{
//If the exiting collider is the player...
if (other.CompareTag ("Player"))
{
//...the player is no longer in range.
playerInRange = false;
}
}
//Logic for patrol state when it transitions from alert state
public void ToPatrolState()
{
Debug.Log ("Cannot transition from attack state to patrol state");
}
//Logic for alert state. This just generates a warning if it attempts to go into alert state when it's already in this state
public void ToAttackState()
{
Debug.Log ("Can't transition to same state");
}
//Logic for chase state
public void ToChaseState()
{
//Sets enemy into chase state from alert state
enemy.currentState = enemy.chaseState;
//Sets search timer to 0 as this isn't needed
//searchTimer = 0f;
}
public void ToDeadState()
{
//Sets enemy into dead state from alert state
enemy.currentState = enemy.deadState;
}
public void ToAlertState()
{
//Sets enemy into alert state when triggered
enemy.currentState = enemy.alertState;
}
void Update()
{
//enemy.messageBoxText.text = "Enemy is attacking the player";
}
//This function sets up the logic so that if the player is detected by the enemy, the enemy will chase the player
public void Shoot()
{
Debug.Log ("Enemy attacking at long distance range");
//Set enemy state alerter to blue to show the enemy is attacking
enemy.meshRendererFlag.material.color = Color.blue;
//The raycast is used to detect the player
RaycastHit hit;
//If the enemy GameObject detects the player when they are within range and can see the player...
if (Physics.Raycast (enemy.eyes.transform.position, enemy.eyes.transform.forward,
out hit, enemy.sightRange) && playerInRange) {
//...the enemy will start to shoot at the player depending on what the raycast hit
//enemy.chaseTarget = hit.transform;
/*if (bullet != null)*/
//{
//Create bullet from bullet prefab
var bullet = GameObject.Instantiate (enemy.bulletPrefab, enemy.bulletSpawn.position, enemy.bulletSpawn.rotation) as GameObject;
//Add velocity to the bullet
bullet.GetComponent<Rigidbody> ().velocity = bullet.transform.forward * 6;
//Destroy the bullet after 2 seconds
//enemy.Destroy (bullet, 2.0f);
//}
enemy.navMeshAgent.Stop ();
//Debug.Log ("Attack");
} else if (playerInRange == false) {
ToAlertState();
}
}
//This function is triggered when the enemy is in the chase state and is very close to the player.
public void Lunge()
{
Debug.Log ("Enemy attacking at close range");
//Set enemy state alerter to blue to show the enemy is attacking
enemy.meshRendererFlag.material.color = Color.white;
//Stops enemy's movement
enemy.navMeshAgent.Stop ();
Debug.Log ("Lunge");
//If the player is no longer in range, the enemy will switch to the alert state
if (playerInRange == false)
{
ToAlertState();
}
}
}
using UnityEngine;
using System.Collections;
public interface IEnemyState
{
void UpdateState();
void OnTriggerEnter (Collider other);
void ToPatrolState();
void ToAlertState();
void ToChaseState();
void ToDeadState();
void ToAttackState();
}