c# - 使用 C# 属性访问数组元素 (Unity3D)
问题描述
我正在尝试为 Unity 游戏的简单通用输入/控制器系统找出一个好的设计模式,该系统可用于玩家、NPC、车辆等。我当前的设计使用具有静态数组的控制器超类“Actions”,每个都有关于如何触发“Action States”数组中的相应布尔值、键绑定等的基本信息。然后我可以为特定的控制器指定派生类。我对这个设计的实现如下所示。
控制器超类:
public class Controller : MonoBehaviour
{
public class Action
{
public enum ActionType
{
Impulse,
Hold,
Toggle
};
public string name;
public ActionType actionType;
public KeyCode binding;
...
}
[HideInInspector]
public static Action[] actions;
public bool[] actionStates;
}
特定控制器示例:
public class HumanController : Controller
{
public bool sprint { get { return actionStates[0]; } set { actionStates[0] = value; } }
public bool jump { get { return actionStates[1]; } set { actionStates[1] = value; } }
...
public bool openInventory { get { return actionStates[13]; } set { actionStates[13] = value; } }
public HumanController()
{
actions = new Action[]
{
new Action("Sprint", Action.InputType.Hold, KeyCode.LeftShift),
new Action("Jump", Action.InputType.Impulse, KeyCode.Space),
...
new Action("Open Inventory", Action.InputType.Toggle, KeyCode.Tab),
};
actionStates = new bool[actions.Length];
}
}
该系统运行良好,因为我可以轻松地在检查器中查看 actionStates 数组,可以通过属性轻松地在代码中访问它们,而不是使用字符串索引字典(我怀疑这会更慢并产生更多垃圾)等等。唯一不理想的部分是手动设置属性,我想知道是否有一种更简洁/更优雅的方式将派生类中的每个属性映射到 actionStates 数组的每个元素,而不是执行每个动作如下:
public bool action { get { return actionStates [0]; } set { actionStates[0] = value; } }
解决方案
在接受了这个建议之后...
当然,最好将带有枚举的数组作为计数器,这样 myAction[JUMP] = ... 等
我想出了以下设置。
控制器超类:
public class Controller : MonoBehaviour
{
public class Action
{
public enum InputType
{
Impulse,
Hold,
Toggle
};
public string name;
public InputType inputType;
public KeyCode binding;
...
}
public virtual Action[] actions { get; }
public bool[] actionStates;
public Controller()
{
actionStates = new bool[actions.Length];
}
}
可索引派生类(尝试将 T 约束为枚举):
public class Controller<T> : Controller where T : struct, System.IConvertible
{
public bool this[T enumIndex]
{
get { return actionStates[System.Convert.ToInt32(enumIndex)]; }
set { actionStates[System.Convert.ToInt32(enumIndex)] = value; }
}
}
特定控制器示例:
public enum HumanControls
{
sprint,
jump,
...
openInventory
}
public class HumanController : Controller<HumanControls>
{
public static Action[] actionList = new Action[]
{
// movement
new Action("Sprint", Action.InputType.Hold, KeyCode.LeftShift),
new Action("Jump", Action.InputType.Impulse, KeyCode.Space),
...
new Action("Open Inventory", Action.InputType.Toggle, KeyCode.Tab),
};
public override Action[] actions { get; } = actionList;
}
然后我可以按如下方式使用控制器:
using static HumanControls;
...
if(controller[sprint]) {
...
它不涉及太多冗余,仍然允许我像以前一样使用简单的类型名称轻松访问数组元素(而不是先将 enum 强制转换为 int 等),并且工作得和我希望的用例一样好.
推荐阅读
- woocommerce - 使用 Woocommerce API 时批量更新产品不起作用
- javascript - 通过包装在 ref() 中的反应性 Vue 路由器对象不起作用
- node.js - npm 审核失败,套接字挂起 (ECONNRESET) (WSL)
- swift - swift中Array的func drop(while)无法正常工作
- php - 在文件夹中调用 Laravel Seeder
- amazon-web-services - S3 静态托管仍然显示旧版本的应用程序
- c++ - 是否对参与偏序的类型执行实例化
- javascript - JSON解析无法正常工作 - Javascript
- arrays - HLSL - 为什么我不能重新定义这个数组?
- node.js - Google Drive API:列出特定文件夹中的文件