将生成对象移动到随机位置

时间:2018-07-12 18:43:25

标签: c# unity3d game-physics

我有一个生成器对象。每次生成一个游戏对象时,我都希望该对象随机移动(游荡)。我的脚本中的问题是游戏对象的移动非常随机(抖动)。我该怎么解决?

void Start ()
{
    InvokeRepeating("SpawnNPC", Spawntime, Spawntime);
}

// Update is called once per frame
void Update () {
    population = GameObject.FindGameObjectsWithTag("NPCobject");
    for (int i = 0; i < population.Length; i++)
    {
        getNewPosition();
        if (population[i].transform.position != pos)
        {
            population[i].transform.position = Vector3.MoveTowards(population[i].transform.position, pos, .1f);
        }
    }
}
void getNewPosition()
{
    float x = Random.Range(-22, 22);
    float z= Random.Range(-22, 22);

    pos = new Vector3(x, 0, z);
}

我用不同的方法制作了新的随机向量,因为我打算用探路器功能对其进行更改,并使其在不同的线程/任务中使用。

4 个答案:

答案 0 :(得分:1)

您正在每帧选择一个新方向。那将永远是非常紧张的。至少在一个很小的间隔后,您就不会只改变方向。这是Unity网站上实现此目的的一种方法的链接。 https://docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.html

答案 1 :(得分:1)

使用Navigation怎么样?正如您所说的wandering,我认为这将为您带来不错的结果,并使您的代码更简单。

以下屏幕截图是带有导航的示例。移动的游戏对象也很好地改变了方向,尽管由于游戏对象是胶囊而无法在示例中看到它。

enter image description here

示例程序中的

Ground游戏对象具有NavMesh。请参见here来构建NavMesh。

Agent游戏对象具有NavMeshAgent组件。请参见here进行设置。

下面的行为类适用于Agent游戏对象。

using UnityEngine;
using UnityEngine.AI;

public class NavAgentBehaviour : MonoBehaviour {

    public Transform[] Destinations { get; set; }

    // Use this for initialization
    void Start ()
    {
        InvokeRepeating("changeDestination", 0f, 3f);
    }

    void changeDestination()
    {
        var agent = GetComponent<NavMeshAgent>();
        agent.destination = Destinations[Random.Range(0, Destinations.Length)].position;
    }
}

下一个Behavior类仅用于生成Agent并设置目标。在Unity上,将其设置为场景中的任何游戏对象,然后将游戏对象分配给字段。

using UnityEngine;

public class GameBehaviour : MonoBehaviour {

    public GameObject Agent;
    public Transform SpawnPoint;

    public Transform Destination1;
    public Transform Destination2;
    public Transform Destination3;

    // Use this for initialization
    void Start()
    {
        Agent.SetActive(false);
        InvokeRepeating("Spawn", 0f, 2f);
    }

    void Spawn() {
        var newAgent = Instantiate(Agent);
        newAgent.GetComponent<NavAgentBehaviour>().Destinations = new[] { Destination1, Destination2, Destination3 };
        newAgent.transform.position = SpawnPoint.position;
        newAgent.SetActive(true);
    }
}

增加目的地数,使移动看起来更加随机。顺便说一下,目的地并不需要由游戏对象指定,这只是为了易于查看示例程序的行为。

答案 2 :(得分:0)

抖动的根源在于您正在更新移动每一帧的位置,因此您的对象永远不会有一致的位置移动。相反,我建议为每个对象附加一个新的脚本,这些脚本分别处理它们的移动。在该脚本中,您可以执行以下操作,延迟将目标位置保持1帧以上。

float delaytimer;
Vector3 pos;

void Start () {
    getNewPosition(); // get initial targetpos
}

void Update () {
    delaytimer += Time.deltaTime;

    if (delaytimer > 1) // time to wait 
    {
        getNewPosition(); //get new position every 1 second
        delaytimer = 0f; // reset timer
    }
    transform.position = Vector3.MoveTowards(transform.position, pos, .1f);
}

void getNewPosition()
{
    float x = Random.Range(-22, 22);
    float z= Random.Range(-22, 22);

    pos = new Vector3(x, 0, z);
}

答案 3 :(得分:0)

您正在改变它们在每一帧中的移动方向,这就是造成抖动的原因。

您可以稍等片刻,然后再更改方向。

// Outside update
float betweenChanges = 2;
float lastChange = 0;

// Inside update
if(Time.realtimeSinceStartup > lastChange) 
{
    // Change directions
    // ...

    lastChange = Time.realTimeSinceStart + betweenChanges;
}

您也可以使用InvokeRepeatingCoroutine解决此问题。

如果您不希望所有NPC都同时改变方向,并且仍然像您的示例一样计划控制同一类中的每个NPC,则应该为每个NPC实例添加一个计时器,并使用该计时器来决定何时改变方向。

一个更好的主意是让每个NPC都有自己的Movement-脚本。

相关问题