using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; using MindPowerSdk; using UnityEngine; namespace MindPowerSdk { [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct SceneObjInfo { public ushort TypeId; // 高2位是type(0: 场景物件, 1: 特效物件), 其余是ID public int X; // 相对坐标 public int Y; public short HeightOff; public short YawAngle; public short Scale; // 保留未使用 public short GetTypeId() { return (short)(TypeId >> 14); } public short GetID() { return (short)(TypeId & 0x3FFF); } public override string ToString() { return $"type={GetTypeId()},id={GetID()},x={X},y={Y},height_off={HeightOff},yaw_angle={YawAngle},scale={Scale}"; } } public class SceneObjFile { /// /// 文件头 /// public struct Header { public string Title; // "HF Object File!" char[16] public int Version; public int FileSize; public int SectionCntX; // 地图的横向区域数 public int SectionCntY; // 地图的纵向区域数 public int SectionWidth; // 区域的宽度(单位:Tile) public int SectionHeight; // 区域的高度(单位:Tile) public int SectionObjNum; // 区域允许的最大物件数 } /// /// 用来索引文件中对象的数据 /// public struct SSectionIndex { public int ObjInfoPos; public int ObjNum; } public Header FileHeader { get; private set; } SSectionIndex[,] sectionIndex; public List[,] objInfos; public unsafe int Load(string obj_file) { FileStream fs = File.OpenRead(obj_file); BinaryReader r = new BinaryReader(fs); long size = r.BaseStream.Length; Header s = new Header(); s.Title = Encoding.ASCII.GetString(r.ReadBytes(16)); s.Version = r.ReadInt32(); s.FileSize = r.ReadInt32(); // 实际是32位 s.SectionCntX = r.ReadInt32(); s.SectionCntY = r.ReadInt32(); s.SectionWidth = r.ReadInt32(); s.SectionHeight = r.ReadInt32(); s.SectionObjNum = r.ReadInt32(); FileHeader = s; Debug.Log(JsonUtility.ToJson(s)); if (s.FileSize != size) { Debug.LogWarning($"{obj_file} 文件szie不匹配: {s.FileSize} != {size}"); return -1; } if (s.Version != 600) { Debug.LogWarning($"{obj_file} 版本只支持600: 当前是={s.Version}"); return -1; } // 读取索引信息 sectionIndex = new SSectionIndex[s.SectionCntX, s.SectionCntY]; for (int y = 0; y < s.SectionCntY; y++) { for (int x = 0; x < s.SectionCntX; x++) { SSectionIndex data = new SSectionIndex(); data.ObjInfoPos = r.ReadInt32(); data.ObjNum = r.ReadInt32(); sectionIndex[x, y] = data; if (data.ObjNum != 0) Debug.Log(JsonUtility.ToJson(data)); } } // 读取场景物体 objInfos = new List[s.SectionCntX, s.SectionCntY]; for (int y = 0; y < s.SectionCntY; y++) { for (int x = 0; x < s.SectionCntX; x++) { SSectionIndex idx = sectionIndex[x, y]; if (idx.ObjNum == 0) continue; var list = objInfos[x, y] ??= new List(); r.BaseStream.Seek(idx.ObjInfoPos, SeekOrigin.Begin); for (int i = 0; i < idx.ObjNum; i++) { byte[] tmpBytes = r.ReadBytes(sizeof(SceneObjInfo)); SceneObjInfo sceneObjInfo = StructReader.ReadStructFromArray(tmpBytes); // 转成绝对坐标 int sectionX = x * s.SectionWidth * 100; int sectionY = y * s.SectionHeight * 100; sceneObjInfo.X += sectionX; sceneObjInfo.Y += sectionY; list.Add(sceneObjInfo); Debug.Log(sceneObjInfo.ToString()); } } } return 0; } } }