首页 > 其他分享 >又一个控制角色移动 NavMeshPlayerControl

又一个控制角色移动 NavMeshPlayerControl

时间:2023-10-30 23:15:54浏览次数:45  
标签:移动 角色 true NavMeshPlayerControl float private NavMeshAgent IsGrounded Animator

在这个的基础上:阴影实现 - 准备工作:场景中行走的角色 - yanghui01 - 博客园 (cnblogs.com),将CharacterController换成了NavMeshAgent,

不过目前功能不完善,仅作为一个参考吧,NavMeshAgent上的跳暂时还不知道怎么实现。

 

效果

 

using UnityEngine;
using UnityEngine.AI;

public class NavMeshPlayerControl : MonoBehaviour
{

    private const float Dir_Speed = 10;
    private const float Gravity = 10;

    [SerializeField]
    private NavMeshAgent m_NavMeshAgent;
    [SerializeField]
    private Animator m_Animator;

    [SerializeField]
    private float m_MoveSpeed = 2;
    [SerializeField]
    private float m_JumpSpeed = 4;
    [SerializeField]
    private bool m_CtrlEnable = true;
    [SerializeField]
    private float m_CheckOnGroundBias = 0.1f;

    private bool m_WasGrounded = true; //上一帧在地面上
    private bool m_IsGrounded = true; //当前在地面上
    private Vector3 m_CurMoveDir = Vector3.zero;

    private float m_JumpTimeStamp = 0;
    private float m_MinJumpInterval = 0.25f; //控制跳跃间隔
    private bool m_JumpInput = false; //控制一帧触发1次

    private Vector3 m_VerticalSpeed = Vector3.zero;

    private float m_GroundY = 0;
    private bool m_GroundYDirty = true;

    void Awake()
    {
        if (!m_NavMeshAgent)
            m_NavMeshAgent = GetComponent<NavMeshAgent>();

        if (!m_Animator)
            m_Animator = GetComponent<Animator>();
    }

    void Start()
    {
        m_NavMeshAgent.updateRotation = false; //自带的太慢了, 角速度设置的很大也很慢
        m_Animator.SetBool("Grounded", true);
    }

    private void Update()
    {
        if (m_CtrlEnable && !m_JumpInput && Input.GetKeyDown(KeyCode.Space))
        {
            m_JumpInput = true;
        }
    }

    private void FixedUpdate()
    {
        m_Animator.SetBool("Grounded", m_IsGrounded);
        DirectUpdate();

        m_WasGrounded = m_IsGrounded;
        m_JumpInput = false;
    }

    private void DirectUpdate()
    {
        float v = 0;
        float h = 0;
        if (m_CtrlEnable)
        {
            v = Input.GetAxis("Vertical");
            h = Input.GetAxis("Horizontal");
        }
        
        //Debug.Log($"v:{v}, h:{h}");
        Transform camera = Camera.main.transform;

        Vector3 inputDir = camera.forward * v + camera.right * h; //摇杆上下为相机forward方向, 左右为相机right方向
        float inputForce = inputDir.magnitude; //区分力度的情况
        inputDir.y = 0;

        if (inputDir != Vector3.zero)
        {
            m_CurMoveDir = Vector3.Slerp(m_CurMoveDir, inputDir, Time.deltaTime * Dir_Speed);

            transform.rotation = Quaternion.LookRotation(m_CurMoveDir);
            m_NavMeshAgent.Move(m_CurMoveDir * m_MoveSpeed * Time.deltaTime);
            m_Animator.SetFloat("MoveSpeed", inputForce); //力度
        }
        else
        {
            m_Animator.SetFloat("MoveSpeed", 0);
        }

        JumpingAndLanding();
    }

    private void JumpingAndLanding()
    {
        bool jumpCooldownOver = (Time.time - m_JumpTimeStamp) >= m_MinJumpInterval;

        if (jumpCooldownOver && m_IsGrounded && m_JumpInput) //地面上按下跳, 多次跳要有一定间隔
        {
            m_JumpTimeStamp = Time.time;
            m_IsGrounded = false;
            m_GroundYDirty = true;
            m_VerticalSpeed.y = m_JumpSpeed;
            Debug.Log($"{GetType().Name}: jump");
        }

        if (!m_IsGrounded) //不在地面上时, 要不断下落
        {
            m_NavMeshAgent.Move(m_VerticalSpeed * Time.deltaTime);
            m_IsGrounded = CheckOnGround();
            if (m_IsGrounded)
            {
                m_VerticalSpeed.y = 0;
            }
            else
            {
                m_VerticalSpeed.y -= Gravity * Time.deltaTime;
            }
        }
        else //在地面上时, 也要不断检测是否需要下落(比如: 从一个高的平台走到低的平台)
        {
            if (!CheckOnGround())
            {
                m_IsGrounded = false;
                m_GroundYDirty = true;
                m_VerticalSpeed.y = 0;
            }
        }

        if (!m_WasGrounded && m_IsGrounded) //之前不在地面上, 现在在地面上了
        {
            m_Animator.SetTrigger("Land");
        }

        if (!m_IsGrounded && m_WasGrounded) //之前在地面上的, 现在不在地面上了
        {
            m_Animator.SetTrigger("Jump");
        }
    }

