u3d honey hex framework 代码解读记录(一)

honey hex framework: 点击打开链接


// file: CameralControl.cs
if (GUILayout.Button("Generate World"))
{
// 将地形和配置资源load到游戏中
// 游戏设置(MHGameSettings)和地形配置(MHTerrain)
// 代码较简单,先从StreamingAssets处寻找资源,如果没有,就从Resource里面寻找,然后load到内存中
// 地形数据会放入到MHTerrain.list中,在第2个函数执行时会用到
    DataManager.Reload();

    // 是生成地图,框架主要内容
    World.GetInstance().Initialize();

    // a*寻路相关,暂时忽略
    AstarPath.RegisterSafeUpdate(GameManager.instance.ActivatePathfinder);
}

public void Initialize()
{
    status = Status.Preparation;

    // load 地形配置
    TerrainDefinition.ReloadDefinitions();

    // 生成地图数据
    GenerateBasicWorld(hexRadius, GeneratorMode.Random);

    // 创建河流数据,先不分析,跳过
    RiverFactory.CreateRivers(this, hexRadius);

    // 为每一个chunk生成地形数据,以便worldoven烘焙
    // x和y从-chunkRadius到+chunkRadius,chunkRadius为1,即有9块chunk
    // -1,1 |0,1 |1,1
    // -1,0 |0,0 |1,0
    // -1,-1|0,-1|1,-1
    for (int x = -chunkRadius; x <= chunkRadius; x++)
        for (int y = -chunkRadius; y <= chunkRadius; y++)
        {
            PrepareChunkData(new Vector2i(x, y));
        }

    status = Status.TerrainGeneration;
}

static public void ReloadDefinitions()
{
// load地形配置和游戏配置
    if (!DataManager.isInitialized)
    {
        DataManager.GetInstance();
        if (!DataManager.isInitialized)
        {
            Debug.LogError("Data Manager is not initialized! no definitions would be loaded...");
            return;
        }
    }

    definitions = new List<TerrainDefinition>();

    // MHTerrain.list是DataManger.loadResource加载的地形配置数据,
    // 填充到TerrainDefinition.definitions这个数组里面
    foreach (MHTerrain t in MHTerrain.list)
    {
        TerrainDefinition td = new TerrainDefinition();
        td.source = t;
        td.diffuse = LoadTexture(t.diffusePath);
        td.height = LoadTexture(t.heightPath);
        td.mixer = LoadTexture(t.mixerPath);
        definitions.Add(td);
    }
}

// 传入的参数,radius是world类的变量hexRadius,默认值是15,mode是GeneratorMode.random
public void GenerateBasicWorld(int radius, GeneratorMode mode)
{
// 清空world对象中的hexes
    hexes = new Dictionary<Vector3i, Hex>();            

    // 第一个参数为全x,y,z都为0的向量,所以此处获取了0为中心半径为radius(15)以内的所有hex的坐标组成的数组
    List<Vector3i> rangeHexes = HexNeighbors.GetRange(new Vector3i(), radius);
    int terrainCount = TerrainDefinition.definitions.Count;
    if (terrainCount < 1)
    {
        Debug.LogError("no terrain definitions to use!");
        return;
    }

    // 从地形配置中找出所有地形类型为normal的地形配置,类型一共有以下几种:
    // 1. normal; 2. IsBorderType; 3. IsRiverType; 4. DoNotUseThisTerrain
    List<TerrainDefinition> tdList = TerrainDefinition.definitions.FindAll(o => o.source.mode == MHTerrain.Mode.normal);

    foreach (Vector3i v in rangeHexes)
    {
        hexes.Add(v, GetHexDefinition(mode, v, tdList));
    }
}

