Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Beginner Coder Question: In-line Conditional Statement

Discussion in 'Scripting' started by decamperic, Feb 20, 2021.

  1. decamperic

    decamperic

    Joined:
    Jan 23, 2021
    Posts:
    3
    Hello Unity community. I am trying to better understand the logic behind an in-line conditional statement shown to me by a Certified Unity Instructor. In the code below I have set up an Array for moving a 2D sawblade back & forth between two points. I am struggling to comprehend the following snippet of code works with the script:

    targetPoint = targetPoint < waypoints.Length-1 ? targetPoint+1 : 0

    This is the first in-line conditional statement I have worked with, so the syntax of it is somewhat confusing. Allow me to state what I think it is saying and please coach and/or correct me as needed:

    "If targetPoint is less than waypoints.Length minus 1, the target point assigns +1 in the array index, else the targetPoint assigns 0 in the array index."



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SawBlades : MonoBehaviour
    6. {
    7.     [SerializeField]//SerializeField is used to make a private variable viewable in the Unity Inspector
    8.     private Transform[] waypoints;//"Point1" and "Point2" objects in Unity which have been dragged into the Array
    9.     [SerializeField]
    10.     private int targetPoint;
    11.     [SerializeField]
    12.     private float speed;
    13.     // Update is called once per frame
    14.     void Update()
    15.     {
    16.         transform.Rotate(0, 0, 100f * Time.deltaTime);//Sawblade rotation; "Rotate" is a method, parameters for which are (float xAngle, float yAngle, float zAngle);
    17.         transform.position = Vector2.MoveTowards(transform.position, waypoints[targetPoint].position, speed * Time.deltaTime);
    18.         if (Vector2.Distance(transform.position, waypoints[targetPoint].position) < .1f)
    19.         {
    20.             targetPoint = targetPoint < waypoints.Length-1 ? targetPoint+1 : 0;// In-line Conditional Statement;
    21.         }
    22.     }
    23. }
     

    Attached Files:

  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    This is called the ternary operator. Some people love it, but in my opinion it is often poorly used and hides what is really going on in the code, especially when used in this particular context.

    The reference way for doing a cycling indexer is:

    Code (csharp):
    1. index++;
    2. if (index >= MAX)
    3. {
    4.   index = 0;
    5. }
    A more common use of the ternary operator is when you have a clear choice of two things that you're trying to assign, something like:

    Code (csharp):
    1. int myHealth = IsUserBuffed() ? HighHealthValue : NormalHealthValue;
    But even then, personally I prefer a traditional construct so you have somewhere to put breakpoints when things go wrong:

    Code (csharp):
    1. int myHealth = NormalHealthValue;
    2. if (IsUserBuffed())
    3. {
    4.   myHealth = HighHealthValue;
    5. }
    Remember: You WILL write bugs, and you WILL have to debug them. Don't use constructs like this in order to feel clever and then end up having to rewrite your code so you can put breakpoints on all the steps in the process when something goes wrong.

    Ternary operator use is often the cause of what I call "Hairy lines of code."

    How to break down hairy lines of code:

    http://plbm.com/?p=248
     
    decamperic likes this.
  3. Omniglitch

    Omniglitch

    Joined:
    May 29, 2017
    Posts:
    37
    decamperic likes this.
  4. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,992
    Putting in another way, that line is merely a shortcut. You never need to use that trick. You can always write it as a simple IF statement instead:
    Code (CSharp):
    1. if(targetPoint < waypoints.Length-1)
    2.   targetPoint+=1;
    3. else
    4.   targetPoint=0;
    Why is it in a beginner lesson? Well, some people like to show a little bit of everything at a time, or like to only show programs written the "right" way. I've found it distracts too much (as it has now).

    KurtDekker: I would never use it for a teaching example, but the standard index-incrementer I've seen looks like:
    index=(index+1)%A.Length;
    .
     
    decamperic and Kurt-Dekker like this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Fair enough... I guess I still like more break-pointable code because as I'm sure you know, a LOT of common bugs happen when precisely when index incrementers wrap.

    Also, NGL, I got into coding when divide and modulo were more expensive so I tended to stay away and that reflex is still present. Nowadays they are completely free of course... :)
     
  6. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,992
    I never heard why
    (i+1)%length
    was so great. The max size is only written once, leaving less room for errors. Modulo automatically handles the extra minus-1. It takes the same time whether you wrap-around or not. It's short and distinctive, so easy to recognize by people who know the trick. But it could just be showing off that you know modulo -- it's one of the first special, cool; things people learn.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Yeah, we used to try and intentionally pad out looping stuff so we could use the
    &
    operator with powers of two minus one.

    Geez, back on the the early 8bit CPUs there was no multiply, let alone div or mod!

    a = (a + 1) % 8;


    had to be done as:

    Code (csharp):
    1.    ld a,(index)
    2.    inc a
    3.    and 7
    4.    ld (index),a
    Still works today anywhere. Good times, good times.
     
  8. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    687
    They are a bit weird at first. I use them in limited places, where there's a clear if/then and it won't be misunderstood. They do save space in the code if you need a bunch of them.

    x = (y > 5) ? 10 : 20;

    "Set variable x to what value? Depends on whether y > 5. If true, set x to 10. If false, set x to 20."
     
  9. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,992
    Sure, but again, an if/else does the job just as well:
    if(y>5) x=10; else x=20;
    . Or if you want to show the "correct" way, a function might be better:
    x=chairsNeededForCats(y);
    .

    But once you know ?: and have used it a thousand times. it's not weird at all. Code can be full of things like
    n<0?0:n
    and
    age<=1"kitten":"cat"
    . Your eyes automatically see it as an if/else. That's why it's been borrowed by so many langusges (C# being one of them). It quickly feels natural as a value-returning if (among people who think "value-returning if" is a very clear phrase).
     
    Munchy2007 and seejayjames like this.
  10. decamperic

    decamperic

    Joined:
    Jan 23, 2021
    Posts:
    3
    Thanks for all the help, everyone. This cleared things up and offered some better alternatives better in line with my current level of knowledge.
     
  11. decamperic

    decamperic

    Joined:
    Jan 23, 2021
    Posts:
    3
    Thanks Owen. This is much, much closer to how I wanted to write the code, but wanted to give the instructor the benefit of the doubt first.