是否有一个可行的解决方案可以启用/禁用 NavMeshAgent 组件而不丢失 NavMesh?

发布于 2025-01-16 22:56:11 字数 5963 浏览 5 评论 0原文

在开始之前,我先说一下我已经尽力做了功课。

Unity3D 如何连接 NavMesh 和 NavMeshAgent -- 建议我在代理接地后循环组件

        while (!stateManager.cow.isGrounded())
    {
        Debug.Log("Waiting");
        yield return new WaitForEndOfFrame();
    }
    Debug.Log("Did it");
    stateManager.cow.agent.enabled = false;
    stateManager.cow.agent.enabled = true;
    stateManager.cow.agent.SetDestination((Player.instance.gameObject.transform.position - stateManager.cow.gameObject.transform.position).normalized * 5);
    yield return null;

“无法创建 NavAgent”错误,但现在代理的行为就好像我没有给它指定目的地一样。 (世界大小为 750x750,随机距离设置为 100 米,起点为 Vector3.zero,因此我有理由确定 SamplePosition 不是问题,因为所选目的地不可能超出更重要的是,Idle 状态运行相同的 SetDestination() 方法,并输入相同的随机变量,直到 IsBeingAbducted 状态释放 Cow。并且它回到了寻路突然成为问题的地面)

使用 Unity 时收到警告“无法创建代理,因为没有有效的 Navmesh” -- 根本没有答案

unity 中的 NavMeshAgent 无法工作 -- 建议正确烘焙我的网格但是 -

照片显示正确烘焙的 NavMesh 的蓝色覆盖层

另外,我已经查看了 Unity 的 API,但找不到我的错误。

所以这是我正在使用的代码 --

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BeingAbducted : CowState
{
    public override void EnterState(CattleStateManager stateManager)
    {
        //Debug.Log("Entering BeingAbducted State");

        // Set gravity use to false
        stateManager.cow.rigidBody.useGravity = false;
        // Disable agent control
        stateManager.cow.agent.enabled = false;
        // Set isBeingAbducted to true
        stateManager.cow.isBeingAbducted = true;
        // Set timer for abduction to starting value
        stateManager.cow.abductionTimer = 0.0f;
        // Play the moo hurt sound
        AudioManager.instance.Play(Sounds.HurtMoo_1, stateManager.cow.transform.position);

    }

    public override void UpdateState(CattleStateManager stateManager)
    {
        //Debug.Log("Updating BeingAbducted State");
        // Begin incrementing timer
        stateManager.cow.abductionTimer += Time.deltaTime;
        // Move towards raycast point
        Vector3 newCowPosition = 
        Vector3.MoveTowards(stateManager.cow.gameObject.transform.position, 
        Player.instance.tractorBeam.rayCastOrigin.position, 5 * Time.deltaTime);
        stateManager.cow.agent.baseOffset = newCowPosition.y * 120;
        stateManager.cow.gameObject.transform.position = newCowPosition;
        // suspend in air at set height

        if (stateManager.cow.gameObject.transform.position.y >= 7)
       {
            Vector3 lockedHeightVector = new Vector3(stateManager.cow.gameObject.transform.position.x, 7, stateManager.cow.gameObject.transform.position.z);
            stateManager.cow.gameObject.transform.position = lockedHeightVector;
       }
       // BeginTransition 
    stateManager.cow.skinnedMeshRenderer.material.SetFloat("_DissolveAmount", (stateManager.cow.abductionTimer / stateManager.cow.timeToAbductCow));

        if (stateManager.cow.abductionTimer >= stateManager.cow.timeToAbductCow)
        {
            stateManager.SwitchState(CattleState.Abducted);
        }
    }
    public override void ExitState(CattleStateManager stateManager)
    {
        //Debug.Log("Exiting BeingAbducted State");

        if (stateManager.cow.abductionTimer < stateManager.cow.timeToAbductCow)
        {
            stateManager.cow.skinnedMeshRenderer.material.SetFloat("_DissolveAmount", 0);
            stateManager.cow.rigidBody.useGravity = true;
            stateManager.cow.agent.baseOffset = 0;
        }

    }

    public override void OnCollisionEnter(CattleStateManager stateManager, Collision collision)
    {

    }
}

