Udemy-Unity制作类暗黑破坏神游戏记录-P42

2024-09-11
74看过
添加玩家攻击敌人时的转向,让角色可以随时攻击敌人随时朝向敌人,当多个敌人在范围内,允许玩家随时攻击任意敌人,并修复玩家在攻击和点击地面移动时的攻击冷却问题,主要是对stopAttack触发重置。

Fighter:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using RPG.Movement;
  5. using RPG.Core;
  6. namespace RPG.Combat
  7. {
  8.     //攻击
  9.     public class Fighter : MonoBehaviour, IAction
  10.     {
  11.         [SerializeField] float weaponRange = 2f;// 武器范围,表示武器可以攻击的最大距离
  12.         [SerializeField] float timeBetweenAttacks = 1f;//攻击间隔时间
  13.         [SerializeField] float weaponDamage = 5f;//武器伤害
  14.         Health target;// 当前攻击的目标
  15.         float timeSinceLastAttack = 0;//攻击后的时间统计
  16.         private Mover mover;// 用于移动角色的 Mover 组件
  17.         private bool isInRange;// 标记目标是否在攻击范围内
  18.         private Animator animator;
  19.         private void Start()
  20.         {
  21.             mover = GetComponent<Mover>();// 获取 Mover 组件
  22.             animator = GetComponent<Animator>();//获取动画组件
  23.            
  24.         }
  25.         private void Update()
  26.         {
  27.             timeSinceLastAttack += Time.deltaTime;//设置攻击后的时间统计累加
  28.            
  29.             if (target == null) return;// 如果目标为空,则不进行任何操作
  30.             if (target.IsDead()) return;//如果目标已经死亡,直接return
  31.             if (!GetIsInRange()) // 如果目标不在攻击范围内,则移动到目标位置
  32.             {
  33.                 mover.MoveTo(target.transform.position);
  34.                
  35.             }
  36.             else
  37.             {
  38.                 mover.Cancel(); // 目标在攻击范围内,取消移动,并触发攻击动画
  39.                 AttackBehaviour();
  40.             }
  41.         }
  42.         private void AttackBehaviour()//攻击行为
  43.         {
  44.             transform.LookAt(target.transform.position);//攻击时面向敌人
  45.             if (timeSinceLastAttack > timeBetweenAttacks)
  46.             {
  47.                 TriggerAttack();
  48.                 timeSinceLastAttack = 0;//重置攻击后的时间为0
  49.             }
  50.         }
  51.         
  52.         private void TriggerAttack()//动画状态机 攻击触发
  53.         {
  54.             animator.ResetTrigger("stopAttack");
  55.             animator.SetTrigger("attack");
  56.         }
  57.         // 动画事件:攻击时触发的事件
  58.         private void Hit()
  59.         {
  60.            if (target == null) return;
  61.             target.TakeDamage(weaponDamage);//造成伤害
  62.         }
  63.         private bool GetIsInRange()// 检查目标是否在攻击范围内
  64.         {
  65.             return Vector3.Distance(transform.position, target.transform.position) < weaponRange;
  66.         }
  67.         public bool CanAttack(CombatTarget combatTarget)//检测是否可以攻击
  68.         {
  69.             if(combatTarget == null) //如果攻击目标为空 跳出
  70.             {
  71.                 return false;
  72.             }
  73.             Health targetToTest = combatTarget.GetComponent<Health>();//
  74.             return targetToTest != null && !targetToTest.IsDead();
  75.         }
  76.         public void Attack(CombatTarget combatTarget)//攻击
  77.         {
  78.             
  79.             GetComponent<ActionScheduler>().StartAction(this); // 启动当前动作并设置目标
  80.             target = combatTarget.GetComponent<Health>();
  81.         }
  82.         public void Cancel()
  83.         {
  84.             StopAttack();
  85.             target = null;// 取消攻击,清除目标
  86.         }
  87.         private void StopAttack()//动画状态机 停止攻击
  88.         {
  89.             animator.ResetTrigger("attack");//重置攻击
  90.             animator.SetTrigger("stopAttack");//播放暂停攻击
  91.         }
  92.     }
  93. }
复制代码
PlayerController


  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using RPG.Movement;
  5. using RPG.Combat;
  6. //角色的控制
  7. namespace RPG.Control
  8. {
  9.    
  10.     public class PlayerController : MonoBehaviour
  11.     {
  12.         private Mover mover;
  13.         private void Start()
  14.         {
  15.             mover = GetComponent<Mover>();
  16.         }
  17.         private void Update()
  18.         {
  19.             if (InteractWithCombat()) return;
  20.             if (InteractWithMovement()) return;
  21.             
  22.         }
  23.         
  24.         // 战斗交互
  25.         private bool InteractWithCombat()
  26.         {
  27.             RaycastHit[] hits = Physics.RaycastAll(GetMouseRay());
  28.             foreach (RaycastHit hit in hits)
  29.             {
  30.                 CombatTarget target = hit.transform.GetComponent<CombatTarget>();//被射线击中的物体获取战斗目标组件
  31.                 if (!GetComponent<Fighter>().CanAttack(target))
  32.                 {
  33.                     continue;
  34.                 }
  35.                 if(Input.GetMouseButtonDown(0))//按下左键
  36.                 {
  37.                     GetComponent<Fighter>().Attack(target);//攻击目标
  38.                 }
  39.                 return true;//射线找到目标
  40.             }
  41.             return false;//射线没有找到目标  ActionScheduler
  42.         }
  43.         // 移动和交互
  44.         private bool InteractWithMovement()
  45.         {
  46.             RaycastHit hit;//存储射线碰撞的信息
  47.             bool hasHit = Physics.Raycast(GetMouseRay(), out hit); //通过射线检测是否有接触到碰撞物体
  48.             if (hasHit)//如果有检测到
  49.             {
  50.                 if (Input.GetMouseButton(0))//如果按下鼠标左键
  51.                 {
  52.                     mover.StartMoveAction(hit.point);
  53.                     
  54.                 }
  55.                 return true;
  56.             }
  57.             return false;
  58.         }
  59.         
  60.         //创建射线
  61.         private static Ray GetMouseRay()
  62.         {
  63.             return Camera.main.ScreenPointToRay(Input.mousePosition);
  64.         }
  65.     }
  66. }
复制代码



回复

举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表