[Unity] 战斗系统学习 5:构建 TPS 框架 1

本文介绍了在Unity中构建第三人称射击(TPS)游戏框架的过程,重点讨论了Scriptable Objects在角色属性中的应用,InputController的进化,以及如何处理冲刺和瞄准等战斗机制。通过多次迭代,作者分享了在使用FlowCanvas时遇到的挑战以及解决方案,强调了游戏逻辑和UI反馈的重要性。

[Unity] ACT 战斗系统学习 4:重构前的第三人称控制器

以前看猴与花果山的文章,感觉大开眼界,但是没做过所以没更多体会
https://zhuanlan.zhihu.com/p/416805924
现在我才发现这真的是网上能找到的最详细的实现思路了
我犯的错误刚好就是没有想着流程,其实属性不需要流程,一个 OnChange 就行了,属性是别的流程的改变的结果,我们不是直接改变流程

说实话 FlowCanvas 学起来好麻烦
做成想要的样子也有点麻烦
为了让底层逻辑适应 FlowCanvas,还要修改底层逻辑,也好麻烦
但是毕竟策划最大……

1. Scriptable 用于角色属性

我有一段时间在纠结的就是,我到底什么时候应该用 scriptable ……因为感觉创建素材太多了很会乱
虽然直觉上他们是用在单个例子中的,需要多次引用的地方
但是我在想,对于需要动态生成的敌人,就不能要求他们都有对应的 scriptableobject 了……
这样的话,感觉框架在处理不同角色的时候行为会不一样,这容易发生一些混乱?

最初我还不知道什么东西是应该用来序列化的
然后我就列了这些

在这里插入图片描述

然后当我重构的时候我就发现,为了能够在监视器中配置 scriptableobject 我必须要把这个使用 scriptableobject 的脚本做成 mono
那么既然已经做成了 mono,那其实有些变量已经可以在监视器上序列化了,我的初衷是为了序列化才基于 scriptableobject 重构的,但是我发现我要是改成 mono 也能实现一部分的序列化
这就有点令人迷茫

不过之后我觉得我应该想懂了,像是血量体力这种被大量引用的,关系到 UI 啊,声音 啊啥的,做成 scriptableobject 很合理,像是 IsSpring 这种状态的,其实也是要影响外部的,比如我想冲刺的时候也有 UI 和 声音的变化
但是像是 timeout cost 这种,他看上去像是状态,但是又其实没那么大可能被其他部件引用的,就不用了

理所当然的,其实 GameFramework 中的 EntityData 就没有必要了,还需要自己在 Excel 中填表,填了还要生成类……
直接写成一个 ScriptableObject 就好了

在这里插入图片描述

然后接下来我在重构的时候,写的时候我就感觉关于一些状态的也是没有必要的
因为这些状态其实是一个瞬时更新的东西,无论我保存或者不保存,我打开游戏的时候都会征程更新,比如 IsGround,我打开游戏之后立即更新,那么打开游戏之前的值就无关紧要了
至于霸体这种东西,确实要存,但是这应该存在一个 Buff 列表里面而不是一个简单的变量一面
霸体是 Buff 流程的结果,而不是一个 Bool 值

2. InputController

2.1 第一版

在这里插入图片描述

在这里插入图片描述

2.2 第二版

添加了控制接受输入的功能

在这里插入图片描述

2.3 第三版

为了控制输入清零,不能直接使用布尔值控制接受输入,而是应该使用调用函数的方法

在这里插入图片描述

Assets/MeowFramework/MeowACT/InputSystem/MeowACTInputController.cs

// ----------------------------------------------
// 作者: 廉价喵
// 创建于: 14/03/2022 9:54
// 最后一次修改于: 06/04/2022 16:39
// 版权所有: CheapMeowStudio
// 描述:
// ----------------------------------------------

using System;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.InputSystem;

namespace MeowFramework.MeowACT
{
   
   
	public class MeowACTInputController : SerializedMonoBehaviour
	{
   
   
		/// <summary>
		/// 是否接受运动输入
		/// </summary>
		[HorizontalGroup("MoveInput")]
		[HorizontalGroup("MoveInput/Left")]
		[ShowInInspector]
		[ReadOnly]
		[Tooltip("是否接受运动输入")]
		private bool CanMoveInput = true;
			
		/// <summary>
		/// 移动
		/// </summary>
		[HorizontalGroup("MoveInput/Right")]
		[LabelWidth(50)]
		[Tooltip("移动")]
		public Vector2 Move;
		
		/// <summary>
		/// 是否接受摄像机旋转输入
		/// </summary>
		[HorizontalGroup("LookInput")]
		[HorizontalGroup("LookInput/Left")]
		[ShowInInspector]
		[ReadOnly]
		[Tooltip("是否接受摄像机旋转输入")]
		private bool CanLookInput = true;
		
		/// <summary>
		/// 鼠标移动
		/// </summary>
		[HorizontalGroup("LookInput/Right")]
		[LabelWidth(50)]
		[Tooltip("鼠标移动")]
		public Vector2 Look;
		
		/// <summary>
		/// 是否接受冲刺输入
		/// </summary>
		[HorizontalGroup("SprintInput")]
		[HorizontalGroup("SprintInput/Left")]
		[ShowInInspector]
		[ReadOnly]
		[Tooltip("是否接受冲刺输入")]
		private bool CanSprintInput = true;
		
		/// <summary>
		/// 冲刺
		/// </summary>
		[HorizontalGroup("SprintInput/Right")]
		[LabelWidth(50)]
		[Tooltip("冲刺")]
		public bool Sprint;
		
		/// <summary>
		/// 是否接受冲刺输入
		/// </summary>
		[HorizontalGroup("AttackInput")]
		[HorizontalGroup("AttackInput/Left")]
		[ShowInInspector]
		[ReadOnly]
		[Tooltip("是否接受冲刺输入")]
		private bool CanAttackInput = true;
		
		/// <summary>
		/// 攻击
		/// </summary>
		[HorizontalGroup("AttackInput/Right")]
		[LabelWidth(50)]
		[Tooltip("攻击")]
		public bool Attack;
		
		/// <summary>
		/// 鼠标锁定
		/// </summary>
		[Tooltip("鼠标锁定")]
		public bool CursorLocked = true;

		/// <summary>
		/// 移动时触发的 Action
		/// </summary>
		[HideInInspector] 
		public Action<Vector2> OnMoveAction;

		/// <summary>
		/// 鼠标移动时,能够输入时触发的 Action
		/// </summary>
		[HideInInspector]
		public Action<Vector2> OnLookAction;

		/// <summary>
		/// 右键冲刺时触发的 Action
		/// </summary>
		[HideInInspector]
		public Action OnSprintAction;

		/// <summary>
		/// 左键攻击时触发的 Action
		/// </summary>
		[HideInInspector]
		public Action OnAttackAction;

		/// <summary>
		/// 应用窗口聚焦时触发的 Action
		/// </summary>
		[HideInInspector]
		public Action<bool> OnApplicationFocusAction;
		
		private void OnMove(InputValue value)
		{
   
   
			if (CanMoveInput)
			{
   
   
				Move = value.Get<Vector2>();
				OnMoveAction?.Invoke(Move);
			}
		}

		private void OnLook(InputValue value)
		{
   
   
			if (CanLookInput)
			{
   
   
				Look = value.Get<Vector2>();
				OnLookAction?.Invoke(Look);
			}
		}

		private void OnSprint(InputValue value)
		{
   
   
			if (CanSprintInput)
			{
   
   
				Sprint = value.isPressed;
				OnSprintAction?.Invoke();
			}
		}

		private void OnAttack(InputValue value)
		{
   
   
			if (CanAttackInput)
			{
   
   
				Attack = value.isPressed;
				OnAttackAction?.Invoke();
			}
		}

		private void OnApplicationFocus(bool hasFocus)
		{
   
   
			SetCursorState(hasFocus);
			CursorLocked = hasFocus;
			OnApplicationFocusAction?.Invoke(CursorLocked);
		}

		private void SetCursorState(bool newState)
		{
   
   
			Cursor.lockState = newState ? CursorLockMode.Locked : CursorLockMode.None;
		}

		public void EnableMoveInput(bool shouldEnable)
		{
   
   
			CanMoveInput = shouldEnable;
			// 注意清零
			Move = Vector2.zero;
		}
		
		public void EnableLookInput(bool shouldEnable)
		{
   
   
			CanLookInput = shouldEnable;
			// 注意清零
			Look = Vector2.zero;
		}
		
		public void EnableSprintInput(bool shouldEnable)
		{
   
   
			CanSprintInput = shouldEnable;
			// 注意清零
			Sprint = false;
		}
		
		public void EnableAttackInput(bool shouldEnable)
		{
   
   
			CanAttackInput = shouldEnable;
			// 注意清零
			Attack = false;
		}
	}
	
}

3. LocomotionController

3.1 第一版

在这里插入图片描述

3.2 第二版

将冲刺逻辑抽象为速度覆盖,使用速度覆盖逻辑替换冲刺+行走逻辑

在这里插入图片描述

Assets/MeowFramework/ThirdPerson/Scripts/ThirdPersonLocomotionController.cs

// ----------------------------------------------
// 作者: 廉价喵
// 创建于: 16/03/2022 16:53
// 最后一次修改于: 07/04/2022 6:27
// 版权所有: CheapMeowStudio
// 描述:
// ----------------------------------------------

using Cinemachine;
using MeowFramework.Core;
using MeowFramework.MeowACT;
using Sirenix.OdinInspector;
using UnityEngine;

namespace MeowFramework
{
   
   
	/// <summary>
	/// 第三人称运动控制器
	/// </summary>
    public class ThirdPersonLocomotionController : SerializedMonoBehaviour
    {
   
   
	    // 常量
	    
	    /// <summary>
	    /// 微量
	    /// </summary>
	    private const float Threshold = 0.01f;
	    
	    // 组件相关

	    /// <summary>
	    /// 角色控制器
	    /// </summary>
	    [BoxGroup(
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值