zoukankan      html  css  js  c++  java
  • 自定义OffMeshLink跳跃曲线

    upload_2015-3-25_13-57-30.png 

    很多时候我们需要做类似上图的OffMeshLink的跳跃功能,并方便添加跳跃动画,Unity本身没提供,但是有官方的案例提供了方法,很多人没找到,故贴出来

    原链接:https://github.com/Unity-Technologies/NavMeshComponents/blob/master/Assets/Examples/Scripts/AgentLinkMover.cs

    我在它的基础上添加了两个多播委托及快速转向(红字显示),用来检测跳跃开始及结束,方便用来做跳跃动画的,而且NavMeshAgentde转速太慢,我添加一个快速转向到落地点的方法。

    用不到的就用原版吧。

    using UnityEngine;
    using System.Collections;
    using UnityEngine.AI;
    
    public enum OffMeshLinkMoveMethod
    {
        Teleport,
        NormalSpeed,
        Parabola,
        Curve
    }
    
    [RequireComponent(typeof(NavMeshAgent))]
    public class AgentLinkMover : MonoBehaviour
    {
        public OffMeshLinkMoveMethod method = OffMeshLinkMoveMethod.Parabola;
        public AnimationCurve curve = new AnimationCurve();
        public float CurveTime = .5f;
        public float FaceTime = .1f;
    
        public delegate void OnStartEvent();
        public event OnStartEvent OnStart;
        public delegate void OnCompleteEvent ();
        public event OnCompleteEvent OnComplete;
    
        IEnumerator Start()
        {
            NavMeshAgent agent = GetComponent<NavMeshAgent>();
            agent.autoTraverseOffMeshLink = false;
            while (true)
            {
                if (agent.isOnOffMeshLink)
                {                
                    yield return StartCoroutine (FaceToTarget (agent, FaceTime));
                    if (method == OffMeshLinkMoveMethod.NormalSpeed)
                        yield return StartCoroutine(NormalSpeed(agent));
                    else if (method == OffMeshLinkMoveMethod.Parabola)
                        yield return StartCoroutine(Parabola(agent, 2.0f, 0.5f));
                    else if (method == OffMeshLinkMoveMethod.Curve)
                        yield return StartCoroutine(Curve(agent, CurveTime));
                    agent.CompleteOffMeshLink();
                    agent.updateRotation = true;
                    OnComplete ();
                }
                yield return null;
            }
        }
    
        IEnumerator FaceToTarget(NavMeshAgent agent,float duration){
            agent.updateRotation = false;
            OffMeshLinkData data = agent.currentOffMeshLinkData;
            Quaternion startRotation = agent.transform.rotation;
            Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
            var endRotation = Quaternion.LookRotation (new Vector3 (endPos.x - agent.transform.position.x, 0, endPos.z - transform.position.z));
            float normalizedTime = 0.0f;
            while (normalizedTime < 1.0f)
            {
                agent.transform.rotation = Quaternion.Slerp(startRotation ,endRotation ,normalizedTime);
                normalizedTime += Time.deltaTime / duration;
                yield return null;
            }
            OnStart ();
        }
    
        IEnumerator NormalSpeed(NavMeshAgent agent)
        {
            OffMeshLinkData data = agent.currentOffMeshLinkData;
            Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
            while (agent.transform.position != endPos)
            {
                agent.transform.position = Vector3.MoveTowards(agent.transform.position, endPos, agent.speed * Time.deltaTime);
                yield return null;
            }
        }
        IEnumerator Parabola(NavMeshAgent agent, float height, float duration)
        {
            OffMeshLinkData data = agent.currentOffMeshLinkData;
            Vector3 startPos = agent.transform.position;
            Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
            float normalizedTime = 0.0f;
            while (normalizedTime < 1.0f)
            {
                float yOffset = height * 4.0f * (normalizedTime - normalizedTime * normalizedTime);
                agent.transform.position = Vector3.Lerp(startPos, endPos, normalizedTime) + yOffset * Vector3.up;
                normalizedTime += Time.deltaTime / duration;
                yield return null;
            }
        }
        IEnumerator Curve(NavMeshAgent agent, float duration)
        {
            OffMeshLinkData data = agent.currentOffMeshLinkData;
            Vector3 startPos = agent.transform.position;
            Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
            float normalizedTime = 0.0f;
            while (normalizedTime < 1.0f)
            {
                float yOffset = curve.Evaluate(normalizedTime);
                agent.transform.position = Vector3.Lerp(startPos, endPos, normalizedTime) + yOffset * Vector3.up;
                normalizedTime += Time.deltaTime / duration;
                yield return null;
            }
        }
    }

    用法,附着到NavMeshAgent物体上,选择需要的移动方式即可,然后搭配一下代码食用更佳:

    AgentLinkMover mover = GetComponent<AgentLinkMover>();
    mover.OnStart += () => print("start");
    mover.OnComplete += () => print("complete");
  • 相关阅读:
    js setInterval() 用法示例
    js 判断iframe是否加载完毕
    el表达式 多条件判断
    exception java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment
    oracle 存储过程 示例
    linux下小试redis demo
    关于数组的一些经常使用函数
    大话设计模式—何为设计模式
    窗口间传值的几种方法
    ncurses简单的一个多窗体程序
  • 原文地址:https://www.cnblogs.com/CodeSnippet/p/7835361.html
Copyright © 2011-2022 走看看