【问题标题】:I want to spawn my zombies in my game at a random location but I want to make sure to not spawn the inside the buildings我想在我的游戏中随机生成我的僵尸,但我想确保不会在建筑物内部生成
【发布时间】:2021-04-12 18:22:08
【问题描述】:

目前在我的脚本中,我在整个地图上随机生成 125 个僵尸,但是使用我当前的代码,它只会在包括建筑物内部在内的任何地方生成它们。我想保留随机生成,所以我无法确定确切的生成位置。有谁知道如何阻止它们在建筑物内生成?

我当前生成它们的代码(如果代码不好/混乱,我是个菜鸟,很抱歉)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZombieRandomSpawn : MonoBehaviour
{
    public GameObject ZK;
    public int xPos;
    public int zPos;
    public int enemyCount;


    // Start is called before the first frame update
    void Start()
    {
        while (enemyCount < 125)
        {
            xPos = Random.Range(1, 165);
            zPos = Random.Range(1, 215);
            Instantiate(ZK, new Vector3(xPos, 0.3f, zPos), Quaternion.identity);
            enemyCount = enemyCount + 1;
        }
    }

    
}

【问题讨论】:

  • 是建筑物吗?场景中的预制件或游戏对象?如果是这样,您可能可以枚举它们,保存它们的边界框,并在生成敌人时生成新坐标(如果您生成的坐标在这些边界框内)。

标签: c# visual-studio unity3d


【解决方案1】:

我会创建一个空游戏对象数组,作为可能的生成位置。然后将它们放置在建筑物外的任何您想要的地方。然后每次生成僵尸时,让它从你创建的位置数组中随机选择一个生成位置。

【讨论】:

    【解决方案2】:

    我会按照here的建议使用SphereCast

    顾名思义,它会沿某个方向投射一个球体,并检查它是否撞到任何东西。

    您可能更愿意使用Physics.CheckSphere 来检查某个半径内某个周围的任何碰撞器而不返回它们,因为我们对Colliders 的命中不感兴趣,但只在返回值中 (bool)。

    在这个特定的用例中,虽然它可能无法按预期工作,因为在Start 中,可能并非所有与物理相关的东西都已正确初始化。我会等到第一个FixedUpdate 调用,例如

    // Adjust this via the Inspector
    [Tooltip("How far away from any collider do zombies have to spawn?")]
    [SerializeField] private float zombySpawnDistanceThreashold = 0.3f;
    
    // Yes, if you make Start return IEnumerator 
    // Unity automatically runs it as a Coroutine
    private IEnumerator Start ()
    {
        // Wait for the first physics Update
        yield return new WaitForFixedUpdate ();
    
        // We don't actually care about the hits
        // We only need to know IF we hit anything at all
        // But this is way more efficient then everytime allocating a new array
        var hits = new Collider[1];
        while (enemyCount < 125)
        {
            // I assume you don't need to have exact INT values but can use any FLOAT value between them
            // If that's the case make sure to use the FLOAT version here
            var xPos = Random.Range(1f, 165f);
            var zPos = Random.Range(1f, 215f);
            var spawnPos = new Vector3(xPos, 0.3f, zPos);
    
            // If we hit something we have to continue and pick a new random position
            // Note: You might want/need to ignore the floor layer if your radius is too big since it would count as hit
            if(Physics.OverlapSphereNonAlloc(spawnPos, zombySpawnDistanceThreashold, hits) > 0) continue;
    
            Instantiate(ZK, spawnPos, Quaternion.identity);
            // (Not sure if needed) Resimulate the physics to take the newly added zomby collider into account
            Physics.Simulate(0.00001f);
            enemyCount++;
        }
    }
    

    作为在命中时跳过生成的替代方法,您还可以使用Physics.OverlapSphereNonAlloc,然后使用Physics.ComputePenetration 来获取您必须移动僵尸的位置和距离的方向和距离,以便将其推出碰撞对撞机。

    【讨论】:

    • 好电话不知道 Physics.CheckSphere。酷炫强大的功能。
    【解决方案3】:

    对于一个简单的方法,我会考虑查看spherecast。在生成僵尸之前,施放一个球体,如果它击中建筑物,然后尝试另一个地点生成。这可能会花费大量计算时间,因为它是随机选择点并检查它是否有效。有时它会不断地在建筑物内随机选取点。

    更可靠的方法是预先定义建筑物所在的范围,然后仅随机选择这些范围之外的位置。它还很大程度上取决于您的建筑物有多大或您拥有多少建筑物。这是一个相当模糊的问题,因此更详细的信息有助于给出更准确的答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      相关资源
      最近更新 更多