第一部分:人物移动(2)

        使用unity新输入系统实现人物的行走,奔跑,跳跃功能

unity Input System:

        通过创建Input Actions,同时添加按键的绑定实现输入。

Input Actions:

        使用到的Action Type 有Button 和 Value 两种类型:

Button:只关心输入的按键是否发生         Jump Run 等按键输入使用了Button

Value:会同时获取输入具体的值是多少,WASD的输入使用了Value

        按键的交互方式 Interactions Type:

Press:按键被按下时即触发                        Release:当按键被释放时触发

Tap:当快速点击一个按钮时触发                SlowTap:按钮被持续按住一段时间后松开才能触发

Hold:按钮被持续按住一段时候后触发

        一些参数:PressPoint(确定被按下的压力阈值) Duration,holdTime(持续时间,tap,hold,slowtap均有此参数,代表不同的具体含义)

        按键的3中状态(开始,完成,取消) 不同交互方法具体变化时间不同

started:按键被按下时    performed:按键操作完成时     canceled:按键取消时

例如:

1:Press方式 的started在按键被正确(力度超过阈值)按下时,performed就在started的下一帧执行,cancel在按键抬起时。

2:Hold方式 的started在按键被正确(力度超过阈值)按下时,performed在持续按住HoldTime时间后执行,cancel在按键抬起时。

…………

Walk,Run按键使用了Hold的方式(Walk和Run以实现短暂的延迟效果(方便移动前的转向))

InputSystem的具体使用方法:

        方法一:挂在PlayerInput,同时使用事件的方式进行拖拽赋值。

        方法二:创建具体的 InputActions,并且 生成它的C#代码,在要使用的类(PlayerController)awake中new出来一个创建好的InputActions(注意要在Enable中启动,在Disable中关闭),然后利用 每个按键对应的 started,performed,canceled 注册相应的函数即可。

具体实现:

        PlayerController实现:(代码在后续进行了大幅调整,包含了许多未提及功能,以下是更新后的代码,可能与本章描述有些许出路)

要点:

1:设置bool值判断状态(isWalk(是否处于行走状态(包括跑步)),isRun(是否按着奔跑键),JumpButton(是否按着跳跃键))

2:Move和Run按钮的 Perfomred 注册开始函数,而Jump按钮的 started注册 开始函数

3:通过属性器,在修改状态的同时改变 动画控制器参数

4:Run 和 Jump 按钮的触发只代表状态的改变,不一定真的开始奔跑或跳跃(以优化一直按着Run或Jump键的情况)

5:使用协程和Lerp函数动态改变Player的速度,更加平滑

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

//玩家的控制脚本
public class PlayerController : MonoBehaviour
{
    [Header("引用")]
    [SerializeField] private Transform faceDirection;
    [SerializeField]private ThirdLockEnemyCamera thirdLockEnemyCamera;

    private PlayerInputController inputActions;

    [HideInInspector]public CharacterController characterController;
    [HideInInspector]public PlayerCharacterStats playerCurrentStats;

    private Animator anim;

    private PlayerAnimationController playerAnimationInf;

    private int animatorCombatLayer;

    //public FirstPersonCamera firstPersonCamera;

    [Header("基本属性")]
    [SerializeField]private float curSpeed;

    [SerializeField, Header("行走速度")]              private float walkSpeed = 3;          

    [SerializeField, Header("奔跑速度")]              private float runSpeed = 5;   
    

    [SerializeField, Header("奔跑消耗精力速度速度")]    private float runCostEnergy = 1;     

    [SerializeField, Header("翻滚速度")]              private float rollSpeed = 20;     

    [SerializeField, Header("翻滚消耗的精力值")]        private float rollCost = 10;          

    [SerializeField, Header("人物旋转角度速度")]        private float rotationSpeed = 5;      

    [SerializeField, Header("重力加速度")]             private float gravity = -9.8f;        

    [SerializeField, Header("跳跃高度")]               private float jumpHeight = 10f;      

    private Vector3 velocityByGravity;            //重力所产生的向下的速度

