如何从我的玩具 ECS 实现中删除这种间接性

问题描述 投票:0回答:1

我在下面有一个简单的玩具 ECS 对象实现。

DerefData(GameBehavior behavior)
方法的签名需要
GameBehavior
参数才能用作索引查找。

GameBehavior
值应由类型
Flyable.BehaviorID
设置。但要知道,我们需要一个实例,这是行不通的,因为 deref 方法的目的是从泛型类型获取实例。

最好不使用反射,以便尽可能快。

可以重构为只需要

BaseGameObject<U> DerefData()
而不需要参数吗?

using System;

GameObject gameobj = new();

Flyable fdata = new Flyable {   Velocity = 0d };

gameobj.AddBehavior(fdata);

var flightdata = gameobj.DerefData<Flyable>(GameBehavior.Flyable); 
// i'd like to remove the parameter from this method signature. 
// Which means we need access to IBehavior.BehaviorID, 
// which is a 'type-level' property that in theory shouldn't need an object to lookup the value.

interface IBehavior
{
    GameBehavior BehaviorID { get; }
}

struct Flyable : IBehavior
{
    public GameBehavior BehaviorID => GameBehavior.Flyable;
    public double Velocity;
}


[Flags]
enum GameBehavior : int
{
    Flyable,
    Burnable
}

class GameObject : BaseGameObject<IBehavior>{}

abstract class BaseGameObject<T> where T : IBehavior
{
    T[] Items = new T[32]; // Max number of enum flags; this ECS is limited to at max 32 behaviors per game object


    public U DerefData<U>(GameBehavior behavior) where U : T
    {
        return (U)Items[(int)behavior]; // We don't have an object instance to lookup behavior ID
    }

    public void AddBehavior<U>(U obj) where U : T
    {
        Items[(int)obj.BehaviorID] = obj; // we have an object instance to lookup BehaviorID
    }

}
c#
1个回答
0
投票

我自己的问题有答案,但我肯定会接受批评或其他答案

所讨论的方法是:

public U DerefData<U>(GameBehavior behavior) where U : T
{
    return (U)Items[(int)behavior]; // We don't have an object instance to lookup behavior ID
}

我们重构如下:

public U DerefData<U>() where U : struct, T
{
    return (U)Items[(int)new U().BehaviorID]; 
}

这需要在堆栈上分配预期行为类型的一次性结构。只要行为结构保持相对较小,堆栈分配应该很快并且不会逃逸到堆。

现在用法可以重构为

var flightdata = gameobj.DerefData<Flyable>();
© www.soinside.com 2019 - 2024. All rights reserved.