以及相应的脚本 --

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RunAway : CowState
{
    public override void EnterState(CattleStateManager stateManager)
    {
        Debug.Log("Entering RunAway State");
        // set agent destination to a random long distance opposite player
        stateManager.StartCoroutine(AgentGrounded(stateManager));
    }

    public override void UpdateState(CattleStateManager stateManager)
    {
        Debug.Log("Updating RunAway State");

        // run the path
        // increase the animation velocity to match the navagent velocity
        // moo a lot
        if (stateManager.cow.agent.isOnNavMesh)
        {
        
stateManager.cow.agent.SetDestination((Player.instance.gameObject.transform.position - stateManager.cow.gameObject.transform.position).normalized * 5);
        }

    }
    public override void ExitState(CattleStateManager stateManager)
    {
        Debug.Log("Exiting RunAway State");
    }

    public override void OnCollisionEnter(CattleStateManager stateManager, Collision collision)
    {

    }

    public IEnumerator AgentGrounded(CattleStateManager stateManager)
    {
        while (!stateManager.cow.isGrounded())
        {
            Debug.Log("Waiting");
            yield return new WaitForEndOfFrame();
        }
        Debug.Log("Did it");
        stateManager.cow.agent.enabled = false;
        stateManager.cow.agent.enabled = true;
        stateManager.cow.agent.SetDestination((Player.instance.gameObject.transform.position - stateManager.cow.gameObject.transform.position).normalized * 5);
        yield return null;
    }
}

所以总而言之,我需要一种方法将牛抬离地面,然后当把它放回地面时,我需要牛逃跑。这是一个简单的 StateMachine 实现,协程存在于静态类中,但由派生自 Monobehavior 的上下文运行。

就像我说的,我尝试的每个问题都会导致相同的错误 - 代理被降低、启用并分配了目的地,但什么也不做。

Before I begin, let me say I have tried hard to do the homework first.

Unity3D how to connect NavMesh and NavMeshAgent -- Suggested I cycle the component after the agent is grounded

        while (!stateManager.cow.isGrounded())
    {
        Debug.Log("Waiting");
        yield return new WaitForEndOfFrame();
    }
    Debug.Log("Did it");
    stateManager.cow.agent.enabled = false;
    stateManager.cow.agent.enabled = true;
    stateManager.cow.agent.SetDestination((Player.instance.gameObject.transform.position - stateManager.cow.gameObject.transform.position).normalized * 5);
    yield return null;

That stopped the 'Failed To Create NavAgent' error but now the agent acts as if I've given it no destination. (The world size is 750x750, the random distance is set to 100 meters, and the starting point is Vector3.zero, so I'm reasonably sure a SamplePosition isn't the issue as the chosen destination couldn't possible be outside of the realms of possible. What's more, the Idle state runs the same SetDestination() method with the same random variables fed in just fine. It isn't until the IsBeingAbducted state Releases the Cow and it returns to the ground that pathfinding suddenly becomes an issue)

Getting warning "Failed to create agent because there is no valid Navmesh" using Unity -- Has no Answers at all

NavMeshAgent in unity not working -- suggests to properly bake my mesh but -

Photo shows the blue overlay of a properly baked NavMesh

Plus I've reviewed the API from Unity, and I just can't find my error.

