我想创造一个追随者AI喜欢斯巴克斯从Spyro。你可以在这段视频中看到机械师
https://youtu.be/2DicrivJ2xc?t=5
Sparx在地面上寻找宝石,飞向它们,然后飞回Spyro。当飞向他们的时候,宝石也开始飞向球员。所以Sparx正在收集宝石。
我已经创建了使创业板飞向播放器的功能。假设我称之为这个方法
StartMovingToPlayer();Sparx将从脚本中的gem调用此方法。
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;//采集速度
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?
}}
发布于 2017-09-10 20:30:37
我会这样做:
你有你的代码在宝石(Collectable)和你的代码在你的收集-AI (PlayerFollower)。
PlayerFollower需要一个代表搜索半径的Trigger,它需要一个代表其物理位置的对撞机。也把AI放在自己的物理层上。你的收藏品需要相同的设置,但我建议你将Trigger设置在与AI相同的层上,而碰撞应该与世界相同(所以你可以触摸它,但AI通过)。
每当对象进入具有类型为Trigger的PlayerFollower组件的Collectable时,就将其存储在List<Collectable>中。每当一个对象退出具有类型为Trigger的PlayerFollower组件的Collectable时,就将其从列表中删除。这就是你如何追踪什么可以收集,什么不能收集。
现在,当一个对象进入Trigger并得到添加时,您将检查是否有当前的目标要移动,如果没有,则将添加的对象设置为目标。
当你的人工智能进入另一个对象的触发器时,这个对象会触发它的OnTriggerEnter并识别AI。它调用AI上的一个方法,该方法声明它现在被收集,并且可能设置一个布尔值,可以从其他对象读取到true,说明它现在已经被收集,不再是世界的一部分了。
此方法从列表中移除对象,并搜索下一个目标(列表中)。当什么都找不到的时候,它就会返回到播放器,等待下一个对象的收集。
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;
}
}
}可能(未经测试)执行宝石:
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);
}
}
}https://stackoverflow.com/questions/46144800
复制相似问题