c# - 如何正确地继续将多个脚本添加到游戏对象

标签 c# unity3d

我的 unity 项目越来越大,我有点害怕。

我创建了一个具有大量协同工作的脚本的播放器。 (最近它会更大。) 这是它的样子。

enter image description here

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

其中一些:

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 脚本是否可持续?

最佳答案

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

例如,在这种情况下,我会将能力数据和增益/恶意数据分离到 ScriptableObjects 中。您可以在那里设置任何您想要的类层次结构,并将它们作为单独的游戏 Assets 修改给您的核心玩家(如果您投入足够的工作,您甚至可以使它们足够模块化以供敌人和您的玩家使用,这很漂亮方便!)

一旦你设置了你的脚本对象,你就可以给它们一些基本功能,比如'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 可以帮助您将功能分解成更小的东西,也许它们只是妨碍您的额外样板。这取决于您游戏的具体需求。

关于c# - 如何正确地继续将多个脚本添加到游戏对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55443249/

相关文章:

c# - 为什么是 float.Epsilon 而不是零?

c# - 同时调用 3 个函数。应该使用 Parallel.For 吗?

c# - 自动更新下载最新的 .exe 文件 - 如何验证它没有被篡改?

c# - 如何在 Nant 0.91 中使用正则表达式调用 C#

c# - 无法存储类数组

c# - Unity3D不安全代码需要指定 `unsafe'命令行选项

c# - OpenCV 将位图转换为垫子

c# - 如何检查用户是否已在 AdMob for Unity 中完成视频?

c# - 实例化一个 GameObject 会导致所述对象的 Transform 被破坏?

c# - 获取另一个类的所有属性名称 - Unity 5 C#