【问题标题】:How to randomly generate GameObjects programmatically?如何以编程方式随机生成游戏对象?
【发布时间】:2014-08-28 16:34:04
【问题描述】:

我需要一些关于以下问题的帮助。我正在制作一个简单的游戏,其中你有一个角色正在奔跑,他必须跳过迎面而来的障碍。

我目前在创建游戏对象并在运行时在游戏场景中随机生成它们时遇到了困难。

我写了一个类来帮助完成这个:

using UnityEngine;
using System.Collections;

public class randomObstacles : MonoBehaviour {

    public GameObject myCube;
    public Vector3 spawnLocation = new Vector3(0,2,0);

    // Use this for initialization
    void Start () {
        GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);
    }

    // Update is called once per frame
    void Update () {

    }
}

上面的代码是我为了简单地创建对象而编写的,一个接一个。但是当我运行游戏时,它出现空 -_- !

谁能告诉我哪里出了问题,从外观上看,我的代码似乎没有达到我希望达到的效果:(

正如我在 Unity 社区论坛的教程中看到的那样,我已将上述脚本附加到一个空的 GameObject 中,但这也无济于事。 (我环顾四周,似乎没有人遇到过这样的问题 - 我可能错了)

【问题讨论】:

  • 什么时候定义变量“myCube”?因为目前还没有分配。
  • 如果 myCube 在编辑器中预设并指向场景中存在的预制件或对象,代码应该可以正常工作。
  • @LightStriker 未分配“myCube”吗?我以为我用这行代码做了GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);!感谢您指出这一点!虽然我不太确定如何分配,也不确定分配到哪里!! :(
  • @Kay 我尝试将脚本分配给场景中的现有对象,但没有成功。
  • 1.你有一个GameObject,在你附加randomObstacles的场景中我们称之为initial。 2. 你应该有另一个你必须转换成prefab 并命名为myCubePrefab。 3.将myCube上的myCube拖到randomObstacles组件上initial上的initial

标签: c# unity3d


【解决方案1】:

您的myCube 变量似乎是您问题的根源,在我自己的场景中对其进行了测试。通过替换

(GameObject)Instantiate(myCube, ... 

(GameObject)Instantiate(GameObject.CreatePrimitive(PrimitiveType.Cube), ...

我能够毫无疑虑地在 (0,2,0) 处生成一个立方体。也许您的myCube GameObject 缺少网格渲染器,在这种情况下,它会在运行时出现在层次结构中,即使它在游戏视图中不可见。也许您在运行游戏之前没有在 Inspector 中分​​配它,在这种情况下,myCube 变量将引用null,因此不会被创建。此外,尽管您可能将您实例化的 GameObject 分配给 SpawnLocation,但它是一个未使用的局部变量(MonoDevelop 或您的代码编辑器应该通知您)。确保在运行前在 Inspector 中提供对 myCube GameObject 的引用,或者在运行时通过脚本引用加载的预制件/游戏对象。提供一个回退(比如说,可能是 PrimitiveType.Cube?)也会很有帮助,这将使您的代码更加健壮,并且能够在出现引用错误时处理它们。

无论如何,为了实现您所描述的功能,首先确保您已正确准备好您希望myCube 成为的任何东西。此外,对于未来的后代,您可能希望在Start 例程中初始化您的spawnLocation,并通过将Random.value * yourValueCeiling 替换为您希望myCube 生成的每个随机坐标来分配变量坐标。您甚至可以将辅助方法外部化,从而独立于启动例程,这样您就不必拥有单个脚本的一百个实例来创建一百个您需要的实例;相反,您可以通过单个脚本调用该方法,这样就省去了麻烦。如果您愿意,这是我对您目标的实现,希望对您有所帮助!

using UnityEngine;
using System.Collections;

public class randomObstacles : MonoBehaviour {

    public Vector3 spawnLocation;
    public GameObject myCube;

    // Use this for initialization
    void Start () {
        if (myCube != true) {
            Debug.Log("myCube not set");
            myCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }
        if (myCube.renderer.enabled == false) {
            Debug.Log("myCube not rendered");
            myCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }
        CreateCube();
    }

    // Update is called once per frame
    void Update () {  
    }

    void CreateCube() {
        spawnLocation = new Vector3(0, Random.value * 10, 0);
        Instantiate(myCube, spawnLocation, Quaternion.identity);
    }
}

【讨论】:

  • 我刚刚尝试了您给我的样品,不幸的是,没有任何显示。我不太确定为什么什么都没有出现!
  • 日志中给出了哪些信息? myCube not setmyCube not rendered 是否出现?您可能希望在 CreateCube() 中放置另一个 Debug.Log。
  • 我首先将脚本附加到一个空的游戏对象,然后我尝试对立方体执行相同的操作,但无论哪种方式,它仍然表示没有对象链接到脚本,并且运行时屏幕上没有任何内容.
  • 我已经弄清楚了,我的意思是如何以及在何处放置代码和对象以使其出现。虽然现在,我有几百个立方体在整个游戏场景中弹跳......哈哈!关于如何解决这个问题的任何建议?我正在考虑将 spawnLocation = new Vector3(0, Random.value * 10, 0); 调整为 spawnLocation = new Vector3(0, Random.value * 5, 0); !最后,有没有办法让每个对象都保持在同一位置 - 例如在地面上......!
  • 您可能想按照您的建议尝试调整 spawnLocation;例如,您可能想尝试spawnLocation = new Vector3(Random.value * 5, Random.value * 5, Random.value * 5); 在 3D 空间中展开您的立方体。您很可能将刚体/网格碰撞器附加到您的myCube,在这种情况下,将它们中的太多靠在一起会导致您所描述的问题。最后,您可以在 y = 0 处添加一个平面或地板,并向其添加一个对撞机,以确保立方体固定在那里。
【解决方案2】:

可能值得指出的是,您是在 Start 方法中创建对象,这意味着您的代码只会运行一次:根据您的类的名称,我假设您想要创建多个使用此代码的对象。

如果您将代码移动到Update,您将在每个 创建一个对象,这很可能太多了。我的猜测是你想要一个像协程这样的东西,它会在随机间隔上运行,然后随着时间的推移重复生成多维数据集,如下所示:

void Start () {
    StartCoroutine("SpawnObjects");
}

IEnumerator SpawnObjects()
{
    while (keepAddingObjects) // a boolean - could just be "true" or could be controlled elsewhere
    {
        GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);
        float delay = Random.Range(1f, 5f); // adjust this to set frequency of obstacles
        yield return new WaitForSeconds(delay);
    }
}

【讨论】:

  • 这只运行一次。不重复。您应该将 SpawnObjects() 内部代码包围到 while(true)
【解决方案3】:

取自我自己在一个自动生成迷宫的游戏中的代码:

public class Cell
{
    private GameObject instance;

    public void CreateVisual()
    {
        // Load a GameObject that exist inside the "Resources" folder.
        GameObject prefab = (GameObject)Resources.Load("Models/Walls/3W1"); 

        // Create an instance of the prefab
        instance = (GameObject)GameObject.Instantiate(prefab);
        instance.transform.position = myPosition;
    }
}

我认为您缺少的部分是 Resources.Load() 方法。

【讨论】:

  • 我会将预制加载代码分离到一个只调用一次的方法中。在当前版本中,每次调用CreateVisual多次时都会加载预制件。
  • 我认为这不正确 - 预制件是通过检查器使用 myCube 字段设置的。
  • @Kay 这只是一个例子。在实际代码中,加载是Start() 方法的一部分。
猜你喜欢
  • 1970-01-01
  • 2015-01-07
  • 2021-02-06
  • 2014-03-31
  • 2023-04-05
  • 1970-01-01
  • 2018-06-04
  • 2021-04-19
  • 1970-01-01
相关资源
最近更新 更多