首页 > 解决方案 > 遍历 List 以检查 ScriptableObject 中的 bool 是否为真

问题描述

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

字符.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 中创建一个自定义方法,用于循环遍历此列表并检查有多少角色是男性,有多少不是。

对于@derHugo Character.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;
    }
}

标签: c#visual-studiounity3d

解决方案


例如,您可以为此使用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);

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

或者你也可以使用

Character[] characters = new Character[10];

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

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

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);
}

所以你看到使用Add10 或 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;
    }
}

推荐阅读