入职以来一直很想实现一个技能编辑器,在积累了一些经验以后,决定利用ScriptableObject开发一个,在此记录
1.简单的需求分析
在游戏开发中,技能系统是一个至关重要的组成部分。技能决定了游戏角色可以执行的各种动作,例如攻击、治疗、移动等。通常,技能由多个元素组成,包括技能效果(Effect)、技能触发条件(triggerr)、技能冷却时间(Cooldown)等。为了更好地管理和调整这些技能,我们需要一个可视化的编辑器。
2.粗略的实现哪些功能
Buff 类似计时器功能 startscript endscript delaytime(开始延时时间) lasttime(buff持续时间-1为永久) TrickTime(脚本执行间隔) TrickScript(持续时间内按间隔时间刷新执行的脚本)
Trigger 一些事件触发 触发条件 判断是否执行后续脚本 触发后执行的脚本,要在特定位置埋下事件
Effect 生成bullet 执行Script (设计一个skillbyEffect 凭此释放技能可以让怪物NPC靠Buff释放技能)
Bullet 子弹 子弹形态 链接track
Skill 技能应该具有各种属性,包括伤害、冷却时间、目标、范围等。编辑器需要允许用户定义这些属性,并且能够将 Effect、Buff 和 Bullet 与技能关联。
3.ScriptableObject的意义
可以创建多个不同类型的ScriptableObject,例如Skill、Buff、Effect、Bullet等,以满足不同的需求。
ScriptableObject的数据是独立的,它们不依赖于特定的场景或游戏对象。这使得技能可以轻松地跨不同场景和游戏对象共享和重用。
脚本化操作:可以通过脚本在运行时创建、修改和管理ScriptableObject。
例如
using UnityEngine;
using UnityEngine.Events;
[CreateAssetMenu(fileName = "New Skill", menuName = "Skill System/Skill")]
public class SkillSo : ScriptableObject
{
[SerializeField]
public SkillType skillType;
[SerializeField]
public AttackType attackType;
[SerializeField]
public float spiritCost;
[SerializeField]
public float damageRatio;
[SerializeField]
public float skillCD;
public float lifeTime;
public Vector3 direction;
public float speed;
public float damage = 1f;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
[CreateAssetMenu(fileName = “New Skill”, menuName = “Skill System/Skill”)] 是一个特性(Attribute),用于在Unity编辑器中创建新的技能资产(Asset)。它指定了在Unity项目中创建新技能时的默认文件名和菜单路径。这使得在Unity编辑器中可以右键点击创建新技能,并将其保存为一个ScriptableObject。
下面一系列的 public 字段是用来存储技能的各种属性和参数。这些字段包括:
skillType:技能的类型,可能是一个自定义枚举类型 SkillType。
attackType:技能的攻击类型,可能是一个自定义枚举类型 AttackType。
spiritCost:使用技能所需的精力消耗。
damageRatio:技能的伤害比率。
skillCD:技能的冷却时间。
lifeTime:技能在游戏中存在的时间。
direction:技能的方向。
speed:技能的速度。
damage:技能的伤害值,默认为1。
后续我可能会扩展它和SkillType的枚举
在编写这段代码后即可右键创建so文件
using System;
// 技能类型枚举
public enum SkillType
{
MeteorSword, // 陨剑术
SkySword, // 天剑
SpeedBuff, // 速度增益
SwordRain, // 剑雨
WaterDrawSword, // 提水剑
None // 无
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
一个简单的skillType枚举
然后设计一个skill基类去读取和利用其中的信息
public abstract class SkillBase : MonoBehaviour
{
public SkillSo so;
public SkillType GetSkillType()
{
return so.skillType;
}
public AttackType GetAttackType()
{
return so.attackType;
}
public float SpiritCost()
{
return so.spiritCost;
}
public float DamageRatio()
{
return so.damageRatio;
}
public float SkillCD()
{
return so.skillCD;
}
protected void Awake()
{
so.sr = base.GetComponentInChildren<SpriteRenderer>();
}
protected virtual void SkillFinish()
{
UnityEngine.Object.Destroy(base.gameObject);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
后续应该在skillbase写一些逻辑去处理,例如对外提供skill图标让UImanager加载,对碰撞或范围内的敌人造成伤害。
在贴一个attackType
using System;
// 攻击类型枚举
public enum AttackType
{
Metal, // 金
Wood, // 木
Water, // 水
Fire, // 火
Earth, // 土
Thunder, // 雷
Sword, // 剑
None // 无
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
然后我会设计palyerManager去读取预制体身上实例的SkillSo文件进行相应的处理
今天就先分享到这,管他能不能用,先写了再说
评论记录:
回复评论: