我已经设置了 Unity 导航网格(四个平面)、导航代理(球体)并设置了自动和手动关闭网格链接。它现在应该在网格之间跳转。它确实在网格之间跳跃,但它是直线跳跃的。
换句话说,当代理到达边缘时,它并没有真正跳起来(就像绘制了脱离网格的链接),它只是直线移动,但速度更快。我尝试将一架飞机移动得比其他飞机高,但球体仍在直线跳跃。
它应该是这样的吗?是否可以设置导航以跳跃某些曲线?还是我应该尝试自己实现?
我已经设置了 Unity 导航网格(四个平面)、导航代理(球体)并设置了自动和手动关闭网格链接。它现在应该在网格之间跳转。它确实在网格之间跳跃,但它是直线跳跃的。
换句话说,当代理到达边缘时,它并没有真正跳起来(就像绘制了脱离网格的链接),它只是直线移动,但速度更快。我尝试将一架飞机移动得比其他飞机高,但球体仍在直线跳跃。
它应该是这样的吗?是否可以设置导航以跳跃某些曲线?还是我应该尝试自己实现?
我是通过这个问题来的,不得不深入研究 Unity 示例。我只是希望通过提取重要的部分来让人们更容易。
要在 navmesh 链接上应用您自己的动画/过渡,您需要告诉 Unity 您将处理所有 offmesh 链接遍历,然后添加定期检查代理是否在 offmesh 链接上的代码。最后,当转换完成时,您需要告诉 Unity 您已移动代理,并恢复正常的导航网格行为。
您处理链接逻辑的方式取决于您。你可以直接走直线,有一个旋转的虫洞,无论如何。对于跳转,unity 使用动画进度作为 lerp 参数遍历链接,这非常有效。(如果您正在制作循环或更复杂的动画,则效果不佳)
重要的统一位是:
_navAgent.autoTraverseOffMeshLink = false; //in Start()
_navAgent.currentOffMeshLinkData; //the link data - this contains start and end points, etc
_navAgent.CompleteOffMeshLink(); //Tell unity we have traversed the link (do this when you've moved the transform to the end point)
_navAgent.Resume(); //Resume normal navmesh behaviour
现在是一个简单的跳跃示例...
using UnityEngine;
[RequireComponent(typeof(NavMeshAgent))]
public class NavMeshAnimator : MonoBehaviour
{
private NavMeshAgent _navAgent;
private bool _traversingLink;
private OffMeshLinkData _currLink;
void Start()
{
// Cache the nav agent and tell unity we will handle link traversal
_navAgent = GetComponent<NavMeshAgent>();
_navAgent.autoTraverseOffMeshLink = false;
}
void Update()
{
//don't do anything if the navagent is disabled
if (!_navAgent.enabled) return;
if (_navAgent.isOnOffMeshLink)
{
if (!_traversingLink)
{
//This is done only once. The animation's progress will determine link traversal.
animation.CrossFade("Jump", 0.1f, PlayMode.StopAll);
//cache current link
_currLink = _navAgent.currentOffMeshLinkData;
//start traversing
_traversingLink = true;
}
//lerp from link start to link end in time to animation
var tlerp = animation["Jump"].normalizedTime;
//straight line from startlink to endlink
var newPos = Vector3.Lerp(_currLink.startPos, _currLink.endPos, tlerp);
//add the 'hop'
newPos.y += 2f * Mathf.Sin(Mathf.PI * tlerp);
//Update transform position
transform.position = newPos;
// when the animation is stopped, we've reached the other side. Don't use looping animations with this control setup
if (!animation.isPlaying)
{
//make sure the player is right on the end link
transform.position = _currLink.endPos;
//internal logic reset
_traversingLink = false;
//Tell unity we have traversed the link
_navAgent.CompleteOffMeshLink();
//Resume normal navmesh behaviour
_navAgent.Resume();
}
}
else
{
//...update walk/idle animations appropriately ...etc
建议通过动画解决您的问题。只需为您的对象创建一个Jump
动画,并在正确的时间播放它。该位置是相对的,因此如果您在动画中增加 Y 位置,它看起来就像对象在跳跃。
这也是 Unity 示例的工作方式,士兵四处奔跑。
不确定你使用的是什么版本的统一,但你也可以试试这个,我知道它在 4 中工作得很好:
string linkType = GetComponent<NavMeshAgent>().currentOffMeshLinkData.linkType.ToString();
if(linkType == "LinkTypeJumpAcross"){
Debug.Log ("Yeah im in the jump already ;)");
}
也只是给你一些额外的麻烦,最好使用代理并遵循 navAgent 游戏对象:
就像是:
AIMan = this.transform.position; AI_Proxy.transform.position = AIMan;
并且一定要使用:
AI_Proxy.animation["ProxyJump"].blendMode = AnimationBlendMode.Additive;
如果您使用的是内置的统一动画!
K,这是我这周的好事。
修复 update() 中的位置
if (agent.isOnOffMeshLink)
{
transform.position = new Vector3(transform.position.x, 0f, transform.position.z);
}