    private bool CheckOnGround()
    {
        var pos = this.transform.position;
        pos.y += m_NavMeshAgent.radius;
        pos.y -= m_CheckOnGroundBias;
        var isHit = Physics.CheckSphere(pos, m_NavMeshAgent.radius, 1 << LayerMask.NameToLayer("Ground"));
        Debug.DrawLine(pos, pos + Vector3.down * m_NavMeshAgent.radius, Color.red, 0.05f);
        return isHit;
    }

    public float GetGroundY()
    {
        var playerPos = this.transform.position;
        if (!m_IsGrounded)
        {
            if (m_GroundYDirty)
            {
                bool isHit = Physics.Raycast(playerPos, Vector3.down, out var hitInfo, 5);
                if (isHit)
                    m_GroundY = hitInfo.point.y;
                m_GroundYDirty = false;
            }
            return m_GroundY;
        }

        return playerPos.y;
    }

}

 

标签:移动,角色,true,NavMeshPlayerControl,float,private,NavMeshAgent,IsGrounded,Animator
From: https://www.cnblogs.com/sailJs/p/17798226.html

相关文章

  • 5.5G移动通信技术
    5.5G即5G-Advanced,是一种移动通信技术。5.5G是5G和6G之间的过渡阶段,将在速率、时延、连接规模和能耗方面全面超越现有5G,有望实现下行万兆和上行千兆的峰值速率、毫秒级时延和低成本千亿物联。按照国际标准组织3GPP定义,5G到6G 间共存在Release15到Release20六个技术......
  • sql多表连接 ,三表连接查询 用户表、角色表、用户角色关系表
    sql多表连接,三表连接查询文章目录一、普通的三表连接查询。二、加入查询条件、排序、分页、字段重命名的三表连接查询。三、疑问解答(大家有疑问可以在评论区留言,笔者一般一日内会回复):一、普通的三表连接查询。用户表、部门表、用户部门关联表selecta.idasuserI......
  • 将所有的零移动到数组的末尾并保持非零元素的顺序的两种思路及JAVA代码实现
    //思路2:从前向后遍历数组,将非0数字放入一个集合中publicstaticvoidmoveZeroes02(int[]nums){if(nums==null||nums.length==0){return;}if(nums.length==1){return;}//......
  • 【RuoYi移动端】HbuilderX实现底部弹窗示例
    一、单选样式弹窗选择1、View页面代码<uni-popupref="textBox"type="bottom"> <viewclass="select_box"> <viewclass="select_row"v-for="(item,index)instatus"@click="selectClick(item.id)"&g......
  • Leetcode 283. 移动零
    移动零题目链接283.移动零给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。示例1:输入:nums=[0,1,0,3,12]输出:[1,3,12,0,0]示例2:输入:nums=[0]输出:[0]题目解释这道题目......
  • 让物体动起来,Unity的几种移动方式
    一、前言在大部分的Unity游戏开发中,移动是极其重要的一部分,移动的手感决定着游戏的成败,一个优秀的移动手感无疑可以给游戏带来非常舒服的体验。而Unity中有多种移动方法,使用Transform,使用刚体Rigidbody,使用CharacterController,使用NavMesh导航系统等等等等。当然,对于新手来说,最常......
  • 移动端H5使用pdf.js预览
    1.下载pdf.js文件GettingStarted(mozilla.github.io) 2.将下载的文件放进uniapp项目中 3.创建预览页面 代码:<template>   <view>      <web-view:src="allUrl"></web-view>   </view></template><script>   importrequestfro......
  • 手撸移动便签功能
    实现原理  1.位置计算(相对视口)     1.获取鼠标点击坐标     2.获取元素的坐标    3.移动时鼠标位置   2.window.onmouseup=function(){console.log('不再监听移动')//moveBar.onmousedown=nullwindow.on......
  • 2023-10-26 无法访问此网站网址为 http://xxx.yy.com/ 的网页可能暂时无法连接,或者它
    新购一域名,并添加了解析,保存后若干分钟访问该域名,报错显示:原因,我给域名添加的解析地址不正确,所以导致无法找到该服务器,故而报错。看到圈中的【记录值】了吗,这里应该填你的服务器公网ip,如果填错了就无法访问。解决方案,前往你的服务器管理后台,找到域名解析的地方,重新修改解析地......
  • 第五章:移动端事件
    typora-root-url:assetis第五章:移动端事件目标会使用移动端事件开发移动端特效移动端事件封装会使用touch.js移动端事件库1、移动端事件我们之前学习的电脑端事件,点击,双击,鼠标事件等,在手机端是没有的,因为我们很少见到有人在手机上用一个鼠标进行操作,取而代之的是触摸事件等点击事......