【问题标题】:Loop through a List to check whether a bool is true within a ScriptableObject遍历 List 以检查 ScriptableObject 中的 bool 是否为真
【发布时间】:2019-04-04 15:38:31
【问题描述】:

我有一个字符 Scriptable Object 'Character',它有一个 bool IsMale。我还有一个“团队”脚本对象,它有一个字符脚本对象类中的字符列表。现在,我想在 Team Class 中创建一个自定义方法,用于循环遍历此列表并检查有多少角色是男性,有多少不是。

Character.cs

 using UnityEngine;

 // Personal Attributes
 public string firstName;
 public string middleName;
 public string lastName;
 public string fullName;

 public bool isMale;

团队.cs

 using UnityEngine;

 public List<Character> characters;

 // For adding ten players.
 public void AddPlayer(Character p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
 {
 characters.Add(p1);
 characters.Add(p2);
 characters.Add(p3);
 characters.Add(p4);
 characters.Add(p5);
 characters.Add(p6);
 characters.Add(p7);
 characters.Add(p8);
 characters.Add(p9);
 characters.Add(p10);
 }
 // I want to loop through these ten characters in the list and tell how many are males and how many are not

再次,我想在 Team Class 中创建一个自定义方法,用于循环遍历此列表并检查有多少角色是男性,有多少不是。

对于 cmets 中的问题@derHugo 字符.cs

using UnityEngine;
using System;

[CreateAssetMenu()]
public class Character : ScriptableObject
{
    // Personal Attributes
    public string firstName;
    public string middleName;
    public string lastName;
    public string fullName;

    public bool isMale;

    private int age;
    public int personalMoney;

    public Sprite image;

    // Game Attributes
    public int totalRuns;
    public int salary;

    public enum characterTypes { PlayerCharacter, Manager, Player, Staff };
    public characterTypes characterType;
    public enum battingHands { LeftHanded, RightHanded };
    public battingHands battingHand;
    public enum bowlingHands { LeftHanded, RightHanded };
    public bowlingHands bowlingHand;
    public enum battingMentalities { Aggressive, Balanced, Defensive };
    public battingMentalities battingMentality;
    public enum bowlingMentalities { Aggressive, Balanced, Defensive };
    public bowlingMentalities bowlingMentality;

    // Skills
    // Technical Skills
    public int technical; // Overall Technical
    public int judgement; // Batting
    public int agility; // Running, Low means if player accidentaly falls down, the time he will take to get back up
    public int cardioFitness; // Injury
    public int muscleFitness; // Injury and Hitting Power
    public int runSpeed; // Running
    public int strength; // Hitting Power

    // Methods
    // Personal Attributes Methods
    public void CalculateAge(DateTime dateOfBirth)
    {
        age = 0;
        age = DateTime.Now.Year - dateOfBirth.Year;
        if (DateTime.Now.DayOfYear < dateOfBirth.DayOfYear)
            age = age - 1;
    }

    // Starting Game Methods Required
    public void SetCharacterType(characterTypes cT)
    {
        Debug.Log("Setting Character Type for " + fullName);

        cT = characterType;

        if (cT == characterTypes.PlayerCharacter)
        {
            Debug.Log(fullName + " is a Player Character");
        }
        else if (cT == characterTypes.Manager)
        {
            Debug.Log(fullName + " is a Manager");
        }
        else if (cT == characterTypes.Player)
        {
            Debug.Log(fullName + " is a Player");
        }
        else if (cT == characterTypes.Staff)
        {
            Debug.Log(fullName + " is a Staff");
        }
        else
        {
            Debug.Log("No Character Type");
        }
    }
    public void TechnicalAverage()
    {
        technical = (judgement + agility + cardioFitness + muscleFitness + runSpeed + strength / 600) * 100;
    }
}

【问题讨论】:

  • 如果我是你,我会将AddPlayer(Character p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) 更改为AddPlayer(Character p)。然后以不同的方式添加它们,并为男性/女性保留一个计数器,并在每次添加角色时检查并增加女性的男性计数器。这样您就不必每次需要此信息时都循环列表。
  • @AliKanat 也许他想确保它总是以正好 10 个字符调用
  • @derHugo 是的,实际上这是有道理的。感谢您指出。
  • 我正在制作板球比赛。这就是为什么我添加了 10 名玩家(我知道有 11 名玩家,但这只是为了测试目的)。我想确保添加了玩家。必须的。我也是 15 岁,也是 Unity 的初学者。这也可能是这种业余爱好者的原因。
  • 或者你可以使用Character[] characters = new Character[10];,因为你不希望大小是动态的

标签: c# visual-studio unity3d


【解决方案1】:

你可以例如为此使用Linq Count(我宁愿在这里使用属性,但您当然可以使用方法来做同样的事情。):

using System.Linq;

public int Males
{
    get
    {
        return characters != null ? characters.Count(c => c.isMale) : 0;
    }
}

public int Females
{
    get
    {
        return characters != null ? characters.Count(c => !c.isMale) : 0;
    }
}

您只需使用该值,例如

Debug.LogFormat(this, "Males: {0}, Females: {1}", Males, Females);

提示:即使 Unity Inspector 自动初始化 List 和数组字段,您也应该始终将其与定义一起执行,例如

public List<Character> characters = new List<Character>(10);

只是为了确保在调用 Add 时它永远不会是 null,并确保将默认容量设置为您希望 List 稍后作为 Count 具有的容量。

或者你也可以使用

Character[] characters = new Character[10];

因为无论如何您都不希望大小是动态的。 (注意然而,Unity 中的 Inspector 总是会覆盖这些定义)

这样做更好的原因:List 在后台无论如何都会将它的值存储在一个数组中。通过使用Add 添加元素,它每次都会检查数组是否仍然足够大,如果不够,则将其扩展为双倍大小(参见here

public void AddPlayer(Character p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
{
    characters.Add(p1); // characters has now capacity 4
    characters.Add(p2);
    characters.Add(p3);
    characters.Add(p4);
    characters.Add(p5); // characters reallocated and has now capacity 8 
    characters.Add(p6);
    characters.Add(p7);
    characters.Add(p8);
    characters.Add(p9); // characters reallocated and has now capacity 16
    characters.Add(p10);
}

所以你看到使用Add 10 或 11 次总是分配比实际需要更多的内存。

我愿意

// hide because if you do it via the method you probably don't
// want to add items via Inspector which would get overwritten later anyway
[HideInInspector] public Character[] characters = new Character[10];

public void AddPlayer(Character p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
{
    characters[0] = p1;
    characters[1] = p2;
    characters[2] = p3;
    characters[3] = p4;
    characters[4] = p5;
    characters[5] = p6;
    characters[6] = p7;
    characters[7] = p8;
    characters[8] = p9;
    characters[9] = p10;
}

除此之外,您在数组或列表中访问或更改值的方式没有太大区别。


要为每个字符设置所需的所有值,您可以/应该使用适当的构造函数(不过我会更改命名):

[Serializable]
public class Character
{
    // Personal Attributes
    public string firstName;
    public string middleName;
    public string lastName;
    public string fullName;

    public bool isMale;

    public Character(string _firstName, string _middleName, string _lastName, bool _isMale)
    {
        firstName = _firstName;
        middleName = _middleName;
        lastName = _lastName;

        fullName = string.Format("{0} {1} {2}", firstName, middleName, lastName);

        isMale = _isMale;
    }
}

【讨论】:

  • 感谢您提供public List&lt;Character&gt; characters = new List&lt;Character&gt;(); 代码。现在我可以轻松地使用检查器将所有玩家添加到列表中。让生活变得如此轻松;)。
  • 但请注意,Inspector 不受数组或列表大小限制的限制;)并且它仅在 Character 被标记为 [Serializable] 时才有效
  • 呃。 Unity 永远不会过时。
  • 无论如何。我不认为历史上任何板球队都有 1,00,000 名球员。所以,我绝对可以超越尺寸限制;)。
  • @SwastikBhattacharyya 是的,这只是很小的细节;)这就是为什么我只把它写成Hint
猜你喜欢
  • 2016-02-10
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多