我想从Spyro创建一个像Sparx这样的追随者AI . 您可以在此视频中查看机制
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,调用方法,飞回 and have all the gems in the trigger stored in a queue 因为当触发器中有多个gem时,AI必须排队 .
所以这是一个 update ,我试图让追随者收集宝石时将它们存储在我的列表中
public class PlayerFollower:Ai {private List collectablesToCollect = new List(); //将范围内的所有宝石存储在此处私有bool isCollecting = false; //是目前正在收集宝石的追随者吗?私人浮动运动速度= 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?
}
}
1 回答
这就是我要做的事情:
您在Gem(
Collectable
)上有代码,而您的代码在Collecting-AI(PlayerFollower
)上 .PlayerFollower
需要一个代表其搜索半径的Trigger
,它需要一个代表其物理位置的对撞机 . 还将AI放在自己的物理层上 . 您的收藏品需要相同的设置,但我建议您将Trigger
设置在与AI相同的层上,而碰撞应该与世界相同(因此您可以触摸它,但AI会通过) .每当一个对象进入
PlayerFollower
的PlayerFollower
时,其组件类型为Collectable
,就将其存储在List<Collectable>
中 . 每当一个对象退出_544390_的_544390_,其组件类型为Collectable
时,您将从列表中删除它 . 这就是你如何追踪可以收集和不收集的东西 .现在,当一个对象进入
Trigger
并被添加时,您将检查是否有当前目标要移动到,如果没有,则将添加的对象设置为目标 .当您的AI进入另一个对象的触发器时,此对象会被激活
OnTriggerEnter
并识别AI . 它在AI上调用一个方法,声明它现在被收集并且可能设置一个布尔值,可以从其他对象读取到true
,声明它现在已经被收集而不再是世界的一部分 .此方法从列表中删除对象并搜索下一个目标(在列表中) . 当什么都找不到时,它就会回到播放器并等待下一个要收集的对象 .
AI的可能(未经测试)实现:
Gem的可能(未经测试)实现: