我觉得看视频太慢了,还是看别人源码更快……
1.664235822/DarkSouls-Demo
Github 源码:
https://github.com/664235822/DarkSouls-Demo
其中关于战斗的主要代码:
BattleManager.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CapsuleCollider))]
public class BattleManager : IActorManagerInterface
{
private void OnTriggerEnter(Collider other)
{
WeaponController targetController = other.GetComponentInParent<WeaponController>();
if (targetController == null) return;
GameObject attacker = targetController.weaponManager.actorManager.gameObject;
GameObject receiver = actorManager.actorController.model.gameObject;
bool attackValid = CheckAngleTarget(receiver, attacker, 45.0f);
bool counterValid = CheckAnglePlayer(receiver, attacker, 30.0f);
if (other.gameObject.layer == LayerMask.NameToLayer("Weapon"))
{
actorManager.TryDoDamage(targetController, attackValid, counterValid);
}
}
/// <summary>
/// 检查格挡
/// </summary>
/// <param name="player"></param>
/// <param name="target"></param>
/// <param name="playerAngle"></param>
/// <returns></returns>
public static bool CheckAnglePlayer(GameObject player, GameObject target, float playerAngle)
{
Vector3 counterDir = target.transform.position - player.transform.position;
float counterAngle = Vector3.Angle(player.transform.forward, counterDir);
float counterAngle2 = Vector3.Angle(target.transform.forward, player.transform.forward);
bool counterValid = (counterAngle < playerAngle && Mathf.Abs(counterAngle2 - 180.0f) < playerAngle);
return counterValid;
}
public static bool CheckAngleTarget(GameObject player, GameObject target, float targetAngle)
{
Vector3 attackingDir = player.transform.position - target.transform.position;
float attackingAngle = Vector3.Angle(target.transform.forward, attackingDir);
bool attackValid = (attackingAngle < targetAngle);
return attackValid;
}
}
ActorManager.cs
public class ActorManager : MonoBehaviour
{
public ActorController actorController;
public BattleManager battleManager;
public WeaponManager weaponManager;
public StateManager stateManager;
public DirectorManager directorManager;
public InteractionManager interactionManager;
public void TryDoDamage(WeaponController target, bool attackValid, bool counterValid)
{
// 如果自己正在无敌状态,那么目标不会受到伤害
if (stateManager.isImmortal)
{
}
// 如果自己允许使用 counter,并且该次攻击 counter 角度成立,那么目标进入被眩晕流程
else if (stateManager.isCounterBack && counterValid)
{
target.weaponManager.actorManager.Stunned();
}
// 如果自己正在防御,那么自己进入格挡流程
// counter 的优先级高于防御
else if (stateManager.isDefence)
{
Blocked();
}
// 以上情况均不成立,进入伤害判断
else
{
// 如果自己血量大于 0,并且攻击有效,那么可以对自己造成伤害
if (stateManager.HP > 0 && attackValid)
{
// 思考:这里是在武器伤害的部分检查死亡
// 等到流程多了之后,应该在别的地方判断死亡
// 比如在 HP 的 setter 的地方判断死亡
// 还有就是,之后应该将受到攻击的流程和死亡的流程不放在同一个逻辑层级里面
// 对自己造成伤害的值就是目标的武器的伤害值
stateManager.AddHP(-1 * target.WeaponData.ATK);
// 如果自己血量被扣除之后仍然大于 0,那么自己进入受攻击流程
if (stateManager.HP > 0)
{
// 进入被攻击流程
Hit();
}
// 如果自己血量被扣除之后小于 0,那么自己进入死亡流程
else
{
// 死亡流程
Die();
}
}
}
}
private void Blocked()
{
actorController.IssueTrigger("blocked");
}
private void Hit()
{
actorController.IssueTrigger("hit");
}
public void Stunned()
{
actorController.IssueTrigger("stunned");
}
public void SetIsCounterBack(bool value)
{
stateManager.isCounterBack = value;
}
private void Die()
{
actorController.IssueTrigger("die");
actorController.