- Home /
Can else statements be nested inside an else statement?
Hello, this is my first question here, I am a beginner with Unity but I have used C# before so I do know the scripting basics with this language.
Problem: I'm having a bit of trouble nesting an "else" statement inside another else. I thought this was possible but for some reason only my "if" and "else if" statements are being fired inside my main "else" statement. I'm creating a simple ai system which uses raycasts, public booleans and debug logs in combination to give specific information about what the enemy gameobject is doing at any given moment. I'll explain the basic script further below, but first here it is:
using UnityEngine;
using System.Collections;
public class SimpleAISystem : MonoBehaviour {
public Transform target; //Target we're moving towards
public float nudgeSpeed = 1;
public float speed = 2;
public float rotateSpeed = 10;
public float rotateAngle = 45;
private int direction = 1;
public float forwardRaycastLength = 5;
public float leftRaycastLength = 5;
public float rightRaycastLength = 5;
public bool raycastForwardHit = false;
public bool raycastLeftHit = false;
public bool raycastRightHit = false;
RaycastHit hit = new RaycastHit();
// Update is called once per frame
void Update () {
Debug.Log(direction);
//Forward Raycast
if(!Physics.Raycast(transform.position, transform.forward, out hit, forwardRaycastLength)){
Debug.DrawLine(transform.position, transform.forward * forwardRaycastLength, Color.blue);
//transform.Rotate(Vector3.up, rotateAngle * rotateSpeed * Time.smoothDeltaTime * direction);
transform.position += transform.forward * speed * Time.deltaTime;
raycastForwardHit = false;
Debug.Log("Front Raycast");
}
else{
Debug.Log("Outer Else");
//Forward Left Raycast
if(Physics.Raycast(transform.position, -transform.right, out hit, leftRaycastLength)){
Debug.DrawLine(transform.position, -transform.right * leftRaycastLength, Color.yellow);
if (hit.transform != transform && !hit.collider.gameObject.CompareTag("Ground")) {
direction = 1;
raycastLeftHit = true;
Debug.Log("Left Raycast");
}
}
//Forward Right Raycast
else if(Physics.Raycast(transform.position, transform.right, out hit, rightRaycastLength)){
Debug.DrawLine(transform.position, transform.right * rightRaycastLength, Color.red);
if (hit.transform != transform && !hit.collider.gameObject.CompareTag("Ground")) {
direction = -1;
raycastRightHit = true;
Debug.Log("Right Raycast");
}
}
//Otherwise set our left & right booleans back to false
else {
raycastLeftHit = false;
raycastRightHit = false;
Debug.Log("Nested Else");
}
//transform.position += transform.forward * speed * Time.deltaTime;
transform.Rotate(Vector3.up, rotateAngle * rotateSpeed * Time.smoothDeltaTime * direction);
raycastForwardHit = true;
}
//If our Forward Left & Forward Right raycast booleans are set to true, (the Enemy will not
//know which way to turn) nudge Enemy forward
if(raycastLeftHit && raycastRightHit){
transform.position += transform.forward * nudgeSpeed * Time.smoothDeltaTime;
Debug.Log("Both");
}
//If none of our raycasts are hitting, look towards our target
if(!raycastForwardHit && !raycastLeftHit && !raycastRightHit){
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target.position - transform.position), rotateSpeed * Time.deltaTime);
Debug.Log("Look At target");
}
}
}
The else statement in question is just past halfway down below the "//Forward Right Raycast" with the Debug.Log("Else") in it. In short I am using a separate boolean(raycastForwardHit, raycastLeftHit & raycastRightHit) for each raycast which is set to true on hit. This allows me to check for when only an individual raycast hits and when several hit without needing to re-cast the same ray multiple times.
Problem (in detail): The trouble then is that the nested else statement is supposed to be setting the booleans raycastLeftHit and raycastRightHit back to false when neither the Left Raycast or the Right Raycast are hitting anything. But this is never fired, not even the debug log and I can't figure out why. I realise I could re-cast a !Physics.Raycast for each of them, but this is less efficient, especially since this script will be used by numerous gameobjects. How can I turn off the specific boolean when one of these raycasts is not hitting without re-casting?
I don't see any reason why this shouldn't work. Are you sure that all three Debug.DrawLines aren't visible? $$anonymous$$aybe you hit something else.
Also comments should increase the readability and should help to understand the code. Comments that just reflect exactly what the code does aren't helpful, they make the code messy.
comments should only be used when the code isn't obvious and they should explain why you do something. What you do is obvious.
Below is your code a bit more nicely formatted and with all the extraneous (not-logic) stuff and comments removed. The braces all line up, so there's no reason this shouldn't work. In the case that your nested else{} is failing, are you checking that you're even entering the outer else{} code? I don't see any debugs or verification in there in your code. According to your logic, the first else{} is only called if Physics.Raycast(transform.position, transform.forward, out hit, forwardRaycastLength) does hit something - is this your test case?
void Update ()
{
Debug.Log(direction);
if(!Physics.Raycast(transform.position, transform.forward, out hit, forwardRaycastLength))
{
Debug.DrawLine(transform.position, transform.forward * forwardRaycastLength, Color.blue);
}
else
{
if(Physics.Raycast(transform.position, -transform.right, out hit, leftRaycastLength))
{
Debug.DrawLine(transform.position, -transform.right * leftRaycastLength, Color.yellow);
if (hit.transform != transform && !hit.collider.gameObject.CompareTag("Ground"))
{
}
}
else if(Physics.Raycast(transform.position, transform.right, out hit, rightRaycastLength))
{
Debug.DrawLine(transform.position, transform.right * rightRaycastLength, Color.red);
if (hit.transform != transform && !hit.collider.gameObject.CompareTag("Ground"))
{
}
}
else
{
}
}
if(raycastLeftHit && raycastRightHit)
{
}
if(!raycastForwardHit && !raycastLeftHit && !raycastRightHit)
{
}
}
Thank you for your input. I'm sorry if my commenting made it difficult for you to read, if I were working in a $$anonymous$$m I would definitely have formatted it differently. Commenting this way makes it easier for me to understand what everything in the script is doing and helps isolate where the problem may be occurring. I understand if it may be obvious to you, but that doesn't necessarily mean it is obvious to everyone, me included. Thank you for the advice and I'll keep it in $$anonymous$$d for future posts, but this question isn't actually about comment formatting.
I am just as confused as you as to why it isn't working, especially since it is such a simple script. As I wrote in my question there is a: Debug.Log("Else"); in the else statement (clearly visible in the script above) and is supposed to fire to the console letting me see if this statement is actually being called or not. But there is never a log of this in the console at all. And since I can see in the inspector that the booleans (checkboxes) are not turning off once turned on this is a pretty good indication that it is not being called. As I wrote in the question the nested else statement is supposed to be setting the booleans raycastLeftHit and raycastRightHit back to false when neither the Left Raycast or the Right Raycast are hitting anything. If I could do a separate else statement for each of the left and right raycasts that would be even better, but I don't know how.
If anyone has suggestions as to why this is happening or has an alternative approach would like to hear your advice. Thank you very much.
Setup: I am using the standard FPS controller for the player, and a Unity cube with a rigidbody and this script attached. The cube's Z & X rotation is also frozen.
$$anonymous$$,
I'm not talking about having a Debug statement in the nested else - you mentioned that that wasn't getting called. What I'm talking about is putting a debug in the wrapping else call, to make sure we're at least entering that code. $$anonymous$$y guess is that you're not - because if you were, either a drawline or your else{} debug statement would have to be firing.
The debug drawlines are firing, as are all the other debug logs except the one in the nested else; I mentioned this at the beginning of the question. The debug logs:
Debug.Log("Left Raycast");
Debug.Log("Right Raycast");
are (as far as I understand) in the wrapping else call which would indicate that the wrapping else and the two raycasts (if & else if) within them are working, correct? Why the final "else" does not fire is beyond me, but that is the current problem I am trying to solve.
Answer by rutter · Apr 06, 2012 at 01:53 AM
You should really just step through your code with MonoDevelop's built-in debugger to see what it is actually doing in more or less real time. It'll take some getting used to, but it's much more powerful than throwing debug statements at the wall.
Sure that is a good idea thank you. I'll see if I can work out how to use this as I never have tried it before. I'll try using a new project as well.