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);
    }
}
相关推荐
向日葵xyz14 分钟前
Qt5与现代OpenGL学习(十一)OpenGL Widget鼠标控制直线旋转
开发语言·qt·学习
o0向阳而生0o33 分钟前
42、在.NET 中能够将⾮静态的⽅法覆写成静态⽅法吗?
c#·.net
aminghhhh1 小时前
多模态融合【十九】——MRFS: Mutually Reinforcing Image Fusion and Segmentation
人工智能·深度学习·学习·计算机视觉·多模态
努力毕业的小土博^_^2 小时前
【深度学习|学习笔记】 Generalized additive model广义可加模型(GAM)详解,附代码
人工智能·笔记·深度学习·神经网络·学习
虾球xz3 小时前
游戏引擎学习第277天:稀疏实体系统
c++·学习·游戏引擎
小堃学编程3 小时前
前端学习(2)—— CSS详解与使用
前端·css·学习
虾球xz5 小时前
游戏引擎学习第276天:调整身体动画
c++·学习·游戏引擎
虾球xz5 小时前
游戏引擎学习第275天:将旋转和剪切传递给渲染器
c++·学习·游戏引擎
qq_386322696 小时前
华为网路设备学习-21 IGP路由专题-路由过滤(filter-policy)
前端·网络·学习
J先生x6 小时前
【IP101】图像处理进阶:从直方图均衡化到伽马变换,全面掌握图像增强技术
图像处理·人工智能·学习·算法·计算机视觉