Unity类银河战士恶魔城学习总结(P178 Archer s arrow 弓箭手的箭)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/

本章节制作了一个弓箭手的箭

Arrow_Controller.cs

1.OnTriggerEnter2D方法

  • 功能:检测箭矢与其他对象的碰撞。
  • 逻辑
    • 如果碰撞对象的层级与targetLayerName匹配
      • 获取碰撞对象的CharacterStats组件并调用TakeDamage(damage)方法,造成伤害。
      • 调用StuckInto(collision)方法,使箭矢嵌入碰撞对象。
    • 如果碰撞对象的层级为"Ground"
      • 直接调用StuckInto(collision)方法,使箭矢嵌入地面。

2.StuckInto方法

  • 功能:处理箭矢嵌入目标后的状态变化。
  • 步骤
    1. 停止粒子系统 :停止箭矢子对象中的ParticleSystem,例如拖尾效果。
    2. 禁用碰撞体 :禁用箭矢的Collider2D,防止进一步的碰撞检测。
    3. 停止移动 :将canMove设为false,阻止在Update中继续移动。
    4. 设置刚体为运动学 :将rb.isKinematic设为true,使箭矢不再受物理引擎影响。
    5. 冻结所有刚体约束 :通过rb.constraints = RigidbodyConstraints2D.FreezeAll冻结箭矢的所有移动和旋转,确保其在嵌入后不再移动。
    6. 设置父对象 :将箭矢的transform设置为碰撞对象的子对象,使其随碰撞对象一起移动。
    7. 销毁箭矢 :在5到7秒后销毁箭矢对象,使用Random.Range(5,7)生成销毁延迟时间。

3.FlipArrow()方法

功能:翻转箭矢的方向,使其朝相反方向移动,并更改目标层级。

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//2024.12.11
public class Arrow_Controller : MonoBehaviour
{
    [SerializeField] private int damage;//箭矢造成的伤害值
    [SerializeField] private string targetLayerName = "Player";//箭矢的目标层

    [SerializeField] private float xVelocity;
    [SerializeField] private Rigidbody2D rb;

    [SerializeField] private bool canMove;
    [SerializeField] private bool flipped;


    private void Update()
    {
        if(canMove)
            rb.velocity = new Vector2(xVelocity, rb.velocity.y);
    }



    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.layer == LayerMask.NameToLayer(targetLayerName))
        {
            collision.GetComponent<CharacterStats>().TakeDamage(damage);
            StuckInto(collision);

        }
        else if (collision.gameObject.layer == LayerMask.NameToLayer("Ground"))
        {
            StuckInto(collision);
        }

    }


    private void StuckInto(Collider2D collision)//射中目标
    {
        GetComponentInChildren<ParticleSystem>().Stop();//停止粒子系统
        GetComponent<Collider2D>().enabled = false;
        canMove = false;
        rb.isKinematic = true;//刚体为运动
        rb.constraints = RigidbodyConstraints2D.FreezeAll;
        transform.parent = collision.transform;//箭矢的父物体为碰撞物体

        Destroy(gameObject, Random.Range(5,7));
    }


    public void FlipArrow()
    {
        if (flipped)
            return;


        xVelocity = xVelocity * -1;
        flipped = true;
        transform.Rotate(0,180,0);
        targetLayerName = "Enemy";

    }
}

PlayerCounterAttackState.cs

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerCounterAttackState : PlayerState
{
    private bool canCreateClone;

    public PlayerCounterAttackState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();

        canCreateClone = true;
        stateTimer = player.counterAttackDuration;
        player.anim.SetBool("SuccessfulCounterAttack", false);

    }

    public override void Exit()
    {
        base.Exit();
    }

    public override void Update()
    {
        base.Update();

        player.SetZeroVelocity();

        Collider2D[] colliders = Physics2D.OverlapCircleAll(player.attackCheck.position, player.attackCheckRadius);


        foreach (var hit in colliders)
        {
            if(hit.GetComponent<Arrow_Controller>()!= null)
            {
                hit.GetComponent<Arrow_Controller>().FlipArrow();
                SuccesfulCounterAttack();
            }


            if (hit.GetComponent<Enemy>() != null)
            {
                if (hit.GetComponent<Enemy>().CanBeStunned())
                    {
                        SuccesfulCounterAttack();

                        player.skill.parry.UseSkill();


                        if (canCreateClone)
                        {
                            canCreateClone = false;
                            player.skill.parry.MakeMirageOnParry(hit.transform);
                        }
                    }
                }
        }

        if (stateTimer < 0 || triggerCalled)
            stateMachine.ChangeState(player.idleState);

    }

    private void SuccesfulCounterAttack()
    {
        stateTimer = 10;//大于1的数,保证不会进入idle状态
        player.anim.SetBool("SuccessfulCounterAttack", true);
    }
}
相关推荐
什巳3 分钟前
JAVA练习278- 和为 K 的子数组
java·学习·算法·leetcode
碎光拾影36 分钟前
CPU与MCU核心区别揭秘
单片机·学习·51单片机
我命由我123452 小时前
复利极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
AOwhisky3 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制
tyqtyq223 小时前
药品说明书解读 —— AI 安全用药助手,鸿蒙原生应用深度解析
人工智能·学习·华为·生活·harmonyos
小心亦新4 小时前
STM32学习13 定时器1中断
stm32·嵌入式硬件·学习
我命由我123454 小时前
72 法则极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
qq_263_tohua5 小时前
第112期 CNN学习,不错的文章
学习
我想我不够好。5 小时前
满级的惩戒在范围
学习
LiaoWL1235 小时前
【SpringCloud合集-04】Sentinel 流量控制与熔断降级 学习笔记
学习·spring cloud·sentinel