[Realize 17 of 100 Games with Unity] Create a Survivor Roguelike game 3 from scratch (with project source code)

The final effect of this section

Insert image description here

Preface

This section follows the previous one and mainly implements weapon functions.

melee weapons

Added Bullet, bullet script

public class Bullet : MonoBehaviour
{
    
    
    public float damage; // 子弹的伤害值

    /// <summary>
    /// 初始化子弹的属性
    /// </summary>
    /// <param name="damage">伤害值</param>
    public void Init(float damage)
    {
    
    
        this.damage = damage; // 设置子弹的伤害值
    }
}

Added new melee weapon prefab, added triggers, mounting scripts, and configuration parameters
Insert image description here

Modify Enemy enemy script and add trigger detection

void OnTriggerEnter2D(Collider2D collision)
{
    
    
    if (!collision.CompareTag("Bullet")) return;
    health -= collision.GetComponent<Bullet>().damage;
    if (health > 0)
    {
    
    

    }
    else
    {
    
    
        Dead();
    }
}

void Dead()
{
    
    
    gameObject.SetActive(false);
}

Effect, enemies die on contact
Insert image description here

Control melee weapon spawning

Configure melee weapons into the object pool
Insert image description here

Added Weapon. Control weapon/bullet generation

public class Weapon : MonoBehaviour
{
    
    
    public int id; // 武器/子弹的ID
    public int prefabId; // 武器/子弹预制体的ID
    public float damage; // 武器/子弹的伤害值
    public int count; // 发射武器/子弹的数量
    public float speed; // 武器旋转的速度

    void Start()
    {
    
    
        Init(); // 初始化武器属性
    }

    void Update()
    {
    
    
        switch (id)
        {
    
    
            case 0:
                transform.Rotate(Vector3.back, speed * Time.deltaTime); // 绕z轴旋转武器
                break;
            default:
                break;
        }
    }

    /// <summary>
    /// 初始化武器/子弹属性
    /// </summary>
    public void Init()
    {
    
    
        switch (id)
        {
    
    
            case 0:
                speed = 150; // 设置武器旋转的速度
                Batch();
                break;
            default:
                break;
        }
    }

    /// <summary>
    /// 批量配置武器属性
    /// </summary>
    void Batch()
    {
    
    
        for (int index = 0; index < count; index++)
        {
    
    
            Transform bullet = GameManager.instance.pool.Get(prefabId).transform; // 从对象池中获取武器预制体的实例
            bullet.parent = transform; // 设置武器的父级为武器

            Vector3 rotvec = Vector3.forward * 360 * index / count; // 计算武器的旋转角度,使其均匀分布在圆周上
            bullet.Rotate(rotvec); // 设置武器的旋转角度
            bullet.Translate(bullet.up * 1.5f, Space.World); // 将武器沿着自身的y轴方向向前移动一定距离

            bullet.GetComponent<Bullet>().Init(damage); // 初始化武器的属性
        }
    }
}

Mount configuration parameters
Insert image description here
Single weapon effect
Insert image description here
Multiple weapon effect
Insert image description here
Insert image description here

Upgrades increase weapon damage and quantity

Modify Weapon

void Update()
{
    
    
    //。。。

    //测试
    if (Input.GetKeyDown(KeyCode.Space))
    {
    
    
        LevelUp(20, 5);
    }
}


/// <summary>
/// 批量配置武器属性
/// </summary>
void Batch()
{
    
    
    for (int index = 0; index < count; index++)
    {
    
    
        Transform bullet;
        if (index < transform.childCount)
        {
    
    
            bullet = transform.GetChild(index);
        }
        else
        {
    
    
            bullet = GameManager.instance.pool.Get(prefabId).transform;// 从对象池中获取武器预制体的实例
            bullet.parent = transform;// 设置武器的父级为武器
        }
        
        //。。。
    }
}

Effect
Insert image description here

Find the enemy closest to the protagonist

Add Scanner

public class Scanner : MonoBehaviour
{
    
    
    public float scanRange; // 扫描范围
    public LayerMask targetLayer; // 目标层
    public RaycastHit2D[] targets; // 扫描到的目标
    public Transform nearestTarget; // 最近的目标

    void FixedUpdate()
    {
    
    
        targets = Physics2D.CircleCastAll(transform.position, scanRange, Vector2.zero, 0, targetLayer); // 在扫描范围内发射圆形光线,获取扫描到的目标
        nearestTarget = GetNearest();
    }

    // 获取最近的目标
    Transform GetNearest()
    {
    
    
        Transform result = null; // 初始化最近的目标为null
        float diff = scanRange; // 初始化最小距离为100,用于后面比较
        foreach (RaycastHit2D target in targets)
        {
    
    
            Vector3 myPos = transform.position; // 获取自身位置
            Vector3 targetPos = target.transform.position; // 获取目标位置
            float curDiff = Vector3.Distance(myPos, targetPos); // 计算自身与目标的距离
            if (curDiff < diff) // 如果当前目标距离比之前的最小距离还小,说明这个目标更近
            {
    
    
                diff = curDiff; // 更新最小距离
                result = target.transform; // 更新最近的目标
            }
        }
        return result; // 返回最近的目标
    }
    
    //场景窗口可视化射线
    private void OnDrawGizmos()
    {
    
    
        Gizmos.DrawWireSphere(transform.position, scanRange);
        Gizmos.color = Color.red;
    }
}

Mount script, configuration parameters
Insert image description here

The effect is to obtain the enemy closest to you.
Insert image description here

bullet prefab

Insert image description here

Object pool mounted bullet
Insert image description here

generate bullets

Modify Weapon

float timer;
Player player;

void Start()
{
    
    
    player = GameManager.instance.player;
    Init(); // 初始化武器属性
}

void Update()
{
    
    
    switch (id)
    {
    
    
        //。。。
        
        default:
            timer += Time.deltaTime;
            if (timer > speed)
            {
    
    
                timer = 0f;
                Fire();
            }
            break;
    }
}

/// <summary>
/// 初始化武器/子弹属性
/// </summary>
public void Init()
{
    
    
    switch (id)
    {
    
    
        //。。。
        
        default:
            speed = 0.3f;
            break;
    }
}

//发射子弹
void Fire()
{
    
    
    if (!player.scanner.nearestTarget) return;
    Transform bullet = GameManager.instance.pool.Get(prefabId).transform;
    bullet.position = transform.position;
}

Modify Player to obtain recent enemy data

[NonReorderable]
public Scanner scanner;

scanner = GetComponent<Scanner>();

Configure bullet generation container and data
Insert image description here
Effect, generate a bullet every 0.3 seconds
Insert image description here

fire bullets

Modify Bullet

Rigidbody2D rigid;
private int per; // 子弹的穿透次数

void Awake()
{
    
    
    rigid = GetComponent<Rigidbody2D>(); // 获取子弹的刚体组件
}

public void Init(float damage, int per, Vector3 dir)
{
    
    
    this.damage = damage; // 初始化子弹的伤害值
    this.per = per; // 初始化子弹的穿透次数

    if (per > -1)
    {
    
    
        rigid.velocity = dir * 15f; // 如果子弹具有穿透次数,则设置子弹的初始速度和方向
    }
}

void OnTriggerEnter2D(Collider2D collision)
{
    
    
    if (!collision.CompareTag("Enemy") || per == -1) return; // 如果碰撞物体不是敌人或子弹没有穿透次数,直接返回

    per--; // 穿透次数减一

    if (per == -1)
    {
    
    
        rigid.velocity = Vector2.zero; // 如果穿透次数减到-1,即没有穿透能力了,将子弹的速度设为零
        gameObject.SetActive(false); // 将子弹设为非激活状态,使其隐藏或回收
    }
}

Modify Weapon

void Batch()
{
    
    
    //。。。

        bullet.GetComponent<Bullet>().Init(damage, -1, Vector3.zero); // 初始化武器的属性
    }
}

// 发射子弹
void Fire()
{
    
    
    if (!player.scanner.nearestTarget) return; // 如果玩家的扫描器没有最近的目标,直接返回

    Vector3 targetPos = player.scanner.nearestTarget.position; // 获取最近目标的位置
    Vector3 dir = targetPos - transform.position; // 计算从当前位置指向目标位置的方向向量
    dir = dir.normalized; // 将方向向量归一化,使其成为单位向量

    Transform bullet = GameManager.instance.pool.Get(prefabId).transform; // 从对象池中获取一个子弹对象
    bullet.position = transform.position; // 设置子弹的初始位置为当前位置
    bullet.rotation = Quaternion.FromToRotation(Vector3.up, dir); // 将子弹的朝向调整为指向目标位置的方向
    bullet.GetComponent<Bullet>().Init(damage, count, dir); // 初始化子弹的伤害值、穿透次数和初始速度方向
}

Effect
Insert image description here

Modify Weapon and upgrade testing

//测试
if (Input.GetKeyDown(KeyCode.Space))
{
    
    
    LevelUp(10, 1);
}

The effect is that after the upgrade, the bullet has a certain degree of penetration.
Insert image description here

reference

【Video】https://www.youtube.com/watch?v=MmW166cHj54&list=PLO-mt5Iu5TeZF8xMHqtT_DhAPKmjF6i3x

Source code

Source code is in the last section

end

Giving roses to others will leave a lingering fragrance in your hands! If the content of the article is helpful to you, please don't be stingy with your 点赞评论和关注 so that I can receive feedback as soon as possible. Every time you 支持 The greatest motivation for creation. Of course, if you find 存在错误 or 更好的解决方法 in the article, you are welcome to comment and send me a private message!

Good, I am向宇,https://xiangyu.blog.csdn.net

A developer who has been working quietly in a small company recently started studying Unity by himself out of interest. If you encounter any problems, you are also welcome to comment and send me a private message. Although I may not necessarily know some of the questions, I will check the information from all parties and try to give the best suggestions. I hope to help more people who want to learn programming. People, encourage each other~
Insert image description here

Guess you like

Origin blog.csdn.net/qq_36303853/article/details/134679197