【问题标题】:Check value of a variable from every gameobject that attached by a script检查脚本附加的每个游戏对象的变量值
【发布时间】:2016-09-19 00:42:01
【问题描述】:

我有一个名为“student”的游戏对象,它附加了一个脚本,然后我手动复制它(ctrl+D),这样每个复制的学生对象都具有相同的脚本组件。这是脚本(因为太长,不完整)

public class StudentScript : MonoBehaviour {

private Animator animator;
float sec;
public int m;
public GameManage gm;

void Start () {
    animator = GetComponent<Animator> ();
    sec = 0f;
    m = 0;
}

void Update () {
    sec+=Time.deltaTime;
    if (m == 5 && animator.GetInteger ("Behav") == 0) {
        animator.SetTrigger ("Finish");
    }
}

//this is called from another script
public void ResetStudentBehaviour(){
    if (animator.GetInteger ("Behav") != 0) {
        animator.SetInteger ("Behav", 0);
        sec = 0f;
        if (m < 5) {
            m++;
        }
    }else
        Debug.Log ("student done <3");
}
}

我想要 => 如果每个学生的 m 值 m == 5,那么游戏结束。到目前为止我所做的是 GameManage 脚本中的 StudentScript(公共,所以我必须手动设置所有实例),然后检查每个学生的 m 值

public StudentScript stu1, stu2;
void Update () {
    if (stu1.m == 5 && stu2.m == 5) {
        StartCoroutine (ChangeScene());
    }
}
IEnumerator ChangeScene(){
    yield return new WaitForSeconds (10);
    SceneManager.LoadScene(5);
}

有没有一种简单的方法可以在不使用if (stu1.m == 5 &amp;&amp; stu2.m == 5) 的情况下检查所有学生对象的 m 值,因为在每个级别中,学生的数量都是不同的,所以我想为所有级别制作一个动态脚本

【问题讨论】:

    标签: c# unity3d unityscript gameobject


    【解决方案1】:

    我会使用 List&lt;&gt; 并将所有 StudentScript 对象添加到其中。然后您可以使用System.LinqAll 方法检查列表中的所有元素。

    using System.Linq
    
    //Add all your StudentScript objects to this list
    List<StudentScript> studentScripts = new List<StudentScript>();
    
    if(studentScripts.All(x => x.m == 5))
    {
        StartCoroutine (ChangeScene());
    }
    

    这样您可以使用StudentScripts.Add() 添加脚本,它可以是任意大小,并且仍然会检查所有元素。 x =&gt; x.m == 5 部分称为 lambda 表达式(以防你不知道)。它并不像看起来那么恐怖。

    如果您不想使用 Linq 和 lambda,那么您可以遍历列表并更新变量。您可以将 if 语句替换为:

    private bool isGameOver()
    {
        bool gameOver = true;
    
        for(int i = 0; i < studentScripts.Count; i++)
        {
            if (studentScripts[i].m != 5) 
            {
                gameOver = false;
                break;
            }
        }
    
      return gameOver;
    }
    
    void Update()
    {
        if (isGameOver()) {
        StartCoroutine (ChangeScene());
        }
    }
    

    【讨论】:

    • 我正在处理您答案的第二部分,但您已将其发布。我更喜欢这样,因为一些 linq 函数在 iOS 中不起作用,而一些起作用的函数会大量分配内存。剩下的唯一事情是将问题的第二部分放入函数中。也许布尔函数称为isGameOver。这不是必需的,但它会使代码可重用。现在更新函数将有更少的代码。
    • 聪明,我不知道iOS。再次感谢您的知识哈哈。为了完整起见,我会把它放在一个功能中!我认为All 可以记忆吗?我现在就对其进行分析并检查。
    • @Eeva 您还必须将using System.Collections.Generic; 放在脚本的顶部。
    • @Eeva 这个答案已经被编辑了很多。我修复了一个愚蠢的错误,程序员也是如此。立即尝试,它应该可以工作。
    • @gjttt1 我不知道AllorderBy 和其他一些人由于AOT 有问题。无论如何,我通过将函数更改为 bool 来稍微修复代码,然后如果游戏结束则返回。强烈建议您回答中的第二种方法。 GameEngines 中的内存分配一点都不好,尤其是当它们可以避免时。还优化了功能。
    【解决方案2】:

    你可以找到场景中某种类型的所有物体,然后用Linq或类似的方法过滤它们。

    StudentScript[] studentsInScene = Object.FindObjectsOfType<StudentScript>();
    
    if (studentsInScene.All(student => student.m == 5))
    {
        StartCoroutine(ChangeScene());
    }
    

    FindObjectsOfType 可能不如您自己管理的 List 快(尽管可能如此),但如果这不是您的瓶颈(很可能不是),那么这几行代码会简单得多理解,因此更可取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多