如何正确地将多个脚本添加到GameObject

时间:2019-03-31 16:58:38

标签: c# unity3d

我的团结项目正在发展,我有些害怕。

我创建了一个Player,该Player具有大量可以协同工作的脚本。 (最近会更大。) 看起来就是这样。

enter image description here

播放器组成的所有脚本都继承自基本脚本,该脚本仅包含一些受保护的静态变量,可以从所有其他脚本中更改这些静态变量,因此我可以从任何单个脚本检查播放器的任何状态。

其中一些:

public class BasicCharacter : MonoBehaviour
{
    protected static Rigidbody2D rb2d;
    protected static CharacterRenderer characterRenderer;
    protected static Vector2 directionLookingAt;
    protected static Vector2 movement;
    protected static Vector2 attackPos;

    protected static bool hasDashedAttack = false;
    protected static bool hasFinalizerAttack = false;
    protected static bool isUsingMovementSkills = false;
    protected static bool isStringingAttacks = false;
    ...

这是我如何调用某些变量作为执行其他一些操作的条件的示例:

private GameObject GetAttackAnimation()
    {
        if(hasFinalizerAttack)
        {
            return empoweredAttackVFX;
        }
        else if (hasDashedAttack)
        {
            return dashedAttackVFX;
        }
        else if (isAttackCharged)
        {
            return chargedAttackVFX;
        }
        return basicAttackVFX;
    }

我担心的是,我觉得自己在这里做得并不干净。我认为这是面对这一问题的更好方法。在我的代码中,在引入新的游戏机制之前,我必须记住玩家可能处于的每个可能状态。

我有几个问题:

我需要一个PlayerManager来跟踪可能的行为吗?

有没有一种方法可以不将每个脚本都添加到游戏对象中以使其看起来更干净?

BasicCharacter脚本可持续吗?

1 个答案:

答案 0 :(得分:3)

通过使用ScriptableObjects(https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/scriptable-objects),可以使角色的某些部分更加模块化,它们不一定降低复杂性(游戏很复杂,您必须接受)。它们至少可以帮助整理播放器控制器并使功能分散到其他更独立的类中,这些类方便地内置于Unity编辑器中,允许您拖放它们,更重要的是,可以从主要播放器预制件中单独编辑它们,从而避免出现“脚本数据壁垒”的问题。

例如,在这种情况下,我会将能力数据和buff / malus数据分离为ScriptableObjects。您可以在其中设置所需的任何类层次结构,并将其修改为核心玩家的单独游戏资产(如果您投入了足够的工作,甚至可以使其模块化,足以为敌人和您的玩家使用,这很漂亮方便!)

一旦设置了可脚本编写的对象,就可以为它们提供一些基本功能,例如“ OnTick”,“ OnTakeDamage”,“ OnActivate”等,甚至具有一些内部状态,例如“ IsSkillActive”等,那么您只需存储它们即可作为播放器对象上的列表或词典,并对其进行迭代。快速伪代码可能是:

bool canInput = true;
foreach(Ability in Abilities)
{
 if (Ability.IsSkillActive())
 {
  canInput = false; //still in the middle of an active ability
  break;
 }
}
if (canInput)
{
 //Do allow player to have input here.
}

或者您可以:

class DamageOverTimeDebuff : ScriptableObject
{
 int damagePerTick = 1;

 OnTick(PlayerObject afflictedPlayer)
 {
  afflictedPlayer.TakeDamage(1);
 }
}

通过这种方式,您可以使能力和效果更加模块化,并可以根据组成来构建您的玩家,而不是每个场景都具有if语句。

那是一个折衷,这增加了您的抽象水平,这使得极端特定的行为或特殊的边缘情况很难实现。您也可能会花费大量时间为减益或能力编写特定的功能,而这些功能只能用于一种效果,在这种情况下,这仅仅是多余的工作。

这只是一种可能的策略,您要描述的问题是每款游戏都必须以不同方式面对和应对的问题。也许ScriptableObjects可以帮助您将功能分解成更小巧的功能,也许它们只是阻碍您前进的样板。它取决于您游戏的特定需求。