    private Vector2 inputDirection;               //WASD按键的输入信息

    private Vector3 moveDirection;                //人物移动的方向信息

    private PhysicalCheck physicalCheck;

    private bool isLoading;


    private bool isLock;

    private bool jumpButton;
    
        
    private static readonly int IsLightSword = Animator.StringToHash("IsLightSword");
    private static readonly int IsGreatSword = Animator.StringToHash("IsGreatSword");
    private static readonly int RAttackHold = Animator.StringToHash("RAttack Hold");
    private static readonly int Jump = Animator.StringToHash("Jump");
    private static readonly int Execution = Animator.StringToHash("Execution");
    private static readonly int LAttack = Animator.StringToHash("LAttack");
    private static readonly int ChangeWeapon = Animator.StringToHash("Change Weapon");

    private EnemyController curLockedEnemy;
    public bool IsLock
    {
        get;set;
    }

    private PlayerWeaponType currentWeaponType = PlayerWeaponType.LightSword;
    private PlayerWeaponType CurrentWeaponType
    {
        get => currentWeaponType;
        set
        {
            switch (currentWeaponType)
            {
                case PlayerWeaponType.LightSword:
                    anim.SetBool(IsLightSword, false);
                    break;
                case PlayerWeaponType.GreatSword:
                    anim.SetBool(IsGreatSword, false);
                    break;
            }

            currentWeaponType = value;
            switch (currentWeaponType)
            {
                case PlayerWeaponType.LightSword:
                    anim.SetBool(IsLightSword, true);
                    break;
                case PlayerWeaponType.GreatSword:
                    anim.SetBool(IsGreatSword, true);
                    break;
            }
        }
    }
    
    
    //是否允许攻击的输入
    private bool applyAttackInput;
    public bool ApplyAttackInput { get => applyAttackInput; set => applyAttackInput = value; }

    //是否允许格挡
    public bool CanParry { get => !playerAnimationInf.IsAttack; }
    

    private void Awake()
    {
        inputActions = new PlayerInputController();
        characterController = GetComponent<CharacterController>();
        physicalCheck = GetComponent<PhysicalCheck>();
        playerCurrentStats = GetComponent<PlayerCharacterStats>();
        playerAnimationInf = GetComponent<PlayerAnimationController>();
        anim = GetComponent<Animator>();
       
    }

    private void Start()
    {
        velocityByGravity = Vector2.zero;
        currentWeaponType = PlayerWeaponType.LightSword;
        applyAttackInput = true;
        animatorCombatLayer = anim.GetLayerIndex("Combat Layer");
        
        
        //人物翻滚 Release Only
        inputActions.GamePlay.Roll.performed += StartRoll;

        //人物行走 Hold
        inputActions.GamePlay.Move.performed += StartWalk;
        inputActions.GamePlay.Move.canceled += CancelWalk;

        //人物奔跑 Hold
        inputActions.GamePlay.Run.performed += StartRun;
        inputActions.GamePlay.Run.canceled += CancelRun;

        //人物跳跃 Press
        inputActions.GamePlay.Jump.started += StartJump;
        inputActions.GamePlay.Jump.canceled += CancelJump;

        //人物左键攻击 Press
        inputActions.GamePlay.LAttack.started += StartLAttack;

        inputActions.GamePlay.RAttack.started += StartFocusAttack;
        inputActions.GamePlay.RAttack.canceled += StopFocusAttack;

        //人物格挡
        inputActions.GamePlay.Parry.started += StartParry;
        inputActions.GamePlay.Parry.canceled += StopParry;
        //锁定敌人 Press
        inputActions.GamePlay.LockEnemy.started += SwitchLockState;

        //切换武器
        inputActions.GamePlay.ChangeWeapon.started += SwitchWeapon;
        
    }