So here is the code I'm working with --

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BeingAbducted : CowState
{
    public override void EnterState(CattleStateManager stateManager)
    {
        //Debug.Log("Entering BeingAbducted State");

        // Set gravity use to false
        stateManager.cow.rigidBody.useGravity = false;
        // Disable agent control
        stateManager.cow.agent.enabled = false;
        // Set isBeingAbducted to true
        stateManager.cow.isBeingAbducted = true;
        // Set timer for abduction to starting value
        stateManager.cow.abductionTimer = 0.0f;
        // Play the moo hurt sound
        AudioManager.instance.Play(Sounds.HurtMoo_1, stateManager.cow.transform.position);

    }

    public override void UpdateState(CattleStateManager stateManager)
    {
        //Debug.Log("Updating BeingAbducted State");
        // Begin incrementing timer
        stateManager.cow.abductionTimer += Time.deltaTime;
        // Move towards raycast point
        Vector3 newCowPosition = 
        Vector3.MoveTowards(stateManager.cow.gameObject.transform.position, 
        Player.instance.tractorBeam.rayCastOrigin.position, 5 * Time.deltaTime);
        stateManager.cow.agent.baseOffset = newCowPosition.y * 120;
        stateManager.cow.gameObject.transform.position = newCowPosition;
        // suspend in air at set height

        if (stateManager.cow.gameObject.transform.position.y >= 7)
       {
            Vector3 lockedHeightVector = new Vector3(stateManager.cow.gameObject.transform.position.x, 7, stateManager.cow.gameObject.transform.position.z);
            stateManager.cow.gameObject.transform.position = lockedHeightVector;
       }
       // BeginTransition 
    stateManager.cow.skinnedMeshRenderer.material.SetFloat("_DissolveAmount", (stateManager.cow.abductionTimer / stateManager.cow.timeToAbductCow));

        if (stateManager.cow.abductionTimer >= stateManager.cow.timeToAbductCow)
        {
            stateManager.SwitchState(CattleState.Abducted);
        }
    }
    public override void ExitState(CattleStateManager stateManager)
    {
        //Debug.Log("Exiting BeingAbducted State");

        if (stateManager.cow.abductionTimer < stateManager.cow.timeToAbductCow)
        {
            stateManager.cow.skinnedMeshRenderer.material.SetFloat("_DissolveAmount", 0);
            stateManager.cow.rigidBody.useGravity = true;
            stateManager.cow.agent.baseOffset = 0;
        }

    }

    public override void OnCollisionEnter(CattleStateManager stateManager, Collision collision)
    {

    }
}

And the corresponding script --

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RunAway : CowState
{
    public override void EnterState(CattleStateManager stateManager)
    {
        Debug.Log("Entering RunAway State");
        // set agent destination to a random long distance opposite player
        stateManager.StartCoroutine(AgentGrounded(stateManager));
    }

    public override void UpdateState(CattleStateManager stateManager)
    {
        Debug.Log("Updating RunAway State");

        // run the path
        // increase the animation velocity to match the navagent velocity
        // moo a lot
        if (stateManager.cow.agent.isOnNavMesh)
        {
        
stateManager.cow.agent.SetDestination((Player.instance.gameObject.transform.position - stateManager.cow.gameObject.transform.position).normalized * 5);
        }

    }
    public override void ExitState(CattleStateManager stateManager)
    {
        Debug.Log("Exiting RunAway State");
    }

    public override void OnCollisionEnter(CattleStateManager stateManager, Collision collision)
    {

    }

    public IEnumerator AgentGrounded(CattleStateManager stateManager)
    {
        while (!stateManager.cow.isGrounded())
        {
            Debug.Log("Waiting");
            yield return new WaitForEndOfFrame();
        }
        Debug.Log("Did it");
        stateManager.cow.agent.enabled = false;
        stateManager.cow.agent.enabled = true;
        stateManager.cow.agent.SetDestination((Player.instance.gameObject.transform.position - stateManager.cow.gameObject.transform.position).normalized * 5);
        yield return null;
    }
}

So all in all I need a way to lift the cow off of the ground, then when returning it to the ground, I need the cow to run away. This is a simple StateMachine implementation and the Coroutine exists in the static class, yet is ran by the context which derives from Monobehavior.

Like I said though, every issue I try results in the same error -- the Agent get's lowered, enabled, and a destination assigned, yet does nothing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文