• Unity 角色控制器的几种实现方式(CharacterController驱动,刚体驱动,动画驱动)


    一.CharacterController组件驱动

    这是常用的角色控制方式,但是最大的缺点就是无法被力所驱动,因此,很难做出冲撞的抵触效果

    另外这里要说明:

    第一种:characterController.SimpleMove(Speed);
    第二种:characterController.Move(Speed*deltaTime);
    发生的问题:第一种和第二种垂直移动效果不同。
    解决:官方文档:第一种始终使用的是系统的默认垂直加速度,而第二种要自己实现。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 角色控制器控制角色物理效果
    /// </summary>
    public class PlayerControllerTest00 : MonoBehaviour
    {
        public float speed = 6.0F;
        public float jumpSpeed = 8.0F;
        public float gravity = 20.0F;
        private Vector3 moveDirection = Vector3.zero;
    
        void Update()
        {
            CharacterController controller = GetComponent<CharacterController>();
            if (controller.isGrounded)
            {
                moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
                moveDirection = transform.TransformDirection(moveDirection);
                moveDirection *= speed;
                if (Input.GetKeyDown(KeyCode.Space))
                    moveDirection.y = jumpSpeed;
            }
    
            moveDirection.y -= gravity * Time.deltaTime;
            controller.Move(moveDirection * Time.deltaTime);
        }
    }

    这里借用了某位老兄的代码:https://www.cnblogs.com/ChenZiRong1999/p/13395132.html

    这里产生了一个疑问,如果有知道的网友,给我留个评论:

    遇到一个玄学Bug,用角色控制器做了一个角色控制组件,采用两种方式:
    第一种:角色外层根用空物体然后挂上组件,动画模型物体作为子物体。
    第二种:动画模型物体直接为根物体,并且模型没有位移动画。
    移动代码charactorController.SimpleMove(verticalSpeed+horizonSpeed);
    发生的问题:第一种比第二种飘,也就是从一个物体边缘走出去落下的过程中第一种很飘,貌似垂直速度不符合效果。

    二.刚体驱动

    这里使用胶囊碰撞体加刚体组件的方式来实现,从而可以实现冲撞效果,缺点是需要大量的时间来调整,而且代码干涉物理效果,并且物理更新与渲染更新并不同步,因此角色的移动会相对看起来比较抖动,当然无论代码是放在FixedUpdate()还是Update()都和很难完全消除抖动,更多的是从相机动手,让相机的跟随抵消不同步抖动带来的视觉干扰。

    在刚体下有几种移动方式,具体如代码中所示。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 刚体角色控制器控制角色
    /// </summary>
    public class PlayerControllerTest01 : MonoBehaviour
    {
        Rigidbody rigid;
    
        public float moveSpeed;
        private Vector3 moveDirection = Vector3.zero;//角色的方向
        float moveScale = 0;
        private void Awake()
        {
            rigid = GetComponent<Rigidbody>();
        }
    
        private void Update()
        {
    
            //跳跃:为刚体施加一个向上的力:该力是由向上的跳跃速度和在刚体原速度方向上的一个速度合成的
            //VelocityChange是一个瞬时速度
            if (Input.GetKeyDown(KeyCode.Space)) {
                rigid.AddForce(transform.up * 20 /*+ rigid.velocity.normalized * directionalJumpFactor*/, ForceMode.VelocityChange);
            }
            
            moveScale = 0;
            if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S))
            {
                moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
                moveScale = 1;
            }
    
            //旋转,使用刚体的旋转
            Quaternion rot = Quaternion.Euler(0, Vector3.SignedAngle(Vector3.forward, moveDirection, Vector3.up), 0);//目标旋转
            Quaternion currentRot = Quaternion.RotateTowards(rigid.rotation, rot, Time.deltaTime * 600);//中间插值旋转
            rigid.MoveRotation(currentRot);
    
            //水平移动
            Vector3 v = Vector3.Project(rigid.velocity, transform.forward);
            float s = moveSpeed == 0 ? 0 : 1 - v.magnitude / moveSpeed;
            //rigid.AddForce(transform.forward * moveScale * s, ForceMode.VelocityChange);//第一种:力驱动,好处:比较真实具体移动交给物理系统;缺点:不好控制,容易滑动
            //rigid.velocity = transform.forward * 10 * moveScale + Vector3.up * rigid.velocity.y;//第二种:速度设置,好处:直接设置速度;缺点:直接干涉物理速度,抖动失真
            //if (moveScale == 1) rigid.MovePosition((rigid.position + transform.forward * moveSpeed * Time.deltaTime));//第三种:直接物理位置,好处:直接移动,缺点:目前描述不出来
        }
    
        private void FixedUpdate()
        {
            if (moveScale == 1) rigid.MovePosition((rigid.position + transform.forward * moveSpeed * Time.fixedDeltaTime));
        }
    }

     同样,参考某位老兄的代码:https://blog.csdn.net/qq_38327432/article/details/91561247

    二.动画驱动

    顾名思义,这里代码只是改变动画状态机的状态参数,移动动画自身带有位移,这样的好处就是动画效果和位移等效果完美契合,整个的动画都交由动画师来完成,缺点是整个过程的动画参数量大,至于动画遇到的问题,做的少,暂时不知道。代码demo,暂时没有资源,没有做

    写了半天必须配张图啊

  • 相关阅读:
    详解Javascript匿名函数的使用 转载自IT EYE Blog
    漂亮、免费和响应式HTML5网站模板 转
    Truth, Equality and JavaScript
    Ember.js 示例
    UX Pin 一款在线界面设计网站
    关于工资的三个秘密
    Semantic Versioning 如何进行版本管理
    CSSS CSS幻灯片
    oracle 导入数据报600错误
    Android 初步Android文件目录介绍
  • 原文地址:https://www.cnblogs.com/xiaoahui/p/13765561.html
Copyright © 2020-2023  润新知