    private void OnEnable()
    {
        inputActions.Enable();
        GlobalEvent.switchToFirstPersonEvent += OnSwitchToFirstPerson;
        GlobalEvent.enemyDeathEvent += OnEnemyDeath;
        GlobalEvent.afterSceneLoadEvent += OnAfterSceneLoad;
        GlobalEvent.beforeSceneLoadEvent += OnBeforeSceneLoad;
        GlobalEvent.stopTheWorldEvent += StopTheGame;
        GlobalEvent.continueTheWorldEvent += ContinueTheGame;
        GlobalEvent.onEnterDialogue += DisablePlayerGamePlayInput;
        GlobalEvent.onExitDialogue += EnablePlayerGamePlayInput;

    }
    
    private void OnDisable()
    {
        inputActions.Disable();
        GlobalEvent.switchToFirstPersonEvent -= OnSwitchToFirstPerson;
        GlobalEvent.enemyDeathEvent -= OnEnemyDeath;
        GlobalEvent.afterSceneLoadEvent -= OnAfterSceneLoad;
        GlobalEvent.beforeSceneLoadEvent -= OnBeforeSceneLoad;
        GlobalEvent.stopTheWorldEvent -= StopTheGame;
        GlobalEvent.continueTheWorldEvent -= ContinueTheGame;
        GlobalEvent.onEnterDialogue -= DisablePlayerGamePlayInput;
        GlobalEvent.onExitDialogue -= EnablePlayerGamePlayInput;
    }

    #region  全局事件函数
    //切换到第一视角:调整faceDirection为人物的朝向
    private void OnSwitchToFirstPerson()
    {
        IsLock = false;
        faceDirection.forward = transform.forward;
    }
    
    private void OnAfterSceneLoad(Vector3 pos)
    {
        inputActions.Enable();
        transform.position = pos;
        Invoke(nameof(SetIsLoadingFalse), 0.02f);
    }

    private void SetIsLoadingFalse() => isLoading = false;

    private void OnBeforeSceneLoad()
    {
        InitPlayer();
        isLoading = true;
        inputActions.Disable();
        
    }

    private void StopTheGame()
    {
        inputActions.GamePlay.Jump.Disable();
        inputActions.GamePlay.LAttack.Disable();
        inputActions.GamePlay.RAttack.Disable();
        inputActions.GamePlay.Roll.Disable();
        inputActions.GamePlay.Parry.Disable();
    }

    private void ContinueTheGame()
    {
        inputActions.GamePlay.Jump.Enable();
        inputActions.GamePlay.LAttack.Enable();
        inputActions.GamePlay.RAttack.Enable();
        inputActions.GamePlay.Roll.Enable();
        inputActions.GamePlay.Parry.Enable();
    }

    private void DisablePlayerGamePlayInput()
    {
        InitPlayer();
        inputActions.GamePlay.Disable();
    }
    
    private void EnablePlayerGamePlayInput()
    {
        playerAnimationInf.IsGuard = false;
        inputActions.GamePlay.Enable();
    }

    //重置Player的所有状态
    private void InitPlayer()
    {
        playerAnimationInf.IsWalk = false;
        playerAnimationInf.IsRun = false;
        anim.SetBool(RAttackHold, false);
        inputActions.GamePlay.Move.Dispose();
        inputActions.GamePlay.Run.Dispose();
        inputActions.GamePlay.RAttack.Dispose();
    }
    

    #endregion



    private void Update()
    { 
        inputDirection = inputActions.GamePlay.Move.ReadValue<Vector2>();
        if(!isLoading)MovePlayer();
        if(!isLoading)Gravitation();
        if (jumpButton&&physicalCheck.IsOnGround&&!playerAnimationInf.IsRoll&&!playerAnimationInf.IsAttack&& playerAnimationInf.landAnimationOver) StartJump(); 
        StatsCheckAndCost();
    }

    private void MovePlayer()
    {
        //如果正在翻滚或者正在攻击 则返回
        if (!playerAnimationInf.rollAnimationOver ||playerAnimationInf.IsAttack) return;
        //如果正在处于受伤状态 也返回
        if (playerAnimationInf.IsHurt) return;
        if (CameraManager.Instance.currentCameraStyle == CameraStyle.FirstPerson)
        {
            RotatePlayerInFirstPerson();
            MovePlayerInFirstPerson();
        }
        else
        {
            RotatePlayerInThirdPerson();
            MovePlayerInThirdPerson();
        }
    }

