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

2024-09-24
130看过
制作箭矢射出功能
Projectile
  1. using RPG.Combat;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. // 定义Projectile类
  6. public class Projectile : MonoBehaviour
  7. {
  8.    
  9.     [SerializeField] float speed = 1;//箭矢射出的速度
  10.     Health target = null;//攻击目标
  11.     float damage = 0;
  12.     private void Update()
  13.     {
  14.         if(target == null)//如果攻击目标为空
  15.         {
  16.             return;
  17.         }
  18.         transform.LookAt(GetAimLocation());//让箭朝向目标位置
  19.         // 使用Translate方法让箭根据速度和时间增量来移动-- // Vector3.forward表示projectile的前向向量,speed是速度,Time.deltaTime是上一帧到当前帧的时间差
  20.         transform.Translate(Vector3.forward*speed * Time.deltaTime);
  21.     }
  22.     public void SetTarget(Health target,float damage)//设置目标
  23.     {
  24.         this.target = target;
  25.         this.damage = damage;
  26.     }
  27.     private Vector3 GetAimLocation()//获取瞄准的目标位置
  28.     {
  29.         CapsuleCollider targetCapsule = target.GetComponent<CapsuleCollider>();//获取目标的碰撞组件
  30.         if(targetCapsule == null)//如果碰撞为空
  31.         {
  32.             return target.transform.position;//返回目标坐标
  33.         }
  34.         // 如果有CapsuleCollider组件,则返回目标位置上方CapsuleCollider高度的一半处  -确保projectile瞄准的是目标的上半身或中心位置  
  35.         return target.transform.position + Vector3.up * targetCapsule.height /2;
  36.     }
  37.     private void OnTriggerEnter(Collider other)
  38.     {
  39.       
  40.         //print("箭的伤害:" + damage);
  41.         Health health = other.GetComponent<Health>();//获取碰撞触发的生命值组件  return
  42.         if (target != null && health != target) return;//如果目标不为空并且生命值不是攻击的目标 return
  43.         if (health == null || health.IsDead()) return;//如果生命值为空 或者角色已经死亡 return
  44.         
  45.         target.TakeDamage(damage);
  46.         Destroy(gameObject);
  47.     }
  48. }
复制代码



Weapon
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace RPG.Combat
  5. {
  6.     /// <summary>
  7.     /// 武器脚本
  8.     /// </summary>
  9.     [CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Waepon", order = 0)]
  10.     public class Weapon : ScriptableObject
  11.     {
  12.         [SerializeField] float weaponDamage = 5f;//武器伤害
  13.         [SerializeField] float weaponRange = 2f;// 武器攻击范围
  14.         [SerializeField] AnimatorOverrideController animatorOverride = null;//装备武器动画
  15.         [SerializeField] GameObject equippedPrefab = null;//武器预制体
  16.         [SerializeField] bool isRightHanded = true;//装备左右手武器,true为右手,false为左手
  17.         [SerializeField] Projectile projectile = null;//箭矢
  18.         /// <summary>
  19.         /// 诞生武器
  20.         /// </summary>
  21.         /// <param name="rightHand">右手武器产生的位置</param>
  22.         /// <param name="leftHand">左手武器产生的位置</param>
  23.         /// <param name="animator">武器对应的动画状态机</param>
  24.         public void Spawn(Transform rightHand,Transform leftHand, Animator animator)
  25.         {
  26.             if (equippedPrefab != null)//如果不为空,就实例化,防止为空时出现错误
  27.             {
  28.                 Transform handTransform = GetTransform(rightHand, leftHand);
  29.                 Instantiate(equippedPrefab, handTransform);//实例化武器
  30.             }
  31.             if (animatorOverride != null) //如果动画状态不为空,就改变为新的动画状态
  32.             {
  33.                 animator.runtimeAnimatorController = animatorOverride;//状态机更改为装备武器的状态
  34.             }
  35.         }
  36.         /// <summary>
  37.         /// 获取位置
  38.         /// </summary>
  39.         /// <param name="rightHand">右手</param>
  40.         /// <param name="leftHand">左手</param>
  41.         /// <returns></returns>
  42.         private Transform GetTransform(Transform rightHand, Transform leftHand)
  43.         {
  44.             Transform handTransform;
  45.             if (isRightHanded)
  46.             {
  47.                 handTransform = rightHand;//fasle则装备右手武器
  48.             }
  49.             else
  50.             {
  51.                 handTransform = leftHand;//装备左手武器
  52.             }
  53.             return handTransform;
  54.         }
  55.         public bool HasProjectile()//是否有箭矢
  56.         {
  57.             return projectile != null;//返回箭不为空
  58.         }
  59.         //发射箭矢
  60.         public void LacunchProjectile(Transform rightHand,Transform leftHand,Health target)
  61.         {
  62.             //实例化箭矢 Quaternion.identity没有旋转的状态
  63.             Projectile projectileInstance = Instantiate(projectile, GetTransform(rightHand, leftHand).position,Quaternion.identity);
  64.             projectileInstance.SetTarget(target);//设置目标
  65.         }
  66.         public float GetDamage() //获取伤害
  67.         {
  68.             return weaponDamage;
  69.         }
  70.         public float GetRange()//获取武器攻击范围
  71.         {
  72.             return weaponRange;
  73.         }
  74.     }
  75. }
复制代码



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.       
  12.         [SerializeField] float timeBetweenAttacks = 1f;//攻击间隔时间
  13.       
  14.         [SerializeField] Transform rightHandTransform = null;//武器实例化的地方
  15.         [SerializeField] Transform leftHandTransform = null;//武器实例化的地方
  16.         [SerializeField] Weapon defaultWeapon = null;//设置默认武器脚本
  17.         Health target;// 当前攻击的目标
  18.         float timeSinceLastAttack = Mathf.Infinity;//上次攻击的时间为 为无穷大
  19.         Weapon currentWeapon = null;
  20.         private Mover mover;// 用于移动角色的 Mover 组件
  21.         private bool isInRange;// 标记目标是否在攻击范围内
  22.         private Animator animator;
  23.         private void Start()
  24.         {
  25.             mover = GetComponent<Mover>();// 获取 Mover 组件
  26.             animator = GetComponent<Animator>();//获取动画组件
  27.             EquipWeapon(defaultWeapon);
  28.         }
  29.         private void Update()
  30.         {
  31.             timeSinceLastAttack += Time.deltaTime;//设置攻击后的时间统计累加
  32.            
  33.             if (target == null) return;// 如果目标为空,则不进行任何操作
  34.             if (target.IsDead()) return;//如果目标已经死亡,直接return
  35.             if (!GetIsInRange()) // 如果目标不在攻击范围内,则移动到目标位置
  36.             {
  37.                 mover.MoveTo(target.transform.position,1f);//设置战斗时百分比为1
  38.                
  39.             }
  40.             else
  41.             {
  42.                 mover.Cancel(); // 目标在攻击范围内,取消移动,并触发攻击动画
  43.                 AttackBehaviour();
  44.             }
  45.         }
  46.         public void EquipWeapon(Weapon weapon)//实例化武器Projectile
  47.         {
  48.             print("装备武器");
  49.             currentWeapon = weapon;
  50.             defaultWeapon = currentWeapon;
  51.             if (weapon == null) return;
  52.             weapon.Spawn(rightHandTransform,leftHandTransform, animator);
  53.             
  54.         }
  55.         private void AttackBehaviour()//攻击行为
  56.         {
  57.             transform.LookAt(target.transform.position);//攻击时面向敌人
  58.             if (timeSinceLastAttack > timeBetweenAttacks)//任何时候都大于攻击间隔
  59.             {
  60.                 TriggerAttack();
  61.                 timeSinceLastAttack = 0;//重置攻击后的时间为0
  62.             }
  63.         }
  64.         
  65.         private void TriggerAttack()//动画状态机 攻击触发
  66.         {
  67.             animator.ResetTrigger("stopAttack");
  68.             animator.SetTrigger("attack");
  69.         }
  70.         // 动画事件:攻击时触发的事件
  71.         private void Hit()
  72.         {
  73.            if (target == null) return;//如果目标为空,跳出
  74.            if(currentWeapon.HasProjectile())//如果当前武器为弓箭
  75.             {
  76.                 //发射箭矢
  77.                 currentWeapon.LacunchProjectile(rightHandTransform, leftHandTransform, target);
  78.             }
  79.            else
  80.             {
  81.                 target.TakeDamage(defaultWeapon.GetDamage());//造成伤害
  82.             }
  83.         }
  84.         private void Shoot()//射击事件
  85.         {
  86.             Hit();
  87.         }
  88.         private bool GetIsInRange()// 检查目标是否在攻击范围内
  89.         {
  90.             return Vector3.Distance(transform.position, target.transform.position) < defaultWeapon.GetRange();
  91.         }
  92.         
  93.         public bool CanAttack(GameObject combatTarget)//检测是否可以攻击
  94.         {
  95.             if(combatTarget == null) //如果攻击目标为空 跳出
  96.             {
  97.                 return false;
  98.             }
  99.             Health targetToTest = combatTarget.GetComponent<Health>();//获取目标的生命组件
  100.             return targetToTest != null && !targetToTest.IsDead();//目标不为空,并且没有死亡
  101.         }
  102.         public void Attack(GameObject combatTarget)//攻击
  103.         {
  104.             
  105.             GetComponent<ActionScheduler>().StartAction(this); // 启动当前动作并设置目标
  106.             target = combatTarget.GetComponent<Health>();//获取目标的生命组件
  107.         }
  108.         public void Cancel()//取消
  109.         {
  110.             StopAttack();//调用停止攻击
  111.             target = null;//清除目标
  112.             mover.Cancel();//取消移动
  113.         }
  114.         private void StopAttack()//动画状态机 停止攻击
  115.         {
  116.             animator.ResetTrigger("attack");//重置攻击
  117.             animator.SetTrigger("stopAttack");//播放暂停攻击
  118.         }
  119.     }
  120. }
复制代码




回复

举报

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

本版积分规则

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