此种方案在第一篇基础之上做了该进,手感有大的改善(仅供参考)

本篇代码:手写摇杆+CharacterController移动,如果想要input移动将ve替换即可

moveDirect = new Vector3(ve.x,0,ve.y);
//换成
moveDirect =new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

利用组件:CharacterController

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class JoyTouchz : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler
{
    private Image backImage, joyImage;
    private Vector2 star,ve;
    public GameObject Cube;
    private CharacterController Ym;
    private bool pass = false;
    private Vector3 moveDirect=Vector3.zero;
    public float Speed;
    void Start()
    {
        backImage = GetComponent<Image>();
        joyImage = transform.GetChild(0).GetComponent<Image>();
        if (Cube!=null)
        {
            Ym=Cube.GetComponent<CharacterController>();
            if (Ym==null)
            {
                Ym=Cube.AddComponent<CharacterController>();
            }
        }
    }

    
    void Update()
    {
        if (pass&&Ym.isGrounded)
        {
            moveDirect = new Vector3(ve.x,0,ve.y);/
            moveDirect = Cube.transform.TransformDirection(moveDirect);
            moveDirect *= Speed;
            
        }

        moveDirect.y -= 20f * Time.deltaTime;
        Ym.Move(moveDirect*Time.deltaTime);
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        star = joyImage.transform.position;
        pass = true;
    }

    public void OnDrag(PointerEventData eventData)
    {
        joyImage.transform.position = Input.mousePosition;
        ve = eventData.position - star;
        joyImage.transform.localPosition = Vector2.ClampMagnitude(ve, 100f);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        pass = false;
        joyImage.transform.localPosition = Vector2.zero;
    }
}

========================================================================= 

以下为官方示例:(看啥不如看官方文档系列)

CharacterController.Move

声明

public CollisionFlags Move(Vector3 motion);

描述

使用附加的 CharacterController 组件提供 GameObject 的移动。

CharacterController.Move动作在给定方向上移动游戏对象。给定方向需要绝对运动增量值。碰撞会限制Move的发生。返回值CollisionFlags指示碰撞的方向:None、Sides、Above 和 Below。CharacterController.Move不使用重力。 下面的示例演示了如何使用 CharacterContoller.Move。Update导致Move重新定位玩家。此外,Jump改变玩家在垂直方向的位置。

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

public class Example : MonoBehaviour
{
    private CharacterController controller;
    private Vector3 playerVelocity;
    private bool groundedPlayer;
    private float playerSpeed = 2.0f;
    private float jumpHeight = 1.0f;
    private float gravityValue = -9.81f;

    private void Start()
    {
        controller = gameObject.AddComponent<CharacterController>();//添加组件
    }

    void Update()
    {
        groundedPlayer = controller.isGrounded;//判断是否在地面上
        if (groundedPlayer && playerVelocity.y < 0)//设置y为0,高度为0
        {
            playerVelocity.y = 0f;
        }

        Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));//获取移动输入数值
        controller.Move(move * Time.deltaTime * playerSpeed);//进行移动
        //判断是此时是否进行移动
        if (move != Vector3.zero)
        {
            //进行则移动(节约性能)
            gameObject.transform.forward = move;
        }

        // 改变玩家的高度位置
        if (Input.GetButtonDown("Jump") && groundedPlayer)
        {
            playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
        }
        
        //数值模拟重力
        //因为此组件会与rigebody组件发生冲突,两个只能用一个
        playerVelocity.y += gravityValue * Time.deltaTime;
        //进行移动(因为模拟的重力是实时的)
        controller.Move(playerVelocity * Time.deltaTime);
    }
}

----itps:测试了以下,跳跃的手感表现的不太好:

建议将:

if (Input.GetButtonDown("Jump") && groundedPlayer)
        {
            playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
        }

替换为:

if (Input.GetKeyDown(KeyCode.Space))
        {
            playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
        }

经测试后手感良好


------------------------------------------------------------------------------------------------------------

ok,续章,fixupdate用来进行移动操作,必然会出现卡顿,之所以要用是为了照顾网络同步,要稳定发包收包。它以固定的帧率数进行调用,0.02秒一次,差不多一秒钟50次调用,如果您不是网络游戏,且游戏项目规模可以的考量下,建议使用Update,以给玩家带来更好的操作体验,当然如果您所使用的物理系统较多的情况下还是要考虑FixUpdate,因为这时候使用Update可能会导致物理系统出现问题,FixUpdate操控负载不宜过大,否则可能会出现更为过分的情况。

Fixupdate的调用次数可进行人工设置,建议您要根据您的项目对此函数进行设置,以确保给用户带来良好的体验。