我有一个基本的 damage/armor 系统,我想根据护甲的多少来减少传入的伤害
I have a basic damage/armor system and I want to reduce the incoming damage by how much the armor is
正如我在 title.I 中所说的那样,我希望通过我拥有的护甲数量来减少传入的伤害(例如伤害是 30,所以如果我做 1/3 * 护甲 = 一些数字)但我无法计算在我应该放的地方 this.Does 它需要在我的敌人脚本中,那里的伤害量正在形成?或者在我的 PlayerStats 脚本中,传入的伤害从我的健康中移除?
我的玩家脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
public class PlayerStats : MonoBehaviour
{
public int armor = 5;
public int currentLevel;
public int currentXP;
public int MaxLevel;
public int[] ExpToNextLevel;
public void SavePlayer(){
SaveSystem.SavePlayer(this);
}
public void LoadPlayer(){
PlayerData data = SaveSystem.loadPlayer();
currentLevel = data.level;
healthMax = data.MaxHealth;
attackDamage = data.Damage;
}
void Awake(){
currentLevel = 1;
currentXP = 0;
}
void Start(){
health = healthMax;
healthBar.SetMaxHealth(healthMax);
ExpToNextLevel = new int [MaxLevel+1];
ExpToNextLevel[1] = 15;
for(int i =2;i<MaxLevel;i++){
ExpToNextLevel[i] = Mathf.RoundToInt(ExpToNextLevel[i-1]*1.2f);
}
}
void Update(){
if(Time.time >= nextAttackTime){
if(Input.GetKeyDown(KeyCode.Mouse0)){
Attack();
nextAttackTime = Time.time +1f/attackRate;
}
}
FindObjectOfType<StatsUI>().UpdatePlayerStatus();
}
public void AddExp(int amount){
currentXP += amount;
if(currentXP >= ExpToNextLevel[currentLevel]){
LevelUp();
}
}
private void LevelUp(){
currentLevel++;
healthMax = Mathf.RoundToInt(healthMax * 1.2f);
attackDamage = Mathf.CeilToInt(attackDamage * 1.2f);
}
//HEALTH SYSTEM
public HealthBarSystem healthBar;
public event EventHandler OnHealthChanged;
public int health;
public int healthMax;
public void Damage(int damageAmount){
health -= damageAmount-1/3*armor;
healthBar.SetHealth(health);
if(health < 0) health =0;
if(OnHealthChanged != null) OnHealthChanged(this,EventArgs.Empty);
}
public void Heal(int healAmount){
health += healAmount;
healthBar.SetHealth(health);
if (health > healthMax)health = healthMax;
if(OnHealthChanged != null) OnHealthChanged(this,EventArgs.Empty);
}
void OnTriggerEnter2D(Collider2D collider){
if(collider.transform.tag=="Potion"){
Debug.Log("Your Halth has risen");
Heal(20);
}
}
public Transform AttackPoint;
public float AttackRange = 0.5f;
public LayerMask enemyLayers;
public Animator animator;
public int attackDamage = 10;
public float attackRate =2f;
float nextAttackTime = 0f;
void Attack(){
animator.SetTrigger("Attack");
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackPoint.position, AttackRange, enemyLayers);
foreach(Collider2D enemy in hitEnemies){
enemy.GetComponent<EnemyHealth>().TakeDamage(attackDamage);
Debug.Log("We hit"+ enemy.name);
}
}
void OnDrawGizmosSelected(){
Gizmos.DrawWireSphere(AttackPoint.position, AttackRange);
}
}
敌人脚本在这里:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemySlime : MonoBehaviour
{
private int armor;
bool IsDead = false;
private PlayerStats playerLevelSystem;
public int expToGive = 15;
public int damage;
public Animator animator;
public int speed;
[SerializeField]
Transform player;
[SerializeField]
float agroRange;
Rigidbody2D rb2d;
private int health;
void Awake(){
}
void Start(){
armor = GetComponent<PlayerStats>().armor;
health = GetComponent<EnemyHealth>().health;
playerLevelSystem = FindObjectOfType<PlayerStats>();
rb2d = GetComponent<Rigidbody2D>();
}
void Update(){
health = GetComponent<EnemyHealth>().health;
float distToPlayer = Vector2.Distance(transform.position, player.position);
if (transform.position.y > 0) {
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
}
if(distToPlayer < agroRange && health > 0){
transform.position = Vector2.MoveTowards(transform.position,player.position,speed*Time.deltaTime);
}
if (health <= 0){
rb2d.velocity = Vector3.zero;
}
if (health <= 0 && IsDead == false){
ExpToPlayer();
}
}
private void ExpToPlayer(){
playerLevelSystem.AddExp(expToGive);
Debug.Log("Xp Given");
IsDead = true;
}
void OnCollisionEnter2D(Collision2D col){
if(col.gameObject.tag == ("Player")){
col.gameObject.GetComponent<PlayerStats>().Damage(damage-((1/3)*armor));
}
}
}
我更喜欢将这个逻辑分成三个不同的接口:
public interface IWeapon {} //deals damage
public interface IArmor {} //reduces damage
public interface IBuff {} //modifies entire plot into something else, for example, swapping armor/damage, or identifiyng damage type, or deal/heal damage, or make some special effect like burning, frozen, chilled, etc. Or just specifying you fighting on EXTREME HARDCORE, thus reducing your armor to nothing.
然后我会定义接口来计算命中时发生的情况:
public interface IDamage {} //identifies what happens, it can deal zero damage and flip player upside down, froze him, or whatever.
public inteface IDamageSystem
{
IDamage Calculate(IWeapon weapon, IArmor armor, params IBuff[] buffs);
}
理想情况下,IWeapon/IArmor本身就是一个buff,所以可以省略,你只要通过一堆条件并相应地计算伤害。
那么像 apply 这样的东西应该出现在你的“健康”实体上,它最终只是修改实体的状态,没有别的:
public interface ILivingBeing
{
void ApplyDamage(IDamage damage);
}
正如我在 title.I 中所说的那样,我希望通过我拥有的护甲数量来减少传入的伤害(例如伤害是 30,所以如果我做 1/3 * 护甲 = 一些数字)但我无法计算在我应该放的地方 this.Does 它需要在我的敌人脚本中,那里的伤害量正在形成?或者在我的 PlayerStats 脚本中,传入的伤害从我的健康中移除? 我的玩家脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
public class PlayerStats : MonoBehaviour
{
public int armor = 5;
public int currentLevel;
public int currentXP;
public int MaxLevel;
public int[] ExpToNextLevel;
public void SavePlayer(){
SaveSystem.SavePlayer(this);
}
public void LoadPlayer(){
PlayerData data = SaveSystem.loadPlayer();
currentLevel = data.level;
healthMax = data.MaxHealth;
attackDamage = data.Damage;
}
void Awake(){
currentLevel = 1;
currentXP = 0;
}
void Start(){
health = healthMax;
healthBar.SetMaxHealth(healthMax);
ExpToNextLevel = new int [MaxLevel+1];
ExpToNextLevel[1] = 15;
for(int i =2;i<MaxLevel;i++){
ExpToNextLevel[i] = Mathf.RoundToInt(ExpToNextLevel[i-1]*1.2f);
}
}
void Update(){
if(Time.time >= nextAttackTime){
if(Input.GetKeyDown(KeyCode.Mouse0)){
Attack();
nextAttackTime = Time.time +1f/attackRate;
}
}
FindObjectOfType<StatsUI>().UpdatePlayerStatus();
}
public void AddExp(int amount){
currentXP += amount;
if(currentXP >= ExpToNextLevel[currentLevel]){
LevelUp();
}
}
private void LevelUp(){
currentLevel++;
healthMax = Mathf.RoundToInt(healthMax * 1.2f);
attackDamage = Mathf.CeilToInt(attackDamage * 1.2f);
}
//HEALTH SYSTEM
public HealthBarSystem healthBar;
public event EventHandler OnHealthChanged;
public int health;
public int healthMax;
public void Damage(int damageAmount){
health -= damageAmount-1/3*armor;
healthBar.SetHealth(health);
if(health < 0) health =0;
if(OnHealthChanged != null) OnHealthChanged(this,EventArgs.Empty);
}
public void Heal(int healAmount){
health += healAmount;
healthBar.SetHealth(health);
if (health > healthMax)health = healthMax;
if(OnHealthChanged != null) OnHealthChanged(this,EventArgs.Empty);
}
void OnTriggerEnter2D(Collider2D collider){
if(collider.transform.tag=="Potion"){
Debug.Log("Your Halth has risen");
Heal(20);
}
}
public Transform AttackPoint;
public float AttackRange = 0.5f;
public LayerMask enemyLayers;
public Animator animator;
public int attackDamage = 10;
public float attackRate =2f;
float nextAttackTime = 0f;
void Attack(){
animator.SetTrigger("Attack");
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackPoint.position, AttackRange, enemyLayers);
foreach(Collider2D enemy in hitEnemies){
enemy.GetComponent<EnemyHealth>().TakeDamage(attackDamage);
Debug.Log("We hit"+ enemy.name);
}
}
void OnDrawGizmosSelected(){
Gizmos.DrawWireSphere(AttackPoint.position, AttackRange);
}
}
敌人脚本在这里:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemySlime : MonoBehaviour
{
private int armor;
bool IsDead = false;
private PlayerStats playerLevelSystem;
public int expToGive = 15;
public int damage;
public Animator animator;
public int speed;
[SerializeField]
Transform player;
[SerializeField]
float agroRange;
Rigidbody2D rb2d;
private int health;
void Awake(){
}
void Start(){
armor = GetComponent<PlayerStats>().armor;
health = GetComponent<EnemyHealth>().health;
playerLevelSystem = FindObjectOfType<PlayerStats>();
rb2d = GetComponent<Rigidbody2D>();
}
void Update(){
health = GetComponent<EnemyHealth>().health;
float distToPlayer = Vector2.Distance(transform.position, player.position);
if (transform.position.y > 0) {
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
}
if(distToPlayer < agroRange && health > 0){
transform.position = Vector2.MoveTowards(transform.position,player.position,speed*Time.deltaTime);
}
if (health <= 0){
rb2d.velocity = Vector3.zero;
}
if (health <= 0 && IsDead == false){
ExpToPlayer();
}
}
private void ExpToPlayer(){
playerLevelSystem.AddExp(expToGive);
Debug.Log("Xp Given");
IsDead = true;
}
void OnCollisionEnter2D(Collision2D col){
if(col.gameObject.tag == ("Player")){
col.gameObject.GetComponent<PlayerStats>().Damage(damage-((1/3)*armor));
}
}
}
我更喜欢将这个逻辑分成三个不同的接口:
public interface IWeapon {} //deals damage
public interface IArmor {} //reduces damage
public interface IBuff {} //modifies entire plot into something else, for example, swapping armor/damage, or identifiyng damage type, or deal/heal damage, or make some special effect like burning, frozen, chilled, etc. Or just specifying you fighting on EXTREME HARDCORE, thus reducing your armor to nothing.
然后我会定义接口来计算命中时发生的情况:
public interface IDamage {} //identifies what happens, it can deal zero damage and flip player upside down, froze him, or whatever.
public inteface IDamageSystem
{
IDamage Calculate(IWeapon weapon, IArmor armor, params IBuff[] buffs);
}
理想情况下,IWeapon/IArmor本身就是一个buff,所以可以省略,你只要通过一堆条件并相应地计算伤害。
那么像 apply 这样的东西应该出现在你的“健康”实体上,它最终只是修改实体的状态,没有别的:
public interface ILivingBeing
{
void ApplyDamage(IDamage damage);
}