您现在的位置是:首页 >技术杂谈 >Unity类·银河恶魔城之P78-P82网站首页技术杂谈
Unity类·银河恶魔城之P78-P82
简介Unity类·银河恶魔城之P78-P82
1,黑洞控制器预制件
2,热键控制器预制件
3,Blackhole_Skill_Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 黑洞控制器,负责管理黑洞技能的相关逻辑,如尺寸增长、敌人捕获、克隆体攻击等
public class Blackhole_Skill_Controller : MonoBehaviour
{
// 热键预制件,用于在敌人上方显示热键提示
[SerializeField] private GameObject hotkeyPrefab;
// 热键列表,存储可供选择的热键
[SerializeField] private List<KeyCode> keyCodeList;
// 黑洞的最大尺寸
private float maxSize;
// 黑洞的增长速度
private float growSpeed;
// 黑洞的缩小速度
private float shrinkSpeed;
// 黑洞持续时间计时器
private float blackholeTimer;
// 增长判断标志,为 true 时黑洞开始增长
private bool canGrow = true;
// 缩小判断标志,为 true 时黑洞开始缩小
private bool canShrink;
// 是否可以创建热键的标志
private bool canCreateHotkeys = true;
// 克隆体攻击释放标志,为 true 时开始克隆体攻击流程
private bool cloneAttackReleased;
// 玩家是否可以消失的标志
private bool playeCanDisapear = true;
// 克隆体攻击的数量
private int amountOfAttacks;
// 克隆体攻击的冷却时间
private float cloneAttackCooldown;
// 克隆体攻击的冷却计时器
private float cloneAttackTimer;
// 存储被黑洞捕获的敌人的集合
private List<Transform> targets = new List<Transform>();
// 存储创建的热键对象的列表
private List<GameObject> createdHotkey = new List<GameObject>();
// 玩家退出状态,外部可获取该状态
public bool playerCanExitState { get; private set; }
/// <summary>
/// 设置黑洞的相关参数
/// </summary>
/// <param name="_maxSize">黑洞的最大尺寸</param>
/// <param name="_growSpeed">黑洞的增长速度</param>
/// <param name="_shrinkSpeed">黑洞的缩小速度</param>
/// <param name="_amountOfAttacks">克隆体攻击的数量</param>
/// <param name="_cloneAttackCooldown">克隆体攻击的冷却时间</param>
/// <param name="_blackholeDuration">黑洞的持续时间</param>
public void SetupBlackhole(float _maxSize, float _growSpeed, float _shrinkSpeed, int _amountOfAttacks, float _cloneAttackCooldown, float _blackholeDuration)
{
maxSize = _maxSize;
growSpeed = _growSpeed;
shrinkSpeed = _shrinkSpeed;
amountOfAttacks = _amountOfAttacks;
cloneAttackCooldown = _cloneAttackCooldown;
blackholeTimer = _blackholeDuration;
}
private void Update()
{
// 减少克隆体攻击冷却计时器
cloneAttackTimer -= Time.deltaTime;
// 减少黑洞持续时间
blackholeTimer -= Time.deltaTime;
// 当黑洞持续时间结束
if (blackholeTimer < 0)
{
// 设置黑洞时间为无穷大,确保只检查一次
blackholeTimer = Mathf.Infinity;
// 若有捕获的敌人,释放克隆体攻击
if (targets.Count > 0)
{
ReleaseCloneAttack();
}
else
{
// 若无捕获的敌人,结束黑洞技能
FinishBlackHoleAbility();
}
}
//如果按下冲刺键则结束黑洞技能
if(Input.GetKeyDown(KeyCode.LeftShift))
{
// 若无捕获的敌人,结束黑洞技能
FinishBlackHoleAbility();
}
// 检测是否按下 R 键,且有捕获的敌人,按下则释放克隆体攻击
if (Input.GetKeyDown(KeyCode.R) && targets.Count > 0)
{
ReleaseCloneAttack();
}
// 处理克隆体攻击逻辑
CloneAttackLogic();
// 如果允许黑洞增长且不允许缩小
if (canGrow && !canShrink)
{
// 平滑地改变黑洞的尺寸,使其趋近于最大尺寸
transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(maxSize, maxSize), growSpeed * Time.deltaTime);
}
// 如果允许黑洞缩小
if (canShrink)
{
// 平滑地缩小黑洞尺寸
transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(-1, -1), shrinkSpeed * Time.deltaTime);
// 当黑洞尺寸小于 0 时,销毁黑洞对象
if (transform.localScale.x < 0)
{
Destroy(gameObject);
}
}
}
/// <summary>
/// 释放克隆体攻击
/// </summary>
private void ReleaseCloneAttack()
{
// 销毁所有热键
DestroyHotkeys();
// 标记克隆体攻击已释放
cloneAttackReleased = true;
// 禁止创建热键
canCreateHotkeys = false;
// 如果玩家可以消失
if (playeCanDisapear)
{
// 标记玩家不能再消失
playeCanDisapear = false;
// 使玩家透明
PlayerManager.instance.player.MakeTransprent(true);
}
}
/// <summary>
/// 处理克隆体攻击逻辑
/// </summary>
private void CloneAttackLogic()
{
// 当冷却时间结束,克隆体攻击已释放,且还有攻击次数
if (cloneAttackTimer < 0 && cloneAttackReleased && amountOfAttacks > 0)
{
// 重置冷却计时器
cloneAttackTimer = cloneAttackCooldown;
// 随机选择一个被捕获的敌人
int randomIndex = Random.Range(0, targets.Count);
// 随机生成 x 轴偏移量
float xOffset;
if (Random.Range(0, 100) > 50)
xOffset = 2;
else
xOffset = -2;
// 调用技能管理器的克隆技能,在随机敌人位置附近创建克隆体
SkillManager.instance.clone.CreateClone(targets[randomIndex], new Vector3(xOffset, 0));
// 减少克隆体攻击数量
amountOfAttacks--;
// 当克隆体攻击数量用完
if (amountOfAttacks <= 0)
{
// 延迟 1 秒后结束黑洞技能
Invoke("FinishBlackHoleAbility", 1f);
}
}
}
/// <summary>
/// 结束黑洞技能
/// </summary>
private void FinishBlackHoleAbility()
{
// 销毁所有热键
DestroyHotkeys();
// 允许玩家退出状态
playerCanExitState = true;
// 标记克隆体攻击未释放
cloneAttackReleased = false;
// 允许黑洞缩小
canShrink = true;
}
/// <summary>
/// 销毁所有创建的热键对象
/// </summary>
private void DestroyHotkeys()
{
// 如果没有创建热键,直接返回
if (createdHotkey.Count <= 0)
{
return;
}
// 遍历并销毁所有热键对象
for (int i = 0; i < createdHotkey.Count; i++)
{
Destroy(createdHotkey[i]);
}
}
/// <summary>
/// 当有 2D 碰撞体进入黑洞的触发范围时调用
/// </summary>
/// <param name="collision">碰撞的 2D 碰撞体</param>
private void OnTriggerEnter2D(Collider2D collision)
{
// 检查碰撞体是否为敌人
if (collision.GetComponent<Enemy>() != null)
{
// 冻结敌人的时间
collision.GetComponent<Enemy>().FreezeTime(true);
// 在敌人上方创建热键提示
CreateHotkey(collision);
}
}
/// <summary>
/// 当有 2D 碰撞体离开黑洞的触发范围时调用
/// </summary>
/// <param name="collision">碰撞的 2D 碰撞体</param>
private void OnTriggerExit2D(Collider2D collision)
{
// 检查碰撞体是否为敌人
if (collision.GetComponent<Enemy>() != null)
{
// 解除敌人的时间冻结
collision.GetComponent<Enemy>().FreezeTime(false);
}
}
/// <summary>
/// 在敌人上方创建热键提示
/// </summary>
/// <param name="collision">敌人的碰撞体</param>
private void CreateHotkey(Collider2D collision)
{
// 如果热键列表为空,输出错误信息并返回
if (keyCodeList.Count <= 0)
{
Debug.Log("热键是空的");
return;
}
// 如果克隆体攻击已释放,不创建热键
if (!canCreateHotkeys)
{
return;
}
// 实例化热键预制件,并设置其位置在敌人上方
GameObject newHotkey = Instantiate(hotkeyPrefab, collision.transform.position + new Vector3(0, 2), Quaternion.identity);
// 将新创建的热键添加到列表中
createdHotkey.Add(newHotkey);
// 随机选择一个热键
KeyCode choosenKey = keyCodeList[Random.Range(0, keyCodeList.Count)];
// 从热键列表中移除已选择的热键
keyCodeList.Remove(choosenKey);
// 获取热键对象的控制器脚本
Blackhole_Hotkey_Controller newHotkeyScript = newHotkey.GetComponent<Blackhole_Hotkey_Controller>();
// 设置热键的相关信息,包括选择的热键、对应的敌人和当前控制器
newHotkeyScript.SetupHotkey(choosenKey, collision.transform, this);
// 这里注释掉了将敌人添加到目标列表的代码,可能需要根据实际情况调整
// targets.Add(collision.transform);
}
/// <summary>
/// 将敌人添加到被捕获的敌人列表中
/// </summary>
/// <param name="_myEnemy">敌人的 Transform 组件</param>
public void AddEnemyToList(Transform _myEnemy) => targets.Add(_myEnemy);
}
4,Blackhole_Hotkey_Controller.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
// 黑洞热键控制器类,负责管理显示在敌人上方的热键提示的逻辑
public class Blackhole_Hotkey_Controller : MonoBehaviour
{
// 热键提示文本的精灵渲染器,用于控制热键提示的显示与隐藏
private SpriteRenderer sr;
// 当前热键对应的按键代码,用于检测玩家是否按下该热键
private KeyCode myHotkey;
// 显示热键文本的 TextMeshProUGUI 组件,用于显示具体的热键字符
private TextMeshProUGUI myText;
// 关联的敌人的 Transform 组件,用于确定热键提示的位置
private Transform myEnemy;
// 黑洞技能控制器,用于将敌人添加到被捕获的敌人列表中
private Blackhole_Skill_Controller blackHole;
/// <summary>
/// 设置热键提示的相关信息
/// </summary>
/// <param name="_myNewHotkey">新的热键按键代码</param>
/// <param name="_myEnemy">关联的敌人的 Transform 组件</param>
/// <param name="_myBlackHole">黑洞技能控制器</param>
public void SetupHotkey(KeyCode _myNewHotkey, Transform _myEnemy, Blackhole_Skill_Controller _myBlackHole)
{
// 获取当前对象的 SpriteRenderer 组件,用于后续控制热键提示的显示
sr = GetComponent<SpriteRenderer>();
// 获取当前对象子物体中的 TextMeshProUGUI 组件,用于显示热键文本
myText = GetComponentInChildren<TextMeshProUGUI>();
// 记录关联的敌人的 Transform 组件
myEnemy = _myEnemy;
// 记录黑洞技能控制器
blackHole = _myBlackHole;
// 记录当前热键对应的按键代码
myHotkey = _myNewHotkey;
// 将热键对应的按键代码转换为字符串并显示在文本组件上
myText.text = _myNewHotkey.ToString();
}
private void Update()
{
// 检测玩家是否按下了当前热键
if (Input.GetKeyDown(myHotkey))
{
// 将关联的敌人添加到黑洞技能控制器的被捕获敌人列表中
blackHole.AddEnemyToList(myEnemy);
// 将热键文本的颜色设置为透明,使其不可见
myText.color = Color.clear;
// 将热键提示的精灵颜色设置为透明,使其不可见
sr.color = Color.clear;
}
}
}
5,Blackhole_Skill.CS
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 黑洞技能类,继承自 Skill 基类,负责黑洞技能的具体逻辑
public class Blackhole_Skill : Skill
{
// 克隆体攻击的数量
[SerializeField] private int amountOfAttacks;
// 克隆体攻击的冷却时间
[SerializeField] private float cloneCooldown;
// 黑洞的持续时间
[SerializeField] private float blackholeDuration;
// 用于在 Inspector 面板中添加一个空白间隔,增强可读性
[Space]
// 黑洞预制件,用于实例化黑洞对象
[SerializeField] private GameObject blackHolePrefab;
// 黑洞的最大尺寸
[SerializeField] private float maxSize;
// 黑洞的增长速度
[SerializeField] private float growSpeed;
// 黑洞的缩小速度
[SerializeField] private float shrinkSpeed;
// 当前激活的黑洞控制器,用于管理黑洞的各种行为
Blackhole_Skill_Controller currentBlachole;
/// <summary>
/// 检查是否可以使用黑洞技能
/// </summary>
/// <returns>如果可以使用技能,返回 true;否则返回 false</returns>
public override bool CanUseSkill()
{
// 调用基类的 CanUseSkill 方法进行基本的技能可用性检查
return base.CanUseSkill();
}
/// <summary>
/// 使用黑洞技能
/// </summary>
public override void UseSkill()
{
// 调用基类的 UseSkill 方法执行通用的技能使用逻辑
base.UseSkill();
// 在玩家当前位置实例化黑洞预制件
GameObject newBlackHole = Instantiate(blackHolePrefab, player.transform.position, Quaternion.identity);
// 获取新创建黑洞对象的黑洞技能控制器组件
currentBlachole = newBlackHole.GetComponent<Blackhole_Skill_Controller>();
// 设置黑洞的相关参数,如最大尺寸、增长速度、缩小速度、克隆体攻击数量、克隆体攻击冷却时间和黑洞持续时间
currentBlachole.SetupBlackhole(maxSize, growSpeed, shrinkSpeed, amountOfAttacks, cloneCooldown, blackholeDuration);
}
/// <summary>
/// 在脚本实例被加载时调用,用于初始化操作
/// </summary>
protected override void Start()
{
// 调用基类的 Start 方法执行通用的初始化逻辑
base.Start();
}
/// <summary>
/// 每帧调用一次,用于更新逻辑
/// </summary>
protected override void Update()
{
// 调用基类的 Update 方法执行通用的更新逻辑
base.Update();
}
/// <summary>
/// 检查黑洞技能是否完成
/// </summary>
/// <returns>如果技能完成,返回 true;否则返回 false</returns>
public bool SkillCompleted()
{
// 如果当前没有激活的黑洞控制器,返回 false
if (!currentBlachole)
return false;
// 如果当前黑洞控制器允许玩家退出状态,说明技能完成
if (currentBlachole.playerCanExitState)
{
// 将当前黑洞控制器置为 null,表示技能已结束
currentBlachole = null;
return true;
}
// 否则,技能未完成,返回 false
return false;
}
}
6,PlayerBlackholeState .cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 玩家黑洞状态类,继承自 PlayerState 类,用于处理玩家处于黑洞技能状态时的逻辑
public class PlayerBlackholeState : PlayerState
{
// 玩家飞行的持续时间,单位为秒
private float flyTime = .4f;
// 标记黑洞技能是否已经使用
private bool skillUsed;
// 玩家刚体的初始重力缩放值,用于在状态结束后恢复重力
private float defaultGravity;
/// <summary>
/// 构造函数,初始化玩家、状态机和动画布尔参数名
/// </summary>
/// <param name="_player">玩家对象</param>
/// <param name="_stateMachine">玩家状态机</param>
/// <param name="_animBooIName">动画布尔参数名</param>
public PlayerBlackholeState(Player _player, PlayerStateMachine _stateMachine, string _animBooIName) : base(_player, _stateMachine, _animBooIName)
{
}
/// <summary>
/// 动画结束触发事件,调用基类的同名方法
/// </summary>
public override void AnimationFinshTrigger()
{
base.AnimationFinshTrigger();
}
/// <summary>
/// 进入玩家黑洞状态时调用,进行状态初始化操作
/// </summary>
public override void Enter()
{
// 调用基类的 Enter 方法执行通用的进入状态逻辑
base.Enter();
// 记录玩家刚体的初始重力缩放值
defaultGravity = player.rb.gravityScale;
// 标记黑洞技能尚未使用
skillUsed = false;
// 设置状态计时器为飞行时间,控制飞行持续时长
stateTimer = flyTime;
// 将玩家刚体的重力缩放值设置为 0,使玩家在飞行阶段不受重力影响
player.rb.gravityScale = 0;
}
/// <summary>
/// 退出玩家黑洞状态时调用,进行状态清理操作
/// </summary>
public override void Exit()
{
// 调用基类的 Exit 方法执行通用的退出状态逻辑
base.Exit();
// 恢复玩家刚体的初始重力缩放值
player.rb.gravityScale = defaultGravity;
// 使玩家恢复不透明状态
player.MakeTransprent(false);
}
/// <summary>
/// 每帧更新玩家黑洞状态的逻辑
/// </summary>
public override void Update()
{
// 调用基类的 Update 方法执行通用的更新逻辑
base.Update();
// 如果状态计时器大于 0,说明玩家处于飞行阶段
if (stateTimer > 0)
{
// 设置玩家刚体的速度,使其向上飞行
player.rb.velocity = new Vector2(0, 15);
}
// 如果状态计时器小于 0,说明飞行阶段结束
if (stateTimer < 0)
{
// 设置玩家刚体的速度,使其有一个轻微的向下速度
player.rb.velocity = new Vector2(0, -.1f);
// 如果黑洞技能尚未使用
if (!skillUsed)
{
// 检查黑洞技能是否可以使用
if (player.skill.blackhole.CanUseSkill())
{
// 使用黑洞技能,并标记技能已使用
player.skill.blackhole.CanUseSkill();
skillUsed = true;
}
}
}
// 检查黑洞技能是否已经完成
if (player.skill.blackhole.SkillCompleted())
{
// 如果技能完成,切换玩家状态到空气状态
stateMachine.ChangeState(player.airState);
}
}
}
注:记得在player1中实例化
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。