    private void StatsCheckAndCost()
    {
        //人物正在奔跑:消耗体力
        if (playerAnimationInf.IsWalk && playerAnimationInf.IsRun) playerCurrentStats.ExpendEnergy(Time.deltaTime * runCostEnergy);
        //体力太少:停止奔跑状态 
        if (playerAnimationInf.IsRun && playerCurrentStats.CurEnergy < 3f) playerAnimationInf.IsRun = false;
    }

    #region 人物的旋转和移动(第三人称和第一人称)

    //第三人称方式移动人物
    private void MovePlayerInThirdPerson()
    {
        if (IsLock) MovePlayerInThirdPersonLock();
        else MovePlayerInThirdPersonFree();
        
    }

    //第三人称 自由视角 移动人物
    private void MovePlayerInThirdPersonFree()
    {
        if (playerAnimationInf.IsWalk == false) return;
        //人物的实际移动:始终朝着面朝的方向进行移动
        if (physicalCheck.HaveBarrierInMoveDirection(transform.position + transform.up * 0.5f, transform.forward, moveDirection.normalized.magnitude * curSpeed * Time.deltaTime * 2)) return;
        characterController.Move(transform.forward.normalized * curSpeed * Time.deltaTime);
    }

    //第三人称 锁定视角 移动人物
    private void MovePlayerInThirdPersonLock()
    {
        if (playerAnimationInf.IsWalk == false) return;
        //人物的实际移动:同时根据人物的朝向 和 人物的WASD输入
        moveDirection = transform.forward * inputDirection.y + transform.right * inputDirection.x;
        moveDirection.y = 0;
        if (physicalCheck.HaveBarrierInMoveDirection(transform.position + transform.up * 0.5f, moveDirection, moveDirection.normalized.magnitude * curSpeed * Time.deltaTime * 2)) return;
        characterController.Move(moveDirection.normalized * curSpeed * Time.deltaTime);
    }

    //第三人称方式旋转人物
    private void RotatePlayerInThirdPerson()
    {
        if (IsLock) RotatePlayerInThirdPersonLockEnemy();
        else RotatePlayerInThirdPersonFree();
    }

    //第三人称 自由视角方式的旋转
    private void RotatePlayerInThirdPersonFree()
    {
        moveDirection = faceDirection.forward * inputDirection.y + faceDirection.right * inputDirection.x;
        if(moveDirection!=Vector3.zero)
        {
            transform.forward = Vector3.Slerp(transform.forward, moveDirection, rotationSpeed * Time.deltaTime);
        }
    }

    //第三人称 锁定视角方式的旋转
    private void RotatePlayerInThirdPersonLockEnemy()
    {
        //人物的forward永远是敌人,人物的目标面向:敌人坐标 - 自己坐标
        moveDirection = new Vector3(curLockedEnemy.transform.position.x - transform.position.x,transform.forward.y, curLockedEnemy.transform.position.z - transform.position.z);
        transform.forward = Vector3.Slerp(transform.forward, moveDirection, rotationSpeed * Time.deltaTime);
    }

    //第一人称方式移动人物
    private void MovePlayerInFirstPerson()
    {
        //如果移动方向有阻碍物:障碍,敌人等 返回
        if (playerAnimationInf.IsWalk == false) return;
        moveDirection = faceDirection.forward * inputDirection.y + faceDirection.right * inputDirection.x;
        if (physicalCheck.HaveBarrierInMoveDirection(transform.position + transform.up * 0.5f, moveDirection, moveDirection.normalized.magnitude * curSpeed * Time.deltaTime * 2)) return;
        characterController.Move(moveDirection.normalized * curSpeed * Time.deltaTime);
    }

    //第一人称方式旋转人物
    private void RotatePlayerInFirstPerson()
    {
        transform.forward = faceDirection.forward;
    }

    private void Gravitation()
    {
        //考虑重力
        if (physicalCheck.IsOnGround && velocityByGravity.y < 0) velocityByGravity.y = 0;
        else velocityByGravity.y += gravity * Time.deltaTime;
        characterController.Move(velocityByGravity * Time.deltaTime);
    }

    private void StartJump()
    {
        anim.SetTrigger(Jump);
        playerAnimationInf.landAnimationOver = false;
        velocityByGravity.y = Mathf.Sqrt(-2 * gravity * jumpHeight);
    }

    #endregion

    #region 人物按键控制
    //开始行走
    private void StartWalk(InputAction.CallbackContext obj)
    {
        playerAnimationInf.IsWalk = true;
        if(!playerAnimationInf.IsRoll &&!playerAnimationInf.IsAttack)StopAllCoroutines();
        float targetSpeed = playerAnimationInf.IsRun ? runSpeed : walkSpeed;
        StartCoroutine(ChangeToTargetSpeed(targetSpeed, 0.3f));
    }
    //结束行走
    private void CancelWalk(InputAction.CallbackContext obj)
    {
        playerAnimationInf.IsWalk = false;
        if (!playerAnimationInf.IsRoll && !playerAnimationInf.IsAttack) StopAllCoroutines();
        StartCoroutine(ChangeToTargetSpeed(0, 0.1f));
    }
    //开始跑步
    private void StartRun(InputAction.CallbackContext obj)
    {
        playerAnimationInf.IsRun = true;
        if (!playerAnimationInf.IsWalk || playerAnimationInf.IsGuard) return;
        if (!playerAnimationInf.IsRoll && !playerAnimationInf.IsAttack) StopAllCoroutines();
        StartCoroutine(ChangeToTargetSpeed(runSpeed, 0.3f));
    }
    //结束跑步
    private void CancelRun(InputAction.CallbackContext obj)
    {
        //延迟调用? (由于Roll和Run是同一个按键的不同交互导致的,确保松开Shift后不会翻滚)
        Invoke(nameof(CancelRun), 0f);
    }
    private void CancelRun()
    {
        playerAnimationInf.IsRun = false;
        if (!playerAnimationInf.IsRoll) StopAllCoroutines();
        float targetSpeed = playerAnimationInf.IsWalk ? walkSpeed : 0;
        StartCoroutine(ChangeToTargetSpeed(targetSpeed, 0.2f));
    }
    //开始跳跃
    private void StartJump(InputAction.CallbackContext obj)
    {
        jumpButton = true;
    }
    //结束跳跃
    private void CancelJump(InputAction.CallbackContext obj)
    {
        jumpButton = false;
    }
    //开始翻滚
    private bool CanRoll()
    {
        return physicalCheck.IsOnGround && playerCurrentStats.CurEnergy >= rollCost && !playerAnimationInf.IsRoll && !playerAnimationInf.IsRun && playerAnimationInf.rollAnimationOver && !playerAnimationInf.IsFocusAttack && !playerAnimationInf.IsChangeWeapon;
    }
    private void StartRoll(InputAction.CallbackContext obj)
    {
        //如果人物在地面上并且人物的能量足够 才进行翻滚
        if (CanRoll())     
        {
            //消耗能量 变更为无敌状态
            StopAllCoroutines();playerAnimationInf.StopAllCoroutines();
            playerCurrentStats.ExpendEnergy(rollCost);
            playerCurrentStats.InvincibleWhenRoll = true;
            playerAnimationInf.IsRoll = true;
            playerAnimationInf.rollAnimationOver = false;
            //StartCoroutine(RollForward());  //转变为由动画控制移动
        }
    }
    //开始普通攻击
    private void StartLAttack(InputAction.CallbackContext obj)
    {
        if (!playerAnimationInf.IsAttack)
            ApplyAttackInput = true;
        if (!ApplyAttackInput || playerAnimationInf.IsRoll||playerAnimationInf.IsGuard) return;
        ApplyAttackInput = false;
        //判定是否能够对于处于虚弱状态的敌人进行处决
        EnemyController weakEnemy = SelectWeakEnemy();
        if (weakEnemy!= null) 
        {
            //执行实际的处决
            Vector3 toDirection = new Vector3(weakEnemy.transform.position.x - transform.position.x, transform.forward.y, weakEnemy.transform.position.z - transform.position.z);
            StartCoroutine(RotateForwardWithSpeed(toDirection, 5));
            weakEnemy.IsExecuted = true;
            GlobalEvent.CallEnemyExitWeakState(weakEnemy);
            anim.SetTrigger(Execution);
        }
        else
        {
            //正常进行普通攻击
            if (curLockedEnemy != null)
            {
                Vector3 toDirection = new Vector3(curLockedEnemy.transform.position.x - transform.position.x, transform.forward.y, curLockedEnemy.transform.position.z - transform.position.z);
                StartCoroutine(RotateForwardWithSpeed(toDirection, 5));
            }
            anim.SetTrigger(LAttack);
        }
    }

