Unity类银河恶魔城学习记录15-3 p155 More example on audio effects

 

 Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
此代码仅为较上一P有所改变的代码

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

 AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManager : MonoBehaviour
{
    public static AudioManager instance;

    [SerializeField] private float sfxMinimumDistance;
    [SerializeField] private AudioSource[] sfx;
    [SerializeField] private AudioSource[] bgm;

    public bool playBgm;
    private int bgmIndex;

    private void Awake()
    {
        if (instance != null)
        {
            Destroy(instance.gameObject);
        }
        else
            instance = this;

    }

    private void Update()
    {
        if (!playBgm)
            StopAllBGM();
        else
        {
            if (!bgm[bgmIndex].isPlaying)
                PlayBGM(bgmIndex);
        }
    }

    public void PlaySFX(int _sfxIndex,Transform _source)
    {
        //if (sfx[_sfxIndex].isPlaying)//防止出现多个相同物体同时发出声音
        //{
        //    return;
        //}
        if (_source != null && Vector2.Distance(PlayerManager.instance.player.transform.position, _source.position) > sfxMinimumDistance)//防止东西很远的情况下发出声音
            return;

        if(_sfxIndex < sfx.Length)
        {
            sfx[_sfxIndex].pitch = Random.Range(.85f, 1.1f);
            sfx[_sfxIndex].Play();
        }
    }

    public void StopSFX(int _sfxIndex)
    {
        sfx[_sfxIndex].Stop();
    }
    public void PlayRandomBGM()
    {
        bgmIndex = Random.Range(0, bgm.Length);
        PlayBGM(bgmIndex);
    }
    public void PlayBGM(int _bgmIndex)
    {
        bgmIndex = _bgmIndex;
        StopAllBGM();
        if (_bgmIndex < sfx.Length)
        {
            bgm[_bgmIndex].Play();
        }
    }

    public void StopAllBGM()
    {
        for(int i = 0; i < bgm.Length; i++)
        {
            bgm[i].Stop();
        }
    }
}
Checkpoint.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Checkpoint : MonoBehaviour
{
    private Animator anim;
    public string id;
    public bool activationStatus;
    private void Awake()
    {
        anim = GetComponent<Animator>();
    }
    private void Start()
    {
        anim = GetComponent<Animator>();
    }

    [ContextMenu("Generate checkpoint id")]
    private void GenerateId()//制作ID函数
    {
        id = System.Guid.NewGuid().ToString();//不根据path,直接生成id
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.GetComponent<Player>()!=null)
        {
            ActivateCheckpoint();
        }
    }

    public void ActivateCheckpoint()//激活检查点函数
    {
        if (activationStatus == false) 
            AudioManager.instance.PlaySFX(5, transform);
        anim.SetBool("active", true);
        activationStatus = true;
    }
}
ItemObject.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemObject : MonoBehaviour
{
    private SpriteRenderer sr;

    [SerializeField] private Rigidbody2D rb;//设置速度
    [SerializeField] private ItemData ItemData;
    [SerializeField] private Vector2 velocity;//设置速度


    private void SetupVisuals()
    {
        if (ItemData == null)
            return;

        GetComponent<SpriteRenderer>().sprite = ItemData.icon;
        gameObject.name = ItemData.name;
    }
   
    public void SetupItem(ItemData _itemData,Vector2 _velocity)设置实例函数
    {
        ItemData = _itemData;
        rb.velocity = _velocity;//设置速度

        SetupVisuals();
    }

    public void PickupItem()//拾取函数打包
    {
        if(!Inventory.instance.CanAddItem()&&ItemData.itemType == ItemType.Equipment)//修复在Inventory满时捡钱装备并销毁它的bug
        {
            rb.velocity = new Vector2(0, 7);
            return;
        }
        AudioManager.instance.PlaySFX(18, transform);
        Inventory.instance.AddItem(ItemData);
        Destroy(gameObject);
    }
}
Skill.cs
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

public class Skill : MonoBehaviour
{
    public float cooldown;
    public float cooldownTimer;

    protected Player player;//拿到player
    
    protected virtual void Start()
    {
        player = PlayerManager.instance.player;//拿到player

        CheckUnlock();
    }
    protected virtual void Update()
    {
        cooldownTimer -= Time.deltaTime;
    }
    protected virtual void CheckUnlock()//再次打开游戏时读取数据文件后使技能可以使用的函数
    {

    }

    public virtual bool CanUseSkill()
    {
        if (cooldownTimer < 0)
        {
            UseSkill();
            cooldownTimer = cooldown;
            return true;
        }
        else
        {
            Debug.Log("Skill is on cooldown");
            return false;
        }

    }
    public virtual void UseSkill()
    {
        // do some skill thing
    }


    //整理能返回最近敌人位置的函数
    protected virtual Transform FindClosestEnemy(Transform _checkTransform)
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(_checkTransform.position, 25);//找到环绕自己的所有碰撞器

        float closestDistance = Mathf.Infinity;//正无穷大的表示形式(只读)
        Transform closestEnemy = null;


        //https://docs.unity3d.com/cn/current/ScriptReference/Mathf.Infinity.html
        foreach (var hit in colliders)
        {
            if (hit.GetComponent<Enemy>() != null)
            {
                float distanceToEnemy = Vector2.Distance(_checkTransform.position, hit.transform.position);//拿到与敌人之间的距离
                if (distanceToEnemy < closestDistance)//比较距离,如果离得更近,保存这个敌人的位置,更改最近距离
                {
                    closestDistance = distanceToEnemy;
                    closestEnemy = hit.transform;
                }
            }
        }

        return closestEnemy;
       
    }

}
Blackhole_Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Blackhole_Skill : Skill
{
    
    [SerializeField] private UI_SkillTreeSlot balckholeUnlockButton;
    public bool blackholeUnlocked { get; private set; }

    [SerializeField]private float maxSize;//最大尺寸
    [SerializeField] private float growSpeed;//变大速度
    [SerializeField] private float shrinkSpeed;//缩小速度

    [SerializeField] private GameObject blackholePrefab;
    [Space]

    [SerializeField] private float blackholeDuration;
    [SerializeField] int amountOfAttacks = 4;
    [SerializeField] float cloneAttackCooldown = .3f;

    Blackhole_Skill_Controller currentBlackhole;
    private void UnlockBlackhole()
    {
        if(balckholeUnlockButton.unlocked)
        {
            blackholeUnlocked = true;
        }
    }
    public override bool CanUseSkill()
    {
        return base.CanUseSkill();
    }

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

        GameObject newBlackhole = Instantiate(blackholePrefab,player.transform.position,Quaternion.identity);

        currentBlackhole = newBlackhole.GetComponent<Blackhole_Skill_Controller>();

        currentBlackhole.SetupBlackhole(maxSize,growSpeed,shrinkSpeed,amountOfAttacks,cloneAttackCooldown,blackholeDuration);

        AudioManager.instance.PlaySFX(3, player.transform);
        AudioManager.instance.PlaySFX(6, player.transform);
    }
    
    protected override void Start()
    {
        base.Start();
        balckholeUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockBlackhole);
    }

    protected override void Update()
    {
        base.Update();
    }

    public bool SkillCompleted()
    {
        if(currentBlackhole == null)
         return false;
        if (currentBlackhole.playerCanExitState)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    //把随机敌人半径改成黑洞半径的一半就行
    public float GetBlackholeRadius()
    {
        return maxSize / 2;
    }

    protected override void CheckUnlock()
    {
        base.CheckUnlock();
        UnlockBlackhole();
    }
}
PlayerGroundState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//GroundState用于保证只有在Idle和Move这两个地面状态下才能调用某些函数,并且稍微减少一点代码量
public class PlayerGroundState : PlayerState
{
    public PlayerGroundState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

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

    public override void Exit()
    {
        base.Exit();
    }
    public override void Update()
    {
        base.Update();
        if(Input.GetKeyDown(KeyCode.R)&& player.skill.blackhole.blackholeUnlocked)
        {
            if (player.skill.blackhole.cooldown > 0)
                return;

            stateMachine.ChangeState(player.blackhole);
        }
        if(Input.GetKeyDown(KeyCode.Mouse1)&&HasNoSword() && player.skill.sword.swordUnlocked)//点击右键进入瞄准状态,当sword存在时,不能进入aim状态
        {
            stateMachine.ChangeState(player.aimSword);
        }
        if(Input.GetKeyDown(KeyCode.Q) && player.skill.parry.parryUnlocked)//摁Q进入反击状态
        {
            stateMachine.ChangeState(player.counterAttack);
        }
        if(Input.GetKeyDown(KeyCode.Mouse0))//p38 2.从ground进入攻击状态
        {
            stateMachine.ChangeState(player.primaryAttack);
        }
        if(player.IsGroundDetected()==false)
        {
            stateMachine.ChangeState(player.airState);
        }// 写这个是为了防止在空中直接切换为moveState了。

        if (Input.GetKeyDown(KeyCode.Space) && player.IsGroundDetected())
        {
            stateMachine.ChangeState(player.jumpState);
        }//空格切换为跳跃状态


    }
    private bool HasNoSword()//用这个函数同时控制了是否能进入aimSword和如果sword存在便使他回归player的功能
    {
        if(!player.sword)
        {
            return true;
        }
        player.sword.GetComponent<Sword_Skill_Controller>().ReturnSword();
        return false;
    }
}
PlayerMoveState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMoveState : PlayerGroundState
{
    public PlayerMoveState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }//构造函数,用于传递信息。
     //当外补New出对象时,New出的对象里传入参数

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

        AudioManager.instance.PlaySFX(14,null);
    }

    public override void Exit()
    {
        base.Exit();
        AudioManager.instance.StopSFX(14);
    }

    public override void Update()
    {
        base.Update();
        player.SetVelocity(xInput*player.moveSpeed, rb.velocity.y);//player.rb.newVelocity.y默认的为0,player.moveSpeed在player中定义,但可以在Unity引擎中更改
        if (xInput==0|| player.IsWallDetected())
        {
            stateMachine.ChangeState(player.idleState);//在这里我们能使用Player里的东西,主要是因为我们通过构造函数传过来Player实体,如果不传,则无法使用已经存在了的Player实体。
        }
    }
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值