MEGALOVANIA MEGALOVANIA

游戏开发中

目录
CPKA开发日志 其二十二
/      

CPKA开发日志 其二十二

工作日志

  • 主要是继续完善了战斗部分

  • 首先优化了角色的攻击判定.虽然感觉更加精确的方式是用武器的碰撞盒来做判定,但是我的游戏并没有那么精确的碰撞需求,于是就直接取之前在 Timeline 里写的配置的方法.在激活碰撞体的时候做一次 OverlapSphere 检测.然后判断夹角是否在允许范围内.
  • 因此目前武器上是需要配置夹角范围的.

  • 目前还有个问题是,某些情况下角色寻路就是敌人位置(攻击敌人的寻路),这会导致两人一起飞天,效果巨搞笑.现在还没想到解决问题,但是应该是这里的问题.尝试解决了一下,没解决.
 1int selectIndex = -1;
 2
 3for (int i = 1; i < path.vectorPath.Count; i++)
 4{
 5    if (Vector3.Distance(path.vectorPath[i - 1], endPos) > attackDistance
 6        && Vector3.Distance(path.vectorPath[i], endPos) <= attackDistance)
 7    {
 8        break;
 9    }
10
11    selectIndex = i;
12}
13
14if (selectIndex != -1)
15{
16    endPos = path.vectorPath[selectIndex+1];
17    //尝试解决,但是并没有解决问题
18    if (Vector3.Distance(endPos, _targetActor.transform.position) < 0.1f)
19    {
20        endPos = (endPos + path.vectorPath[selectIndex]) / 2;
21    }
22}

  • 另外改了 RoundBattleMgr 的一些逻辑:思来想去,还是直接把当前场景里所有的角色加入战斗之中了.
  • 添加了一个震屏效果.简单通过 CinemachineImpluse 实现了这些功能.
  • 添加了一个定帧的效果.其实就是在 HitReact 的时候将攻击者和受攻击者都暂停动画一段时间,然后再 Resume.方法虽然简单粗暴,但是有效.
  • 添加了一个打击例子和打击音效.至少现在看起来的打击感像那么回事了.
  • 另外也解决了一些卡在某个 NPC 的 Bug,主要原因是当移动距离太近的时候,角色对应的 Tween 一直没有办法完成.
  • 接下来就是要写击退和快速反击的功能.
  • 思考了几个方案以后,最终还是决定用已经有的东西来做,也就是还是用 buff 系统来做.没有必要再新引入进来一个系统
  • 为武器添加了 buff 系统.现在的武器在使用的时候,能够给自己上特定的 buff,也能够为敌人上特定的 buff.这里把击退效果看做是给受击者上的一个 Buff.把快速反应看作是给自己上的一个 Buff.
  • 击退效果开始发现计算角度的时候需要知道攻击者和受攻击者的位置.因此把原来 Add 回调中的 ActorBattleMgr 改成了 Buff(buff 中有 caster 和 carrier).另外发现自己之前复制 AddBuff 到 Buff 的时候写错了.
  • 击退效果开始用 DOTween,但是后来发现会穿过墙体.因此最后换成用赋 RigidBody 速度的方式并且 FreezeRotation 来做了.
  • 击退效果看起来很好,能强化打击感
  • 快速反应的思路是,当角色攻击之后,会自动添加这个 Buff.然后这种情况下,会为 Actor 添加一个防护罩的 gameobject.在 gameobject 的 update 里循环检测是否有新的碰撞体角色进入.有的话则反击.当然还有一些判断条件,这里把代码贴出来.
  • 快速反应还有个问题就是,如果敌人在移动过程中触发了快速反应.那么需要把敌人的行动暂停.这里简单在 ActionMgr 中写了一个清理方法.把当前的 Action 强制标记为完成,并且清理掉队列中的其他 Action.
  • 强制标记为完成其实只需要一个变量 isComplete,大概是下面这样代码的思路:
