首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >让AI移动到一个可收藏的地方,调用一个方法,然后飞回统一

让AI移动到一个可收藏的地方,调用一个方法,然后飞回统一
EN

Stack Overflow用户
提问于 2017-09-10 19:35:49
回答 1查看 432关注 0票数 1

我想创造一个追随者AI喜欢斯巴克斯从Spyro。你可以在这段视频中看到机械师

https://youtu.be/2DicrivJ2xc?t=5

Sparx在地面上寻找宝石,飞向它们,然后飞回Spyro。当飞向他们的时候,宝石也开始飞向球员。所以Sparx正在收集宝石。

我已经创建了使创业板飞向播放器的功能。假设我称之为这个方法

代码语言:javascript
复制
StartMovingToPlayer();

Sparx将从脚本中的gem调用此方法。

代码语言:javascript
复制
public class PlayerFollower : Ai
{
    private void OnTriggerEnter(Collider col) // something entered the trigger
    {
        Collectable collectable = col.GetComponent<Collectable>(); // try to get the collectable script

        if (collectable != null) // is it a collectable?
            collectable.StartMovingToPlayer(); // make it move to the player
    }
}

所以我的问题是,如何让AI飞到gem,调用方法,返回,并将触发器中的所有宝石存储在一个队列中,因为当触发器中有多个gem时,AI必须排队。

下面是一个更新,我试图让跟随者在将它们存储在我的列表中时收集它们

公共类PlayerFollower : Ai {私有列表collectablesToCollect =新列表();//在这里存储了所有范围内的宝石--私有bool isCollecting = false;//追随者正在收集宝石吗?专用浮点movementSpeed = 10;//采集速度

代码语言:javascript
复制
private void Update()
{
    if (CollectablesInRange()) // any gems in range?
    {
        if (!isCollecting) // collecting queued?
            MoveToCollectable(); // collect it
    }
    else
    {
        // follow the player
    }
}

private void OnTriggerEnter(Collider col)
{
    Collectable collectable = col.GetComponent<Collectable>(); // get the gem

    if (collectable != null) // is the object a gem?
    {
        if (!collectable.GetMovementState()) // got the gem already collected?
            collectablesToCollect.Add(collectable); // add it to the queue
    }
}

private void OnTriggerExit(Collider col)
{
    Collectable collectable = col.GetComponent<Collectable>();

    if (collectable != null)
        collectablesToCollect.Remove(collectable); // remove it from the queue
}

private void MoveToCollectable() // start collecting
{
    isCollecting = true; 

    if (CollectablesInRange())
    {
        Collectable collectable = collectablesToCollect.First(); just look for one gem
        Vector3 defaultPosition = transform.position;

        transform.position = Vector3.MoveTowards(transform.position, collectable.GetCollectablePosition(), movementSpeed * Time.deltaTime); // move to the gem

        collectable.StartMovingToPlayer(); // call the gems movement

        transform.position = Vector3.MoveTowards(transform.position, defaultPosition, movementSpeed * Time.deltaTime); // move back to the player

        collectablesToCollect.Remove(collectable); // remove it from the queue

        isCollecting = false;

        if (CollectablesInRange()) // collect again, when the list is not empty
            MoveToCollectable();
    }
}

private bool CollectablesInRange()
{
    return collectablesToCollect.Count > 0; // are there any gems in range?
}

}

EN

回答 1

Stack Overflow用户

发布于 2017-09-10 20:30:37

我会这样做:

你有你的代码在宝石(Collectable)和你的代码在你的收集-AI (PlayerFollower)。

PlayerFollower需要一个代表搜索半径的Trigger,它需要一个代表其物理位置的对撞机。也把AI放在自己的物理层上。你的收藏品需要相同的设置,但我建议你将Trigger设置在与AI相同的层上,而碰撞应该与世界相同(所以你可以触摸它,但AI通过)。

每当对象进入具有类型为TriggerPlayerFollower组件的Collectable时,就将其存储在List<Collectable>中。每当一个对象退出具有类型为TriggerPlayerFollower组件的Collectable时,就将其从列表中删除。这就是你如何追踪什么可以收集,什么不能收集。

现在,当一个对象进入Trigger并得到添加时,您将检查是否有当前的目标要移动,如果没有,则将添加的对象设置为目标。

当你的人工智能进入另一个对象的触发器时,这个对象会触发它的OnTriggerEnter并识别AI。它调用AI上的一个方法,该方法声明它现在被收集,并且可能设置一个布尔值,可以从其他对象读取到true,说明它现在已经被收集,不再是世界的一部分了。

此方法从列表中移除对象,并搜索下一个目标(列表中)。当什么都找不到的时候,它就会返回到播放器,等待下一个对象的收集。

AI的可能(未测试)执行:

代码语言:javascript
复制
public class PlayerFollower : AI 
{
    List<Collectable> possibleTargets = new List<Collectable>();
    Collectable target;    

    void OnTriggerEnter(Collider other)
    {
        Collectable collectable = other.GetComponent<Collectable>(); 

        if (collectable != null && !collectable.Collected)
        {
            possibleTargets.Add(collectable);
            SetNextTarget();
        }
    }

    public void Collect(Collectable collectable)
    {
        possibleTargets.Remove(collectable);
        SetNextTarget();
    }

    void SetNextTarget() 
    {
        target = null;
        for(int i = 0; i < possibleTargets.Count; i++)
            if(!possibleTargets[i].Collected)
            {
                target = possibleTargets[i];
                return;
            }
    }
}

可能(未经测试)执行宝石:

代码语言:javascript
复制
public class Collectable : MonoBehaviour
{
    private bool collected;
    public bool Collected { get { return collected; } }

    void OnTriggerEnter(Collider other)
    {
        PlayerFollower ai = other.GetComponent<PlayerFollower>(); 

        if (ai != null)
        {
            collected = true;
            ai.Collect(this);
        }
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46144800

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档