升级角色

时间:2019-08-05 12:36:37

标签: c# unity3d

我有一些脚本,这些脚本分为播放器和播放器下面的游戏对象。这些脚本包括准确性,玩家速度和弹丸伤害。

我创建了一个菜单,玩家(与NPC互动时)可以购买某些升级产品,以在整个游戏中增加这些价值。

现在我想知道,将所有这些脚本转换为1个脚本并对其进行访问是否更好?还是让它在脚本之间划分并单独调用它们更好?

由于这是我第一次升级玩家数据,因此欢迎您提供任何帮助!

让我们从最大运行速度的播放器脚本开始。

public class Player : Actor {

    public int playerNumber = 1;

    // Run Speed & Acceleration
    public float MaxRun = 90f; // Maximun Horizontal Run Speed
    public float RunAccel = 1000f; // Horizontal Acceleration Speed
    public float RunReduce = 400f; // Horizontal Acceleration when you're already when your horizontal speed is higher or equal to the maximum

我拥有的第二个脚本是在武器本身中,我具有武器的准确性。


public class Weapon : MonoBehaviour {

    protected float currentAngle = 0f;
    public float randomAngle = 20;


最后一个脚本是我放置伤害的地方。由于损坏在弹丸之内,因此我将所有内容都放入了弹丸脚本中。


//[RequireComponent (typeof(Rigidbody2D))]
public class Projectile : MonoBehaviour {

    [Header ("Speed")]
    public float baseSpeed;
    public float randomSpeed;
    public Vector2 SpeedV2;
    public Vector2 Direction;

    [Header ("Damage")]
    public int DamageOnHit;

为了将所有内容都放入我的“升级”菜单中,我制作了一个脚本,调用了不同的脚本。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UpgradeMenu : MonoBehaviour
{
    [SerializeField]
    private Text accuracyText;

    [SerializeField]
    private Text speedText;

    [SerializeField]
    private Text damageText;

    [SerializeField]
    private float accuracyMultiplier = 0.7f;

    private Weapon weapon;
    private Projectile projectile;
    private Player player;

    void OnEnable()
    {
        UpdateValues();
    }

    void UpdateValues ()
    {
      accuracyText.text = weapon.randomAngle.ToString();
      damageText.text = projectile.DamageOnHit.ToString();
      speedText.text = player.MaxRun.ToString();

    }

    public void UpgradeAccuracy ()
    {
      weapon.randomAngle = (int)weapon.randomAngle * accuracyMultiplier;
      UpdateValues();
    }

    public void UpgradeDamage ()
    {
      projectile.DamageOnHit = (int)projectile.DamageOnHit + 1;
      UpdateValues();
    }
}

我很确定我试图在UpgradeMenu脚本中调用其他脚本的方式是错误的。因此,如果有人能够提供帮助,那就太好了!

您可以看到机枪是玩家的子弹。因为您能够拿起该物品。这已经引起了枪支问题。由于我可以在Unity内更改此值,但是当我拿起另一把机枪时,该值将恢复为通常的4值。

Random Angle

除此之外,我还有一个具有onclick值的按钮。这个想法是,当玩家单击此按钮(仍然需要更改UI)时,应该使用此UpgradeMenu脚本来更改值。

Random Angle

现在按钮可以正常工作,唯一的问题是升级功能“未设置为对象的实例”

Random Angle

2 个答案:

答案 0 :(得分:1)

您应该区分配置数据逻辑数据

  • 配置数据不变。例如武器杂志的大小。
  • 逻辑数据确实发生了变化。例如杂志上的子弹。

逻辑数据是唯一的,仅存在于某些对象实例中,而配置数据存在于数据库中并由id标识。

以下仅是演示此想法的示例代码。

数据:

public class WeaponData
{
    public string id;
    public float spread;
    public string projectileId;
}

public class ProjectileData
{
    public string id;
    public int damage;
    public string prefabPath;
}

图书馆:

public static class Library
{
    public static Dictionary<string, WeaponData> Weapons;
    public static Dictionary<string, ProjectileData> Projectiles;
    // add more ...
}

配置设置:

WeaponData weapon = new WeaponData
{
    id = "shotgun",
    spread = 20f,
    projectileId = "shotgun_shell"
};

ProjectileData projectile = new ProjectileData
{
    id = "shotgun_shell",
    damage = 100,
    prefabPath = "Projectiles/ShotgunShell"
};

Library.Weapons.Add(weapon.id, weapon);
Library.Weapons.Add(projectile.id, projectile);

逻辑:

public class Weapon
{
    public WeaponData weapon = Library.Weapons["shotgun"];

    public void Shoot()
    {
        GameObject.Instantiate(
            Resources.Load<Projectile>(Library.Projectiles[weapon.projectileId].prefabPath)
        );
    }
}

要使升级系统正常工作,您可以设置多种武器:

"shotgun_v1"-> "shotgun_v2"-> "shotgun_v3"


注意:另一种方法是使用ScriptableObjects,即如果您想在Unity编辑器中序列化数据。在该主题上酷video

答案 1 :(得分:0)

我相信您的问题出在您要在不是静态属性的类类型上设置randomAngle的地方:

public void UpgradeAccuracy ()
{
  Weapon.randomAngle = (int)Weapon.randomAngle * accuracyMultiplier;
  UpdateValues();
}

这里的Weapon是什么?只是一个类名,您无法设置或获取这些东西,因为它没有实例化。我相信您想做的是:

public void UpgradeAccuracy ()
{
  angle.randomAngle = (int)angle.randomAngle * accuracyMultiplier;
  UpdateValues();
}

除此之外,您所做的可能并没有多大错误。可能不是我选择的体系结构,但我还没有看完您的整个游戏,因此可能有您选择的理由。未来的提示是,并非所有内容都必须是组件(源自MonoBehaviour),如果不需要组件行为,则在Unity中创建游戏时也可以使用“普通”类。我通常会尝试保持尽可能少的MonoBehaviour组件脚本。