1public override async UniTask Execute(Action<ActorAction> callback = null)
2{
3    handler.transform.parent.rotation = rotation;
4    handler.PerformAttack(this);
5
6    ///这里的Complete用来强行结束掉这个Action,正常是不会这么用的
7    await UniTask.WaitUntil(()=>handler._animMgr.GetCurrentMontageTime()>=1.0f || isComplete) ;
8}
  • 不过不知道为啥,这种情况下,赋予 Rigbody 速度的方式就不能击退了.但是无所谓
  • 可以看出来 UpdateAsObservable 其实解决了很多问题.然后结束之后 Destroy 也可以保证一定会被销毁.
 1[Title("每回合最多响应几次快速反应")][Range(0,10.0f)][SerializeField] public int maxCountPerRound;
 2
 3public override void OnAddedBuff(BuffBase buff)
 4{
 5    float range = buff.carrier.GetComponentInParent<ActorMgr>().GetCurrentWeapon().range;
 6
 7    var go = Instantiate<GameObject>(Resources.Load<GameObject>("Prefab/shield_sphere"), buff.carrier.transform);
 8    go.transform.position = buff.carrier.transform.position;
 9    go.transform.localScale = 2.0f*range*Vector3.one;
10    go.name = "shield_sphere";
11
12    var goRd = go.GetComponent<MeshRenderer>();
13
14    goRd.enabled = false;
15
16    int curRoundCount = 1;
17  
18   var mgr = buff.carrier.GetRoundBattleMgr();
19   
20   curRoundCount = maxCountPerRound;
21
22   go.UpdateAsObservable().Subscribe((t) =>
23   {
24       Debug.Log($"QuickReaction:curRoundCount:{curRoundCount}");
25       if (buff.carrier.GetComponentInParent<ActorMgr>().IsPlayerTurn())
26       {
27           curRoundCount = maxCountPerRound;
28           goRd.enabled = false;
29           return;
30       }
31     
32       // Debug.Log("QuickReaction:2");
33
34       if (curRoundCount <= 0)
35       {
36           goRd.enabled = false;
37           return;
38       }
39     
40       // Debug.Log("QuickReaction:3");
41
42       goRd.enabled = true;
43      
44        var result = Physics.OverlapSphere(buff.carrier.transform.position, range, LayerMask.GetMask("Character"));
45        foreach (var item in result)
46        {
47            if (item.GetComponent<ActorMgr>().GetActorCamp() !=
48                buff.carrier.GetComponentInParent<ActorMgr>().GetActorCamp() && !item.GetComponent<ActorMgr>().IsActorDead())
49            {
50                buff.carrier.transform.parent.LookAt(item.transform.position);
51                var stateMgr = buff.carrier.GetComponentInParent<ActorMgr>().GetActorStateMgr();
52                stateMgr.TryPerformState(stateMgr.GetStateByName("attack"));
53                curRoundCount--;
54                break;
55            }
56        }
57   }).AddTo(go);
58   
59}
60
61public override void OnRemoved(ActorBattleMgr handler)
62{
63    Destroy( handler.transform.Find("shield_sphere").gameObject);
64}
  • 添加了在战斗结束之后 Battler 主动移除自己身上某些 Tag 的 Buff 的功能.目前是有 battle 这个 Tag 的 Buff 都会被移除
  • 修复了一些其他的 bug.比如角色死亡以后仍然会被选中为目标,行动之类的.
  • 下面是现在的效果

优化事项

  • 战斗的效果可以更好,比如打击感和移动的动画可以再优化一下.
  • 应该提前显示攻击范围
  • 当快速反应触发的时候.应该有一些特写提示
  • 角色的寻路应该再做改进,不应该穿越角色

其他事项

  • 上午的工作真的很重要.上午工作时间拉满一点能给后面留很多空间,即便是有事情或者是想休息了也问题不大.一日之计在于晨.
  • 生物钟现在终于正常了.前天只睡了 4 个小时(1 点-5 点),今天 11 点就睡了,一觉睡到早上 7 点半,很满足.

今日目标

  • 构造新的战斗模式,抄袭一下博德之门还有其他模式,比如远程武器法术,坠落,倒地等等
  • 开始构造具体的 Timeline 和战斗设计
  • 构建 Buff 系统

标题:CPKA开发日志 其二十二
作者:matengli110
地址:https://www.sunsgo.world/articles/2024/04/15/1713143851755.html