C# 将繁殖对象移动到随机位置

C# 将繁殖对象移动到随机位置,c#,unity3d,game-physics,C#,Unity3d,Game Physics,我有一个产卵器对象。每次生成一个游戏对象时,我都希望该对象随机移动(漫游)。我的脚本中的问题是游戏对象的移动非常随机(抖动)。我怎样才能解决这个问题 void Start () { InvokeRepeating("SpawnNPC", Spawntime, Spawntime); } // Update is called once per frame void Update () { population = GameObject.FindGameObjectsWithTa

我有一个产卵器对象。每次生成一个游戏对象时,我都希望该对象随机移动(漫游)。我的脚本中的问题是游戏对象的移动非常随机(抖动)。我怎样才能解决这个问题

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);
}
void Start()
{
调用重复(“SpawnNPC”、Spawntime、Spawntime);
}
//每帧调用一次更新
无效更新(){
population=GameObject.FindGameObjectsWithTag(“NPCobject”);
for(int i=0;i

我用不同的方法创建了新的随机化向量,因为我计划使用pathfinder函数对其进行更改,并将其设置在不同的线程/任务中

抖动的根源来自这样一个事实:您正在更新位置以移动每一帧,因此您的对象永远不会有一个一致的位置来移动。我建议为每个对象附加一个新脚本,分别处理它们的移动。在该脚本中,您可以执行以下操作,这会延迟目标位置保持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);
}

抖动的根源来自这样一个事实:您正在更新位置以移动每一帧,这样您的对象就永远不会有一个一致的位置来移动。我建议为每个对象附加一个新脚本,分别处理它们的移动。在该脚本中,您可以执行以下操作,这会延迟目标位置保持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);
}

您正在为每一帧选择一个新方向。那将永远是非常紧张的。至少在一小段时间后,你不需要改变方向。下面是Unity网站上的一个链接

您正在为每一帧选择一个新方向。那将永远是非常紧张的。至少在一小段时间后,你不需要改变方向。下面是Unity网站上的一个链接

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

你可以等一会儿再改变方向,也许是这样

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

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

    lastChange = Time.realTimeSinceStart + betweenChanges;
}
您还可以通过使用
invokererepeating
corroutine
来解决这个问题

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


更好的办法是让每个NPC都有自己的
移动
-脚本。

您正在改变它们在每个帧中的移动方向,这就是导致抖动的原因

你可以等一会儿再改变方向,也许是这样

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

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

    lastChange = Time.realTimeSinceStart + betweenChanges;
}
您还可以通过使用
invokererepeating
corroutine
来解决这个问题

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

一个更好的办法是让每个NPC都有自己的
动作
-脚本。

如何使用?正如您所说的“漫游”
,我认为它会给您带来一个很好的结果,并使您的代码变得简单

下面的屏幕截图是一个导航示例。移动的游戏对象也在很好地改变它们的方向,尽管在示例中无法看到,因为游戏对象是胶囊

Ground
示例程序中的游戏对象具有
NavMesh
。请参见以构建NavMesh

Agent
游戏对象具有
NavMeshAgent
组件。请注意设置它

下面的行为类用于
代理
游戏对象

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;
    }
}
增加目的地的数量,使移动看起来更随机。顺便说一句,目的地不需要由游戏对象指定,这只是为了便于查看示例程序的行为。

如何使用?正如您所说的“漫游”
,我认为它会给您带来一个很好的结果,并使您的代码变得简单

下面的屏幕截图是一个导航示例。移动的游戏对象也在很好地改变它们的方向,尽管在示例中无法看到,因为游戏对象是胶囊

Ground
示例程序中的游戏对象具有
NavMesh
。请参见以构建NavMesh

Agent
游戏对象具有
NavMeshAgent
组件。请注意设置它

下面的行为类用于
代理
游戏对象

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

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

这是正确的方法是正确的方法是使用navmesh。但我正在尝试让getNewPosition()在另一个线程中运行。例如,在我编写寻路代码之前。但是,谢谢你的回答和解释。这是正确的方法。是的,正确的方法是使用navmesh。但我正在尝试让getNewPosition()在另一个线程中运行。例如,在我编写寻路代码之前。但是,谢谢你的回答和解释。