3DRPG游戏开发核心功能04-数值文件和保存数据
主要技术:Scripts Object 数值文件,角色升级系统,JSON数据保存
Scripts Object 数值文件
CharacterData 人物数值
生命数值
在菜单中创建数值文件类型
[CreateAssetMenu(fileName ="New Data", menuName = "Character Stats/Data")]
生命基础数值类型(玩家和敌人各一个)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[ ]
public class CharacterData_SO : ScriptableObject
{
[ ]
// 最大血量
public int maxHealth;
// 当前血量
public int currentHealth;
// 基础防御
public int baseDefence;
// 当前防御
public int currentDefence;
[ ]
public int killPoint;
}读取数据类型:用属性的方法读写给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
public class CharacterStates : MonoBehaviour
{
public CharacterData_SO characterData;
public AttackData_SO attackData;
// 可读 可写
// 最大生命值
public int MaxHealth
{
get { if (characterData != null) return characterData.maxHealth; else return 0; }
set { characterData.maxHealth = value; }
}
// 当前生命值
public int CurrentHealth
{
get{ if (characterData != null) return characterData.currentHealth; else return 0; }
set{ characterData.currentHealth = value; }
}
// 基础防御力
public int BaseDefence
{
get{if (characterData != null) return characterData.baseDefence; else return 0; }
set{ characterData.baseDefence = value; }
}
// 当前防御力
public int CurrentDefence
{
get{ if (characterData != null) return characterData.currentDefence; else return 0; }
set{ characterData.currentDefence = value; }
}
}使用
1
2
3
4
5
6
7
8
9
10
11
12
public class PlayerController : MonoBehaviour
{
private CharacterStates characterStates;
void Awake()
{
characterStates = GetComponent<CharacterStates>();
}
void Start()
{
characterStates.MaxHealth = 2;
}
攻击数值
在菜单创建攻击数值模板
[CreateAssetMenu(fileName = "New Attack", menuName = "Attack/Attack Data")]
攻击数值类型(玩家和敌人各一个)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[ ]
public class AttackData_SO : ScriptableObject
{
//攻击距离
public float attackRange;
//远程距离
public float skillRange;
//冷却时间
public float coolDown;
//最小攻击值
public float minDange;
// 最大攻击值
public float maxDamage;
// 暴击
public float criticalMultiplier;
//暴击率
public float criticalChance;
}使用
characterStates.attackData.attackRange
1
2
3
4
5
6
7
//修改攻击范围参数,持续不断循环>攻击范围,武器长度
while (Vector3.Distance(attackTarget.transform.position, transform.position) > characterStates.attackData.attackRange)
{
agent.destination = attackTarget.transform.position; // 点击目标
yield return null;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 近战
bool TargetInAttackRange()
{
if (attackTarget != null)
return Vector3.Distance(attackTarget.transform.position, transform.position) <= characterStates.attackData.attackRange;
else
return false;
}
// 远程
bool TargetInSkillRange()
{
if (attackTarget != null)
return Vector3.Distance(attackTarget.transform.position, transform.position) <= characterStates.attackData.skillRange;
else
return false;
}
攻击效果计算
伤害计算:
攻击 - 防御
出现暴击就*暴击百分比
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
// 受伤计算方式
public void TakeDamage(CharacterStates attacker, CharacterStates defener) // 两个Character类型的参数
{
// 攻击者的攻击-受攻击的防御 防御可能高于其攻击,最小为0
int damage = Math.Max(attacker.CurrentDamage() - defener.CurrentDefence, 0);
// 血量最低为0
CurrentHealth = Math.Max(CurrentHealth - damage, 0);
// 暴击
if (attacker.isCritical)
{
defener.GetComponent<Animator>().SetTrigger("Hit");
}
}
// 函数重载 直接写即可
public void TakeDamage(int damage, CharacterStates defener)
{
int currentdamage = Mathf.Max(damage - defener.CurrentDefence, 0);
CurrentHealth = Mathf.Max(CurrentHealth - currentdamage, 0);
}
private int CurrentDamage()
{
float coreDamage = UnityEngine.Random.Range(attackData.minDange, attackData.maxDamage);
if (isCritical)
{
coreDamage *= attackData.criticalMultiplier;
Debug.Log("暴击!" + coreDamage);
}
return (int)coreDamage;
}
动画关键帧添加事件
即动画在执行该关键帧时触发事件,事件中的n个函数执行,产生效果
1 | void Hit() |
升级系统
- 数值参数里面添加
1 |
|
- 调用
1 |
|
保存数据
JSON 类型变成 String 保存 SetString
- object 基类
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 五里霧中!