Unity 按键输入封装&实现第一人称移动&相机移动

实现在Unity中重新封装按键输入

1.创建脚本Input.cs

    //自定义轴
    public class fps_InputAxis
    {
        public KeyCode positive;
        public KeyCode negative;
    }

    //自定义按键集合
    public Dictionary<string, KeyCode> buttons = new Dictionary<string, KeyCode>();
    //自定义轴集合
    public Dictionary<string, fps_InputAxis> axis = new Dictionary<string, fps_InputAxis>();
    //Unity轴集合
    public List<string> unityAxis = new List<string>();
1.1 初始化方法
    void Start(){
        SetupDefaults();  
    }
    
    private void SetupDefaults(string type = ""){
        //初始化按键
        if (type == "" || type == "button"){
            if (buttons.Count == 0){
                AddButton("File", KeyCode.Mouse0); //开火
                AddButton("Reload", KeyCode.R); //装弹
                AddButton("Jump", KeyCode.Space); //跳跃
                AddButton("Crouch", KeyCode.C); //蹲伏
                AddButton("Sprint", KeyCode.LeftShift); //冲刺
            }
        }
        //初始化自定义轴
        if (type == "" || type == "Axis"){
            if (axis.Count == 0){
                AddAxis("Horizontal", KeyCode.W, KeyCode.S);
                AddAxis("Vertical", KeyCode.A, KeyCode.D);
            }
        }
        //初始化unity轴
        if (type == "" || type == "UnityAxis"){
            if (unityAxis.Count == 0){
                AddUnityAxis("Mouse X");
                AddUnityAxis("Mouse Y");
                AddUnityAxis("Horizontal");
                AddUnityAxis("Vertical");
            }
        }
    }
1.2 添加按键、轴方法
    //添加按键
    private void AddButton(string n, KeyCode k){
        if (buttons.ContainsKey(n))
            buttons[n] = k;
        else
            buttons.Add(n, k);
    }
    //添加自定会轴
    private void AddAxis(string n, KeyCode pk, KeyCode nk){
        if (axis.ContainsKey(n))
            axis[n] = new fps_InputAxis() {positive = pk, negative = nk};
        else
            axis.Add(n, new fps_InputAxis() {positive = pk, negative = nk});
    }
    //添加unity轴
    private void AddUnityAxis(string n) {
        if (!unityAxis.Contains(n))
            unityAxis.Add(n);
    }
1.3 获取按键
    //外界获取按键的值—按下
    public bool GetButton(string button) {
            if (buttons.ContainsKey(button)){
                return Input.GetKey(buttons[button]);
            }
            return false;
        }
    //返回按键是否按下状态
    public bool GetButtonDown(string button) {
            if (buttons.ContainsKey(button)) {
                return Input.GetKeyDown(buttons[button]);
            }
            return false;
        }
     //获取轴(-1~1)float 类型
     public float GetAxis(string axis) {
            if(this.unityAxis.Contains(axis)){
                return Input.GetAxis(axis);
            }else
                return 0;
     }
     //获取轴,返回一个值,只有-1,0,1这三个值
     public float GetAxisRaw(string axis) {
            if(this.axis.ContainsKey(axis)) {
                float val = 0;
                if(Input.GetKey(this.axis[axis].positive)) {
                    return 1;
                }
                if(Input.GetKey(this.axis[axis].negative)) {
                    return -1;
                }
                return val;
            }else if(unityAxis.Contains(axis)){
                return Input.GetAxisRaw(axis);
            }
            else{
                return 0;
            }
     }

2. 增加参数控制’FPS_PlayerParameter.cs

[RequireComponent(typeof(CharacterController))]//添加特性
public class FPS_PlayerParameter : MonoBehaviour
{
    [HideInInspector] //隐藏属性
    public Vector2 inputSmootLook;//鼠标输入
    [HideInInspector] //隐藏属性
    public Vector2 inputMoveVerctor;//按键输入
    [HideInInspector] //隐藏属性
    public bool inputCtouch;//是否蹲伏
    [HideInInspector] //隐藏属性
    public bool inputJump;//是否跳跃
    [HideInInspector] //隐藏属性
    public bool inputSprint;//是否冲刺
    [HideInInspector] //隐藏属性
    public bool inputFire;//是否开火
    [HideInInspector] //隐藏属性
    public bool inputReload;//是否装弹
}

3. 按键输入

3.1 取消光标显示
public bool LookCursor
    {
        //如果是锁定状态就返回true 否则就返回false
        get { return Cursor.lockState == CursorLockMode.Locked ? true : false; }
        set
        {
            //光标不可见
            Cursor.visible = value;
            Cursor.lockState = value ? CursorLockMode.Locked : CursorLockMode.None;
        }
    }
3.2 输入和输入参数 的引用 实例化
    private FPS_PlayerParameter parameter;
    private FPS_Input input;

    private void Start()
    {
    	//开启取消光标
        LookCursor = true;
        parameter = this.GetComponent<FPS_PlayerParameter>();
        input = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<FPS_Input>();
    }

3.3 赋值
    private void Update()
    {
        InitialInput();
    }
    
    private void InitialInput(){
        parameter.inputMoveVerctor = new Vector2(input.GetAxis("Horizontal"),input.GetAxis("Vertical"));
        parameter.inputSmootLook = new Vector2(input.GetAxisRaw("Mouse X"), input.GetAxisRaw("Mouse Y"));
        parameter.inputCtouch = input.GetButton("Crouch");
        parameter.inputJump = input.GetButton("Jump");
        parameter.inputSprint = input.GetButton("Sprint");
        parameter.inputFire = input.GetButton("Fire");
        parameter.inputReload = input.GetButtonDown("Reload");
    }

4.第一人称相机旋转实现

4.1 设置默认参数
    public Vector2 mouseLockSensitivity = new Vector2(5, 5);//灵敏度
    public Vector2 rotaionXLimit = new Vector2(87, -87);//X轴转动范围
    public Vector2 rotaionYLimit = new Vector2(-360,360);//Y轴转动范围
    public Vector3 positionOffset = new Vector3(0, 2, 0.2f);//摄像机位置
    private Vector2 currentMouseLook = Vector2.zero;//当前的输入状态
    private float x_Angle = 0;//X轴默认位置
    private float y_Angle = 0;//Y轴默认位置
    private FPS_PlayerParameter parameter;//鼠标输入
    private Transform m_transform;
4.2 实例化
    void Start(){
        parameter = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<FPS_PlayerParameter>();
        m_transform = transform;
        m_transform.localPosition = positionOffset;
    }
4.3 计算相机旋转角度
    void Update() {
        UpdateInput();
    }
       void UpdateInput() {
        if (parameter.inputSmootLook == Vector2.zero)
            return;
        GetMouseLook();
        y_Angle += currentMouseLook.x;
        x_Angle += currentMouseLook.y;
        //y_Angle值范围判定
        y_Angle = y_Angle < -360 ? y_Angle += 360 : y_Angle;
        y_Angle = y_Angle > 360 ? y_Angle -= 360 : y_Angle;
        y_Angle = Mathf.Clamp(y_Angle, rotaionYLimit.x, rotaionYLimit.y);
        //x_Angle值范围判定
        x_Angle = x_Angle < -360 ? x_Angle += 360 : x_Angle;
        x_Angle = x_Angle > 360 ? x_Angle -= 360 : x_Angle;
        x_Angle = Mathf.Clamp(x_Angle, -rotaionXLimit.x, -rotaionXLimit.y);
    }
    private void GetMouseLook() {
        
        currentMouseLook.x = parameter.inputSmootLook.x;
        currentMouseLook.y = parameter.inputSmootLook.y;
        //添加灵敏度
        currentMouseLook.x *= mouseLockSensitivity.x;
        currentMouseLook.y *= mouseLockSensitivity.y;
        currentMouseLook.y *= -1;

    }
4.4 移动相机旋转角度
    void LateUpdate() {
        Quaternion xQuaternion = Quaternion.AngleAxis(y_Angle, Vector3.up);
        Quaternion yQuaternion = Quaternion.AngleAxis(0, Vector3.left);
        m_transform.parent.rotation = xQuaternion * yQuaternion;
        yQuaternion = Quaternion.AngleAxis(-x_Angle, Vector3.left);
        m_transform.rotation = xQuaternion * yQuaternion;
    }

5.第一人称移动实现

