u3d 控制角色行走

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;

public class PlayerController : MonoBehaviour
{
    private Vector3 target;//目标位置  
    public NavMeshAgent agent;
    public Animation anim;//动画  
    private string locoState = "Locomotion_Stand";
    private Vector3 linkStart;//OffMeshLink的开始点  
    private Vector3 linkEnd;//OffMeshLink的结束点  
    private Quaternion linkRotate;//OffMeshLink的旋转  
    private bool begin;//是否开始寻路  

    public RectTransform maxMap;
    public MeshRenderer dxMeshRenderer;

    public Canvas canvas;

    // Use this for initialization  
    void Start()
    {
        //agent = GetComponent<NavMeshAgent>();
        //自动移动并关闭OffMeshLinks,即在两个隔离障碍物直接生成的OffMeshLink,agent不会自动越过  
        agent.autoTraverseOffMeshLink = false;
        //创建动画  
        AnimationSetup();
        //起一个协程,处理动画状态机  
        StartCoroutine(AnimationStateMachine());
    }

    void Update()
    {
        //鼠标左键点击  
        if (Input.GetMouseButtonDown(0))
        {
            if (EventSystem.current.IsPointerOverGameObject())
            {
                //float mapX = Input.mousePosition.x - (Screen.width - maxMap.rect.width);
                //float mapY = Input.mousePosition.y - (Screen.height - maxMap.rect.height);

                //float realX = (mapX / maxMap.rect.width) * dxMeshRenderer.bounds.size.x - dxMeshRenderer.bounds.size.x / 2;
                //float realY = (mapY / maxMap.rect.height) * dxMeshRenderer.bounds.size.y - dxMeshRenderer.bounds.size.y / 2;
                //Debug.Log(realX + "返回" + realY);

                //等比例求点击点在实体地图中的位置
                //Vector2 vector2 = Input.mousePosition;
                //Vector3 target = new Vector3(-vector2.x * dxMeshRenderer.bounds.size.x / maxMap.rect.width, 0, -vector2.y * dxMeshRenderer.bounds.size.z / maxMap.rect.height);
                //Debug.Log("返回" + target);

                //Vector2 pos = Vector2.zero;
                //if (RectTransformUtility.ScreenPointToLocalPointInRectangle(maxMap, Input.mousePosition, canvas.worldCamera, out pos))
                //{
                //    GameObject.Find("MainEvent").GetComponent<MaxMapScript>().SetModelPos(pos);
                //    Debug.Log(pos);
                //}
                Debug.Log("点击到UGUI的UI界面,会返回true");
            }
            else
            {
                //摄像机到点击位置的的射线  
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit))
                {
                    //判断点击的是否地形  
                    if (hit.collider.gameObject.layer == LayerMask.NameToLayer("walk"))
                    {
                        begin = true;
                        //点击位置坐标  
                        target = hit.point;
                    }
                }
                //Debug.Log("如果没点击到UGUI上的任何东西,就会返回false");
            }

        }
        //每一帧,设置目标点  
        if (begin)
        {
            agent.SetDestination(target);
        }
    }

    IEnumerator AnimationStateMachine()
    {
        //根据locoState不同的状态来处理,调用相关的函数  
        while (Application.isPlaying)
        {
            yield return StartCoroutine(locoState);
        }
    }

    //站立  
    IEnumerator Locomotion_Stand()
    {
        do
        {
            UpdateAnimationBlend();
            yield return new WaitForSeconds(0);
        } while (agent.remainingDistance == 0);
        //未到达目标点,转到下一个状态Locomotion_Move  
        locoState = "Locomotion_Move";
        yield return null;
    }

    IEnumerator Locomotion_Move()
    {
        do
        {
            UpdateAnimationBlend();
            yield return new WaitForSeconds(0);
            //角色处于OffMeshLink,根据不同的地点,选择不同动画  
            if (agent.isOnOffMeshLink)
            {
                locoState = SelectLinkAnimation();
                yield return true;
            }
        } while (agent.remainingDistance != 0);
        //已经到达目标点,状态转为Stand  
        locoState = "Locomotion_Stand";
        yield return null;
    }

    IEnumerator Locomotion_Jump()
    {
        //播放跳跃动画  
        string linkAnim = "RunJump";
        Vector3 posStart = transform.position;

        agent.Stop(true);
        anim.CrossFade(linkAnim, 0.1f, PlayMode.StopAll);
        transform.rotation = linkRotate;

        do
        {
            //计算新的位置  
            float tlerp = anim[linkAnim].normalizedTime;
            Vector3 newPos = Vector3.Lerp(posStart, linkEnd, tlerp);
            newPos.y += 0.4f * Mathf.Sin(3.14159f * tlerp);
            transform.position = newPos;

            yield return new WaitForSeconds(0);
        } while (anim[linkAnim].normalizedTime < 1);
        //动画恢复到Idle  
        anim.Play("Idle");
        agent.CompleteOffMeshLink();
        agent.Resume();
        //下一个状态为Stand  
        transform.position = linkEnd;
        locoState = "Locomotion_Stand";
        yield return null;
    }
    //梯子  
    IEnumerator Locomotion_Ladder()
    {
        //梯子的中心位置  
        Vector3 linkCenter = (linkStart + linkEnd) * 0.5f;
        string linkAnim;
        //判断是在梯子上还是梯子下  
        if (transform.position.y > linkCenter.y)
            linkAnim = "Ladder Down";
        else
            linkAnim = "Ladder Up";

        agent.Stop(true);

        Quaternion startRot = transform.rotation;
        Vector3 startPos = transform.position;
        float blendTime = 0.2f;
        float tblend = 0f;

        //角色的位置插值变化(0.2内变化)  
        do
        {
            transform.position = Vector3.Lerp(startPos, linkStart, tblend / blendTime);
            transform.rotation = Quaternion.Lerp(startRot, linkRotate, tblend / blendTime);

            yield return new WaitForSeconds(0);
            tblend += Time.deltaTime;
        } while (tblend < blendTime);
        //设置位置  
        transform.position = linkStart;
        //播放动画  
        anim.CrossFade(linkAnim, 0.1f, PlayMode.StopAll);
        agent.ActivateCurrentOffMeshLink(false);
        //等待动画结束  
        do
        {
            yield return new WaitForSeconds(0);
        } while (anim[linkAnim].normalizedTime < 1);
        agent.ActivateCurrentOffMeshLink(true);
        //恢复Idle状态  
        anim.Play("Idle");
        transform.position = linkEnd;
        agent.CompleteOffMeshLink();
        agent.Resume();
        //下一个状态Stand  
        locoState = "Locomotion_Stand";
        yield return null;
    }

    private string SelectLinkAnimation()
    {
        //获得当前的OffMeshLink数据  
        OffMeshLinkData link = agent.currentOffMeshLinkData;
        //计算角色当前是在link的开始点还是结束点(因为OffMeshLink是双向的)  
        float distS = (transform.position - link.startPos).magnitude;
        float distE = (transform.position - link.endPos).magnitude;

        if (distS < distE)
        {
            linkStart = link.startPos;
            linkEnd = link.endPos;
        }
        else
        {
            linkStart = link.endPos;
            linkEnd = link.startPos;
        }
        //OffMeshLink的方向  
        Vector3 alignDir = linkEnd - linkStart;
        //忽略y轴  
        alignDir.y = 0;
        //计算旋转角度  
        linkRotate = Quaternion.LookRotation(alignDir);

        //判断OffMeshLink是手动的(楼梯)还是自动生成的(跳跃)  
        if (link.linkType == OffMeshLinkType.LinkTypeManual)
        {
            return ("Locomotion_Ladder");
        }
        else
        {
            return ("Locomotion_Jump");
        }
    }

    private void AnimationSetup()
    {
        //anim = GetComponent<Animation>();

        // 把walk和run动画放到同一层,然后同步他们的速度。  
        //anim["Walk"].layer = 1;
        //anim["Run"].layer = 1;
        //anim.SyncLayer(1);

        设置“跳跃”,“爬楼梯”,“下楼梯”的动画模式和速度  
        //anim["RunJump"].wrapMode = WrapMode.ClampForever;
        //anim["RunJump"].speed = 2;
        //anim["Ladder Up"].wrapMode = WrapMode.ClampForever;
        //anim["Ladder Up"].speed = 2;
        //anim["Ladder Down"].wrapMode = WrapMode.ClampForever;
        //anim["Ladder Down"].speed = 2;

        //初始化动画状态为Idle  
        anim.CrossFade("Idle", 0.1f, PlayMode.StopAll);
    }
    //更新动画融合  
    private void UpdateAnimationBlend()
    {
        //行走速度  
        float walkAnimationSpeed = 1.5f;
        //奔跑速度  
        float runAnimationSpeed = 4.0f;
        //速度阀值(idle和walk的临界点)  
        float speedThreshold = 0.1f;

        //速度,只考虑x和z  
        Vector3 velocityXZ = new Vector3(agent.velocity.x, 0.0f, agent.velocity.z);
        //速度值  
        float speed = velocityXZ.magnitude;
        //设置Run动画的速度  
        anim["Run"].speed = speed / runAnimationSpeed;
        //设置Walk动画的速度  
        anim["Walk"].speed = speed / walkAnimationSpeed;

        //根据agent的速度大小,确定animation的播放状态  
        if (speed > (walkAnimationSpeed + runAnimationSpeed) / 2)
        {
            anim.CrossFade("Run");
        }
        else if (speed > speedThreshold)
        {
            anim.CrossFade("Walk");
        }
        else
        {
            //anim.CrossFade("Idle");
            anim.CrossFade("Idle", 0.1f, PlayMode.StopAll);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值