// 此处传入的参数mode是GeneratorMode.random
static public Hex GetHexDefinition(GeneratorMode mode, Vector3i position, List<TerrainDefinition> tdList)
{
    Hex hex = new Hex();
    int index = 0;

    // 随机选择顺序和旋转角度
    hex.orderPosition = UnityEngine.Random.Range(0.0f, 1.0f);
    hex.rotationAngle = UnityEngine.Random.Range(0.0f, 360.0f);
    TerrainDefinition def = null;

    switch (mode)
    {
        case GeneratorMode.Random:
        // 随机从list里面选择一个地形配置
            index = UnityEngine.Random.Range(0, tdList.Count);
            def = tdList[index];
            break;

        case GeneratorMode.Perlin:
        // 柏林噪声选择地形配置
            float xScale = .16f;
            float yScale = .16f;
            float value = Mathf.PerlinNoise(position.x * xScale, position.y * yScale);
            index = (int)(value * (tdList.Count - 1));
            def = tdList[index];
            break;
    }

    // 设置地形配置和位置
    hex.terrainType = def;
    hex.position = position;

    // 将当前hex加入到hexesToPolish这个list里面
    GetInstance().ReadyToPolishHex(hex);

    return hex;
}

public bool PrepareChunkData(Vector2i pos)
{
    Chunk chunk;

    // chunks是world对象的字典,key是pos,value是chunk
    if (chunks.ContainsKey(pos))
    {
    // 如果此位置chunk存在,则清除掉此chunk包含的hex数据
        chunk = chunks[pos];
        chunk.ClearHexesCovered();
    }
    else
    {
        chunk = new Chunk(pos, this);
    }
    Rect r = chunk.GetRect();

    // 扩大chunk的覆盖范围
    //expand its influence by the texture halfWidth (aka radius) which would let us find all hexes which influence our chunk even with border of their texture
    r.xMin -= Hex.hexTexturePotentialReach;
    r.yMin -= Hex.hexTexturePotentialReach;
    r.xMax += Hex.hexTexturePotentialReach;
    r.yMax += Hex.hexTexturePotentialReach;

    // 获取chunk区域包含的所有hex的中心点的坐标
    List<Vector3i> intersections = HexNeighbors.GetHexCentersWithinSquare(r);
    bool foundAny = false;

    foreach (Vector3i v in intersections)
    {
        // hexes是函数GenerateBasicWorld中将此区域中半径为radius(15)以内的所有hex
        // 由于hexes是以0,0为中心点,半径为15之内的hex的集合,所以hex将chunk(0,0)全部覆盖完了,
        // 其他chunk则只有很少的hex,对应生成的地图就成为中心处(chunk(0,0))是地形,周围有部分地形,其余全是海洋(边界)
        //if hex exists at those coordinates, add it to chunk management
        if (hexes.ContainsKey(v))
        {
            chunk.hexesCovered[v] = hexes[v];
            // 如果有任何类型不是边界的hex,则foundAny是true
            foundAny = foundAny || !(hexes[v].terrainType.source.mode == MHTerrain.Mode.IsBorderType);
        }
        else
        {
        // 如果hexes中不包含当前坐标,则表示坐标在边界处(超出radius的半径范围),设置hex类型为border
            //produce border hexes which will fill empty space in chunk
            Hex border = new Hex();
            TerrainDefinition td = TerrainDefinition.definitions.Find(o => o.source.mode == MHTerrain.Mode.IsBorderType);
            if (td == null) td = TerrainDefinition.definitions[0];
            border.terrainType = td;
            border.rotationAngle = 0;                    
            border.orderPosition = UnityEngine.Random.Range(0.0f, 1.0f);
            border.rotationAngle = UnityEngine.Random.Range(0.0f, 360.0f);

            border.position = v;
            hexes.Add(v, border);

            chunk.hexesCovered[v] = border;
        }
    }

    if (foundAny == false)
    {
        return false;
    }
    
    chunks[pos] = chunk;           

    // 将当前chunk设为dirty,这样worldoven可以baking了
    WorldOven.AddDirtyChunk(chunk);

    return true;
} 


待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值