5.1 玩家移动状态定义
public enum PlayerState {//玩家状态
    None,//默认
    Idle,//站立
    Walk,//行走
    Crouch,//蹲伏
    Run,//跑
}
5.2 移动变量定义
    private PlayerState state = PlayerState.None;//玩家状态
        public PlayerState State {
        get {
            if (runing)
                state = PlayerState.Run; 
            else if (walking)
                state = PlayerState.Walk; 
            else if (creouching)
                state = PlayerState.Crouch; 
            else
                state = PlayerState.Idle;
            return state;
        }
    public float sprintSpeed = 10.0f;// 冲刺状态速度
    public float sprintJumpSpeed = 8.0f;//冲刺状态下跳跃速度
    public float normaltSpeed = 6.0f;//行走状态速度
    public float normalJumpSpeed = 7.0f;//行走状态下跳跃速度
    public float crouchSpeed = 2.0f;//蹲伏状态速度
    public float crouchJumpSpeed = 5.0f;//蹲伏状态下跳跃速度
    public float crouchDeletHeight = 0.5f;//蹲伏状态下下降的高度
    public float cameraMoveSpeed = 8.0f;// 蹲伏时相机速度
    public float gravity = 20.0f;//重力
    public AudioClip JumpAudio;//跳跃音效

    private float speed;//玩家当前速度
    private float jumpSpeed;//玩家当前跳跃速度
    private Transform mainTransform;
    private float standardCamHeight;//正常状态相机高度
    private float crouchingCamHeight;//蹲伏状态相机高度
    private bool grounded = false;//玩家是否在地面
    private bool walking = false;//玩家是否在行走
    private bool creouching = false;//玩家是否在蹲伏
    private bool stopCreouching = false;//玩家是否停止蹲伏
    private bool runing = false;//玩家是否在跑
    private Vector3 normalControllerCenter = Vector3.zero;
    private float normalControllerHeight = 0.0f;
    private float rimer = 0;
    private CharacterController controller;
    private AudioSource audioSource;
    private FPS_PlayerParameter parameter;
    private Vector3 moveDirection = Vector3.zero;
5.3 初始化
private void Start() {
        crouching = false;
        walking = false;
        runing = false;
        speed = normaltSpeed;
        jumpSpeed = normalJumpSpeed;
        mainCamera = GameObject.FindGameObjectWithTag(Tags.mainCamera).transform;
        standardCamHeight = mainCamera.localPosition.y;
        crouchingCamHeight = standardCamHeight - crouchDeletHeight;
        audioSource = GetComponent<AudioSource>();
        controller = GetComponent<CharacterController>();
        parameter = GetComponent<FPS_PlayerParameter>();
        normalControllerCenter = controller.center;
        normalControllerHeight = controller.height;
    }

5.4 移动方法
//移动
    private void UpdateMove() {
        if (grounded) {
            moveDirection = new Vector3(parameter.inputMoveVerctor.x, 0, parameter.inputMoveVerctor.y);
            moveDirection = transform.TransformDirection(moveDirection);
            moveDirection *= speed;

            if (parameter.inputJump) {
                moveDirection.y = jumpSpeed;
                AudioSource.PlayClipAtPoint(JumpAudio,transform.position);
                CurrentSpeed();
            }
        }

        moveDirection.y -= gravity * Time.deltaTime;
        CollisionFlags flags = controller.Move(moveDirection * Time.deltaTime);
        grounded = (flags&CollisionFlags.CollidedBelow)!=0;
        if (Mathf.Abs(moveDirection.x)>0&&grounded||Mathf.Abs(moveDirection.z)>0&&grounded) {
            if (parameter.inputSprint) {
                walking = false;
                runing = true;
                crouching = false;
            }else if (parameter.inputCtouch) {
                crouching = true;
                walking = false;
                runing = false;
            }
            else {
                walking = true;
                runing = false;
                crouching = false;
            }
        }
        else {
            if (walking) 
                walking = false;
            if (runing) 
                runing = false;
            if (parameter.inputCtouch)
                crouching = true;
            else
                crouching = false;
        }

        if (crouching) {
            controller.height = normalControllerHeight - crouchDeletHeight;
            controller.center = normalControllerCenter - new Vector3(0, crouchDeletHeight /2 ,0 );
        }
        else {
            controller.height = normalControllerHeight;
            controller.center = normalControllerCenter;
        }
        UpdateCrouch();
        CurrentSpeed();
    }
5.5 根据当前状态修改移动速度
//修改当前速度
    private void CurrentSpeed() {
        switch (State) {
            case PlayerState.Idle:
                speed = normaltSpeed;
                jumpSpeed = normalJumpSpeed;
                break;
            case PlayerState.Walk:
                speed = normaltSpeed;
                jumpSpeed = normalJumpSpeed;
                break;
            case PlayerState.Crouch:
                speed = crouchSpeed;
                jumpSpeed = crouchJumpSpeed;
                break;
            case PlayerState.Run:
                speed = sprintSpeed;
                jumpSpeed = sprintJumpSpeed;
                break;
        }
    }
5.6 移动时声音播放
//移动声音播放
    private void AudioManagement() {
        if (State == PlayerState.Walk) {
            audioSource.pitch = 1.0f;
            if (!audioSource.isPlaying) {
                audioSource.Play();
            }
        }else if (State == PlayerState.Run) {
            audioSource.pitch = 1.3f;
            if (!audioSource.isPlaying) {
                audioSource.Play();
            }
        }else {
            audioSource.Stop();
        }
    }
5.7 根据蹲伏状态修改视角高度
   //更新蹲伏是视角高度
    private void UpdateCrouch() {
        if (crouching) {
            if (mainCamera.localPosition.y>crouchingCamHeight) {
                if (mainCamera.localPosition.y- (crouchDeletHeight * Time.deltaTime * cameraMoveSpeed) <crouchingCamHeight) {
                    mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, crouchingCamHeight, mainCamera.localPosition.z);
                }else {
                    mainCamera.localPosition -= new Vector3(0, crouchDeletHeight * Time.deltaTime, 0);
                }
            }else {
                mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, crouchingCamHeight, mainCamera.localPosition.z);
            }
        } else {
            if (mainCamera.localPosition.y<standardCamHeight) {
                if (mainCamera.localPosition.y+ (crouchDeletHeight * Time.deltaTime * cameraMoveSpeed) >standardCamHeight) {
                    mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, standardCamHeight, mainCamera.localPosition.z);
                }else {
                    mainCamera.localPosition += new Vector3(0, crouchDeletHeight * Time.deltaTime * cameraMoveSpeed, 0);
                }
            }else {
                mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, standardCamHeight, mainCamera.localPosition.z);
            }
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值