    //开始蓄力攻击
    private void StartFocusAttack(InputAction.CallbackContext obj)
    {
        if (playerAnimationInf.IsAttack) return;
        if (playerAnimationInf.IsRoll||playerAnimationInf.IsGuard) return;
        ApplyAttackInput = false;
        if (curLockedEnemy != null)
        {
            Vector3 toDirection = new Vector3(curLockedEnemy.transform.position.x - transform.position.x, transform.forward.y, curLockedEnemy.transform.position.z - transform.position.z);
            StartCoroutine(RotateForwardWithSpeed(toDirection, 5));
        }
        anim.SetBool(RAttackHold, true);
    }

    private void StopFocusAttack(InputAction.CallbackContext obj)
    {
        anim.SetBool(RAttackHold, false);
    }

    //第三人称切换锁定状态
    private void SwitchLockState(InputAction.CallbackContext obj)
    {
        if (CameraManager.Instance.currentCameraStyle == CameraStyle.FirstPerson) return;
        IsLock = !IsLock;
        if (IsLock)
        {
            //选择一个敌人进行锁定
            //curLockedEnemy = SelectLockEnemyByMousePos();
            curLockedEnemy = SelectLockEnemy();
            if (curLockedEnemy != null)
            {
                CameraManager.Instance.SwitchToThirdPersonLockEnemy(curLockedEnemy);
                GlobalEvent.CallEnterFocusOnEnemy(curLockedEnemy);
            }
            else IsLock = false;
        }
        else
        {
            curLockedEnemy = null;
            //取消聚焦点  相机转换
            GlobalEvent.CallExitFocusOnEnemy();
            CameraManager.Instance.SwitchCameraStyle(CameraStyle.ThirdPersonNormal);
        }
    }

    private void SwitchWeapon(InputAction.CallbackContext obj)
    {
        if (playerAnimationInf.IsRoll || playerAnimationInf.IsAttack) return;
        //curSpeed = 0;
        switch (currentWeaponType)
        {
            case PlayerWeaponType.LightSword:
                CurrentWeaponType = PlayerWeaponType.GreatSword;
                break;
            case PlayerWeaponType.GreatSword:
                CurrentWeaponType = PlayerWeaponType.LightSword;
                break;
        }
        anim.SetTrigger(ChangeWeapon);
    }

    //进行格挡
    private void StartParry(InputAction.CallbackContext obj)
    {
        if (CanParry) 
        {
            playerAnimationInf.IsGuard = true;
            CancelRun();
        }
    }

    //取消格挡
    private void StopParry(InputAction.CallbackContext obj)
    {
        playerAnimationInf.IsGuard = false;
    }


    #endregion

    //选择锁定的敌人(根据鼠标锁定)
    private EnemyController SelectLockEnemy()
    {
       //return SelectEnemyCloseToPlayer(GameManager.Instance.enemies, float.MaxValue, Mathf.Acos(0f));;
       return SelectEnemyCloseToMouse(GameManager.Instance.enemies, float.MaxValue, Mathf.Acos(0f));
    }

    
    //综合判断是否有敌人可以被处决 (根据人物当前方向处决)
    private EnemyController SelectWeakEnemy()
    {
        return SelectEnemyCloseToPlayer(GameManager.Instance.weakEnemies, 4f, Mathf.Acos(0.35f));
    }

    //在指定的集合中根据当前人物的朝向选择一个敌人
    private EnemyController SelectEnemyCloseToPlayer(HashSet<EnemyController> enemies, float minDistance,float facing)
    {
        //具体要求:距离小于某个值 + 角度为人物的前方   (根据角度选择最佳的目标) 
        EnemyController currentEnemy = null;
        float minAngle = facing / Mathf.PI * 180;
        foreach (var enemy in enemies)
        {
            if (Vector3.Distance(transform.position, enemy.transform.position) < minDistance)
            {
                //enemy满足要求 比较得到更好的敌人
                Vector3 targetPos = enemy.transform.position - transform.position;
                float curAngle = Vector3.Angle(transform.forward, targetPos);
                if (curAngle < minAngle)
                {
                    minAngle = curAngle;
                    currentEnemy = enemy;
                }
            }
        }
        return currentEnemy;
    }

    private EnemyController SelectEnemyCloseToMouse(HashSet<EnemyController> enemies, float minDistance, float facing)
    {
        //具体要求:距离小于某个值 + 角度为人物的前方   (根据角度选择最佳的目标) 
        EnemyController currentEnemy = null;
        //Vector3 screenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Vector3.Distance(Camera.main.transform.position, transform.position));
        //Vector3 startPos = Camera.main.ScreenToWorldPoint(screenPoint);
        Transform startTransform = Camera.main.transform;
        float minAngle = facing / Mathf.PI * 180;
        foreach (var enemy in enemies)
        {
            if (Vector3.Distance(transform.position, enemy.transform.position) < minDistance)
            {
                //enemy满足要求 比较得到更好的敌人
                Vector3 targetPos = enemy.transform.position - startTransform.position;
                float curAngle = Vector3.Angle(startTransform.forward, targetPos);
                if (curAngle < minAngle)
                {
                    minAngle = curAngle;
                    currentEnemy = enemy;
                }
            }
        }
        return currentEnemy;
    }


    #region 协程
    //使用Lerp实现加速和减速协程
    IEnumerator ChangeToTargetSpeed(float targetSpeed,float needTime)
    {
        float time = 0;
        while(time<needTime)
        {
            curSpeed = Mathf.Lerp(curSpeed, targetSpeed, time / needTime);
            time += Time.deltaTime;
            yield return null;
        }
        curSpeed = targetSpeed;
    }
    
    //向前翻滚的协程
    IEnumerator RollForward()
    {
        while(playerAnimationInf.IsRoll)
        {
            characterController.Move(transform.forward.normalized * rollSpeed * Time.deltaTime);
            yield return null;
        }
    }

    /// <summary>
    /// 旋转人物面朝的方向
    /// </summary>
    /// <param name="toRotation"></param>
    /// <param name="multi"></param>
    /// <returns></returns>
    private IEnumerator RotateForwardWithSpeed(Vector3 toRotation,float multi)
    {
        while (Vector3.Angle(transform.forward, toRotation) > 3f)
        {
            transform.forward = Vector3.Slerp(transform.forward, toRotation, rotationSpeed * multi * Time.deltaTime);
            yield return null;
        }
    }

    #endregion

    #region UnityEvent事件
    public void OnEnemyDeath(EnemyController enemy)
    {
        //如果当前锁定的敌人死亡,则解除死亡状态
        if(curLockedEnemy!=null&&curLockedEnemy==enemy)
        {
            IsLock = false;
            curLockedEnemy = null;
            GlobalEvent.CallExitFocusOnEnemy();
            CameraManager.Instance.SwitchCameraStyle(CameraStyle.ThirdPersonNormal);
        }
    }

    #endregion
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值