使AI移至可收集对象,调用方法并在Unity中飞回 [英] Make an AI move to a collectable, call a method and fly back in Unity

查看:92
本文介绍了使AI移至可收集对象,调用方法并在Unity中飞回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个跟随者AI,例如Spyro的Sparx.您可以在此视频中看到机制

I want to create a follower AI like Sparx from Spyro. You can see the mechanics in this video

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

Sparx在地面上寻找宝石,然后飞向它们,然后飞回Spyro.当飞向他们时,宝石也开始飞向玩家.因此,Sparx正在收集宝石.

Sparx looks for gems on the ground, flies to them and flies back to Spyro. When flying to them, the gems start to fly to the player too. So Sparx is collecting the gems.

我已经创建了使宝石飞向播放器的功能.假设我叫这个方法

I already created the functionality making the gem fly to the player. Let's say I call this method

StartMovingToPlayer();

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

Sparx will call this method from the gem in his script.

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存储在队列中,因为触发器中只有一颗宝石,人工智能必须将其排队.

So my question is, how can I make the AI fly to the gem, call the method, fly back and have all the gems in the trigger stored in a queue because when there is more than one gem in the trigger, the AI has to queue it.

所以这是一个更新,我试图让追随者在将宝石存储在列表中时收集宝石

So here's an update, I tried to make the follower collecting the gems when having them stored in my list

公共类PlayerFollower:Ai { 私有列表collectablesToCollect = new List();//将所有范围内的宝石都存储在这里 私人布尔isCollecting = false;//追随者当前正在收集宝石吗? 私人浮动运动速度= 10;//收集速度

public class PlayerFollower : Ai { private List collectablesToCollect = new List(); // have all the gems in range stored here private bool isCollecting = false; // is the follower currently collecting gems? private float movementSpeed = 10; // collecting speed

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

}

推荐答案

这就是我要做的:

您在Gem(Collectable)上有代码,在Collecting-AI(PlayerFollower)上有代码.

You have your code on the Gem (Collectable) and your code on your Collecting-AI (PlayerFollower).

PlayerFollower需要一个表示其搜索半径的Trigger,并且需要一个表示其物理位置的对撞机.还要将AI放在自己的物理层上.您的收藏品需要相同的设置,但是我建议您将Trigger设置为与AI相同的层,而碰撞应该与世界相同(以便可以触摸它,但AI可以通过)

PlayerFollower needs a Trigger that represents its search-radius and it needs a collider that represents its physical position. Also put the AI on its own physical layer. Your collectables require the same setup, but I would advise you to set the Trigger on the same layer as the AI, while the collision should be on he same as the world (so you can touch it, but the AI passes through).

只要对象进入PlayerFollowerTrigger具有类型为Collectable的组件,就将其存储在List<Collectable>中.每当对象退出PlayerFollowerTrigger具有类型为Collectable的组件时,就将其从列表中删除.这样便可以跟踪可收集的内容和无法收集的内容.

Whenever an object enters the Trigger of PlayerFollower that has a component of type Collectable, you store it in a List<Collectable>. Whenever an object exits the Trigger of PlayerFollower that has a component of type Collectable, you remove it from the list. That's how you track what can be collected and what not.

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

Now when an object enters the Trigger and gets added, you check if you have a current target to move to and if not, you set the added object as target.

当您的AI输入另一个对象的触发器时,此对象将触发其OnTriggerEnter并识别该AI.它在AI上调用了一个方法,该方法声明它现在已被收集,并可能将一个可以从其他对象读取的布尔值设置为true,表明它现在已被收集,不再是世界的一部分.

When your AI enters the trigger of another object, this object gets its OnTriggerEnter fired and recognizes the AI. It calls a method on the AI that states that it is now collected and probably sets a boolean that can be read from other objects to true, stating that it is now collected and not part of the world anymore.

此方法从列表中删除对象并搜索下一个目标(在列表中).如果什么也找不到,它会回到播放器并等待下一个物体的收集.

This method removes the object from the list and searches for the next target (in the list). When nothing can be found, it just goes back to the player and waits for the next object to collect.

AI的可能(未经测试)实施:

Possible (not tested) implementation for the AI:

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


宝石的可能(未经测试)实施:


Possible (not tested) implementation for the Gem:

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

这篇关于使AI移至可收集对象,调用方法并在Unity中飞回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