Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question I am getting an error about a lambda expression using func

Discussion in 'Scripting' started by MasterElement, Apr 2, 2024.

  1. MasterElement

    MasterElement

    Joined:
    Jun 13, 2016
    Posts:
    149
    So I am still following this tutorial on making a pokemon game and I ran into this error
    Assets\Scripts\Data\ConditionsDB.cs(123,49): error CS1643: Not all code paths return a value in lambda expression of type 'Func<Pokemon, bool>'
    Its from this script on line 119
    Code (CSharp):
    1. public class ConditionsDB
    2. {
    3.     public static void Init()
    4.     {
    5.         foreach(var kvp in Conditions)
    6.         {
    7.             var conditionId = kvp.Key;
    8.             var condition = kvp.Value;
    9.  
    10.             condition.Id = conditionId;
    11.         }
    12.     }
    13.  
    14.     public static Dictionary<ConditionID, Condition> Conditions { get; set; } = new Dictionary<ConditionID, Condition>()
    15.     {
    16.         {
    17.             ConditionID.psn, new Condition()
    18.             {
    19.                 Name = "Poison",
    20.                 StartMessage = "has been poisoned",
    21.                 OnAfterTurn = (Pokemon pokemon) =>
    22.                 {
    23.                     pokemon.UpdateHP(pokemon.MaxHp / 8);
    24.                     pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} was hurt by poison");
    25.                 }
    26.             }
    27.         },
    28.         {
    29.             ConditionID.brn, new Condition()
    30.             {
    31.                 Name = "Burn",
    32.                 StartMessage = "has been burned",
    33.                 OnAfterTurn = (Pokemon pokemon) =>
    34.                 {
    35.                     pokemon.UpdateHP(pokemon.MaxHp / 16);
    36.                     pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} suffers from burn");
    37.                 }
    38.             }
    39.         },
    40.         {
    41.             ConditionID.par, new Condition()
    42.             {
    43.                 Name = "Paralyzed",
    44.                 StartMessage = "has been Parzlyzed",
    45.                OnBeforeMove = (Pokemon pokemon) =>
    46.                {
    47.                   if (Random.Range(1,5) == 1)
    48.                    {
    49.                        pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} is paralyzed and can't move");
    50.                        return false;
    51.                    }
    52.  
    53.                   return true;
    54.                  
    55.                }
    56.             }
    57.         },
    58.          {
    59.             ConditionID.frz, new Condition()
    60.             {
    61.                 Name = "Frozen",
    62.                 StartMessage = "has been frozen",
    63.                OnBeforeMove = (Pokemon pokemon) =>
    64.                {
    65.                   if (Random.Range(1, 5) == 1)
    66.                    {
    67.                        pokemon.CureStatus();
    68.                        pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} is no longer frozen");
    69.                        return true;
    70.                    }
    71.  
    72.                   return false;
    73.  
    74.                }
    75.             }
    76.         },
    77.         {
    78.             ConditionID.slp, new Condition()
    79.             {
    80.                 Name = "Sleep",
    81.                 StartMessage = "has fallen asleep",
    82.  
    83.                 OnStart = (Pokemon pokemon) =>
    84.                 {
    85.                     pokemon.StatusTime = Random.Range(1, 4);
    86.                     Debug.Log($"Will be asleep for {pokemon.StatusTime} moves");
    87.                 },
    88.  
    89.                OnBeforeMove = (Pokemon pokemon) =>
    90.                {
    91.                    if (pokemon.StatusTime <= 0)
    92.                    {
    93.                        pokemon.CureStatus();
    94.                        pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} woke up!");
    95.                        return true;
    96.                    }
    97.  
    98.                   pokemon.StatusTime--;
    99.                   pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} is sleeping");
    100.                   return false;
    101.  
    102.                }
    103.             }
    104.         },
    105.  
    106.         // VOlatile Status Conditions
    107.         {
    108.             ConditionID.confusion, new Condition()
    109.             {
    110.                 Name = "confusion",
    111.                 StartMessage = "has become confussed",
    112.  
    113.                 OnStart = (Pokemon pokemon) =>
    114.                 {
    115.                     pokemon.VolatileStatusTime = Random.Range(1, 5);
    116.                     Debug.Log($"Will be confused for {pokemon.VolatileStatusTime} moves");
    117.                 },
    118.  
    119.                OnBeforeMove = (Pokemon pokemon) =>
    120.                {
    121.                    if (pokemon.VolatileStatusTime <= 0)
    122.                    {
    123.                        pokemon.CureVolatileStatus();
    124.                        pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} is no longer confused!");
    125.                        return true;
    126.                    }
    127.  
    128.                   pokemon.VolatileStatusTime--;
    129.                   if (Random.Range(1, 3) == 1)
    130.                        return true;
    131.  
    132.                }
    133.             }
    134.         }
    135.     };
    136.  
    137. }
    138.  
    139. public enum ConditionID
    140. {
    141.     none, psn, brn, slp, par, frz,
    142.     confusion
    143.  
    144. }
    145.  
    Thing is I did my best to copy the code to the letter and in the video the guy doesn't get that error. Now you might notice that the confusion section is partially a copy of the sleep one that came before it. Both have the line OnBeforeMove = (Pokemon pokemon) => only in the confusion portion it gets the error. I was trying to do research and came up with a partial answer that the problem is because they both use (Pokemon pokemon) =>. So the repeat is the cause. Although the video did the same thing and no error. Plus I know I used the Func function in one of my scripts which should have been part of something public, but the search function revealed noting on any of the scripts I tried.
    Any advice?
     
    Last edited: Apr 2, 2024
  2. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    755
    Consider the lambda body on L120-L132.
    Code (csharp):
    1.                {
    2.                    if (pokemon.VolatileStatusTime <= 0)
    3.                    {
    4.                        pokemon.CureVolatileStatus();
    5.                        pokemon.StatusChanges.Enqueue($"{pokemon.Base.Name} is no longer confused!");
    6.                        return true;
    7.                    }
    8.  
    9.                   pokemon.VolatileStatusTime--;
    10.                   if (Random.Range(1, 3) == 1)
    11.                        return true;
    12.  
    13.                }
    Say VolatileStatusTime > 0. The first if statement isn't entered. Then say Random.Range returns 2. Then the second if statement isn't entered. Now you're at the end. What should happen in this case? What should be returned?

    That's where the problem is. You have some code paths that return a value but one that doesn't. You need to deal with that by returning an appropriate value.

    For fun, you could link the tutorial in question so people can see whether you actually did copy things exactly.

    Also, this doesn't seem particularly Unity-related. Even if in the context of a Unity game, I don't see anything that's particularly dependent on Unity. If anything, this seems to belong in the Scripting subforum.
     
    orionsyndrome and PraetorBlue like this.
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,204
    Would like to note that this part:
    Code (CSharp):
    1. public static void Init()
    2.     {
    3.         foreach(var kvp in Conditions)
    4.         {
    5.             var conditionId = kvp.Key;
    6.             var condition = kvp.Value;
    7.             condition.Id = conditionId;
    8.         }
    9.     }
    Can just be a static constructor and avoid the need to call it manually:
    Code (CSharp):
    1. static ConditionsDB()
    2. {
    3.     foreach(var kvp in Conditions)
    4.     {
    5.         var conditionId = kvp.Key;
    6.         var condition = kvp.Value;
    7.  
    8.         condition.Id = conditionId;
    9.     }
    10. }
    I do wonder if this 'database' is even necessary. A simple base class with derived classes is probably better (as in, proper OOP), allowing conditions to be just be
    new()
    'ed as necessary.

    Code (CSharp):
    1. public abstract class Condition
    2. {
    3.     public abstract string Name { get; }
    4.    
    5.     public abstract void Apply(Pokemon pokemon);
    6. }
    7.  
    8. public sealed class BurnCondition : Condition
    9. {
    10.     public override string Name => "Burn";
    11.    
    12.     public override void Apply(Pokemon pokemon)
    13.     {
    14.         // etc etc
    15.     }
    16. }
    You could still give them an ID, probably just an enum value, for use with comparisons.