3

我已经设置了 Unity 导航网格(四个平面)、导航代理(球体)并设置了自动和手动关闭网格链接。它现在应该在网格之间跳转。它确实在网格之间跳跃,但它是直线跳跃的。

换句话说,当代理到达边缘时,它并没有真正跳起来(就像绘制了脱离网格的链接),它只是直线移动,但速度更快。我尝试将一架飞机移动得比其他飞机高,但球体仍在直线跳跃。

它应该是这样的吗?是否可以设置导航以跳跃某些曲线?还是我应该尝试自己实现?

4

4 回答 4

13

我是通过这个问题来的,不得不深入研究 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
于 2012-11-09T12:31:32.470 回答
2

建议通过动画解决您的问题。只需为您的对象创建一个Jump动画,并在正确的时间播放它。该位置是相对的,因此如果您在动画中增加 Y 位置,它看起来就像对象在跳跃。

这也是 Unity 示例的工作方式,士兵四处奔跑。

于 2012-09-03T12:23:45.957 回答
0

不确定你使用的是什么版本的统一,但你也可以试试这个,我知道它在 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,这是我这周的好事。

于 2013-06-19T19:41:28.177 回答
0

修复 update() 中的位置

if (agent.isOnOffMeshLink)
 {
    transform.position =  new Vector3(transform.position.x, 0f, transform.position.z);       
 }
于 2021-02-12T12:28:55.360 回答