374 lines
12 KiB
C#
374 lines
12 KiB
C#
|
/********************************************************************
|
|||
|
created: 2014/03/14
|
|||
|
created: 14:3:2014 16:48
|
|||
|
filename: NPCEditorRoot.cs
|
|||
|
author: 王迪
|
|||
|
|
|||
|
purpose: 种怪编辑器根结点,NPC必须挂在此结点下边界,
|
|||
|
导入导出需要选中带有此脚本的物体
|
|||
|
*********************************************************************/
|
|||
|
using UnityEngine;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Text;
|
|||
|
using GCGame;
|
|||
|
using System;
|
|||
|
using Module.Log;
|
|||
|
using Games.Scene;
|
|||
|
|
|||
|
public class NPCEditorRoot : MonoBehaviour {
|
|||
|
|
|||
|
public float UpdateDuration = 1.0f;
|
|||
|
private float m_updateTimer = 1.0f;
|
|||
|
//public float m_terrainHeight = 20.0f;
|
|||
|
public int curSceneID = 1;
|
|||
|
public int curDataID = -1;
|
|||
|
public float curRadius = 1;
|
|||
|
public Color curColor = Color.white;
|
|||
|
|
|||
|
public GameObject _NPCIniPrefab;
|
|||
|
|
|||
|
// Use this for initialization
|
|||
|
void Start () {
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// Update is called once per frame
|
|||
|
void OnDrawGizmos()
|
|||
|
{
|
|||
|
m_updateTimer -= Time.deltaTime;
|
|||
|
if (m_updateTimer < 0)
|
|||
|
{
|
|||
|
m_updateTimer = UpdateDuration;
|
|||
|
foreach (NPCPresent child in transform.GetComponentsInChildren<NPCPresent>(false))
|
|||
|
{
|
|||
|
//child.SetHeight(m_terrainHeight);
|
|||
|
if (child.DataID == curDataID )
|
|||
|
{
|
|||
|
|
|||
|
child.SetColor(curColor);
|
|||
|
child.SetRadius(curRadius);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void AddNPC(Vector3 pos)
|
|||
|
{
|
|||
|
var npcObj = GameObject.Instantiate(_NPCIniPrefab);
|
|||
|
npcObj.transform.parent = transform;
|
|||
|
npcObj.transform.position = pos;
|
|||
|
npcObj.GetComponent<NPCPresent>().SetHeight(pos.y + 1);
|
|||
|
npcObj.GetComponent<NPCPresent>().DataID = curDataID;
|
|||
|
npcObj.name = curDataID.ToString();
|
|||
|
}
|
|||
|
|
|||
|
public class NPCData
|
|||
|
{
|
|||
|
public string name;
|
|||
|
public int sceneID;
|
|||
|
public int dataID;
|
|||
|
public float xPos;
|
|||
|
public float yPos;
|
|||
|
public float rad;
|
|||
|
public int clientOnly;
|
|||
|
//public int npcType;
|
|||
|
|
|||
|
public string GetString()
|
|||
|
{
|
|||
|
return (name + "\t" +
|
|||
|
sceneID.ToString() + "\t" +
|
|||
|
dataID.ToString() + "\t" +
|
|||
|
xPos.ToString("0.##") + "\t" +
|
|||
|
yPos.ToString("0.##") + "\t" +
|
|||
|
rad.ToString("0.##") + "\t" +
|
|||
|
clientOnly.ToString()
|
|||
|
/*npcType.ToString()*/);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
private Dictionary<int, List<NPCData>> m_dicNPCCache = new Dictionary<int, List<NPCData>>();
|
|||
|
public void ExportData(string filePath)
|
|||
|
{
|
|||
|
|
|||
|
LoadFile(filePath);
|
|||
|
if (m_dicNPCCache.ContainsKey(curSceneID))
|
|||
|
{
|
|||
|
m_dicNPCCache[curSceneID] = new List<NPCData>();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_dicNPCCache.Add(curSceneID, new List<NPCData>());
|
|||
|
}
|
|||
|
|
|||
|
foreach (NPCPresent child in transform.GetComponentsInChildren<NPCPresent>(false))
|
|||
|
{
|
|||
|
NPCData curNPC = new NPCData();
|
|||
|
curNPC.name = child.NPCName;
|
|||
|
curNPC.sceneID = curSceneID;
|
|||
|
curNPC.dataID = child.DataID;
|
|||
|
var pos = GetTerrainPosition(child.transform.position);
|
|||
|
curNPC.xPos = /*child.transform.position.x;*/pos.x;
|
|||
|
curNPC.yPos =/* child.transform.position.z;*/ pos.z;
|
|||
|
curNPC.rad = Utils.DirClientToServer(child.transform.rotation);
|
|||
|
curNPC.clientOnly = child.ClentOnly;
|
|||
|
//curNPC.npcType = child.NPCType;
|
|||
|
m_dicNPCCache[curSceneID].Add(curNPC);
|
|||
|
}
|
|||
|
|
|||
|
WriteFile(filePath);
|
|||
|
//ConvertFile(filePath);
|
|||
|
}
|
|||
|
|
|||
|
public const float navSampleHeight = 30f;
|
|||
|
public const float raycastHeight = 200f;
|
|||
|
public const float sphereCastRadius = 1f;
|
|||
|
public const float edgeSnapDist = 0.05f;
|
|||
|
//public static readonly int terrainLayMask = LayerMask.GetMask("Default", "T4MLayer");
|
|||
|
public Vector3 GetTerrainPosition(Vector3 origin)
|
|||
|
{
|
|||
|
var raySource = origin;
|
|||
|
raySource.y = raycastHeight;
|
|||
|
|
|||
|
RaycastHit raycastHit;
|
|||
|
if (Physics.Raycast(raySource, Vector3.down, out raycastHit, raycastHeight * 2f, LayerMask.GetMask("Default", "T4MLayer")))
|
|||
|
origin = raycastHit.point;
|
|||
|
|
|||
|
if (Physics.SphereCast(raySource, sphereCastRadius, Vector3.down, out raycastHit, raycastHeight * 2f, LayerMask.GetMask("Default", "T4MLayer")))
|
|||
|
origin = raycastHit.point;
|
|||
|
|
|||
|
UnityEngine.AI.NavMeshHit navMeshHit;
|
|||
|
if (UnityEngine.AI.NavMesh.SamplePosition(origin, out navMeshHit, navSampleHeight, UnityEngine.AI.NavMesh.AllAreas))
|
|||
|
origin = navMeshHit.position;
|
|||
|
|
|||
|
if (UnityEngine.AI.NavMesh.FindClosestEdge(origin, out navMeshHit, UnityEngine.AI.NavMesh.AllAreas)
|
|||
|
&& (navMeshHit.position - origin).sqrMagnitude < edgeSnapDist.ToSquare())
|
|||
|
origin = navMeshHit.position;
|
|||
|
|
|||
|
return origin;
|
|||
|
}
|
|||
|
|
|||
|
public void ImportData(string path)
|
|||
|
{
|
|||
|
foreach (Transform curObj in transform)
|
|||
|
{
|
|||
|
DestroyImmediate(curObj.gameObject);
|
|||
|
}
|
|||
|
|
|||
|
List<GameObject> objList = new List<GameObject>();
|
|||
|
for (int i = 0, count = transform.childCount; i < count; i++)
|
|||
|
{
|
|||
|
objList.Add(transform.GetChild(i).gameObject);
|
|||
|
}
|
|||
|
|
|||
|
foreach (GameObject curObj in objList)
|
|||
|
{
|
|||
|
DestroyImmediate(curObj);
|
|||
|
}
|
|||
|
|
|||
|
LoadFile(path);
|
|||
|
if (!m_dicNPCCache.ContainsKey(curSceneID))
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
List<NPCData> curDataList = m_dicNPCCache[curSceneID];
|
|||
|
|
|||
|
//NPCPresent curPresent = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/MLDJ/Editor/NPCInst.prefab", typeof(NPCPresent)) as NPCPresent;
|
|||
|
|
|||
|
int curID = 0;
|
|||
|
foreach (NPCData curNPC in curDataList)
|
|||
|
{
|
|||
|
GameObject newRes = GameObject.Instantiate(_NPCIniPrefab) as GameObject;
|
|||
|
newRes.transform.parent = transform;
|
|||
|
NPCPresent curNPCS = newRes.GetComponent<NPCPresent>();
|
|||
|
curNPCS.transform.position = new Vector3(curNPC.xPos, 0, curNPC.yPos);
|
|||
|
curNPCS.transform.rotation = Utils.DirServerToClient(curNPC.rad);
|
|||
|
curNPCS.SetHeight(GetScenePosy(curNPC.xPos, curNPC.yPos));
|
|||
|
curNPCS.NPCName = curNPC.name;
|
|||
|
curNPCS.DataID = curNPC.dataID;
|
|||
|
curNPCS.ClentOnly = curNPC.clientOnly;
|
|||
|
//curNPCS.NPCType = curNPC.npcType;
|
|||
|
newRes.name = curID.ToString() + "_" + curNPC.name; ;
|
|||
|
curID++;
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
private static float GetScenePosy(float fX, float fZ)
|
|||
|
{
|
|||
|
Vector3 testPos = new Vector3(fX,100, fZ);
|
|||
|
Vector3 testDirect = new Vector3(0, -100, 0);
|
|||
|
Ray ray = new Ray(testPos, testDirect);
|
|||
|
RaycastHit hit;
|
|||
|
int layerMask = 1 << 12;
|
|||
|
if (Physics.Raycast(ray, out hit, 1000, layerMask))
|
|||
|
{
|
|||
|
|
|||
|
//如果检测点是
|
|||
|
//if (hit.collider.gameObject.CompareTag(m_szServerObstacleTag))
|
|||
|
{
|
|||
|
return hit.point.y;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//for (int i = 0; i < m_ServerObstacleTestAgent.Count; ++i)
|
|||
|
//{
|
|||
|
// m_ServerObstacleTestAgent[i].destination = pos;
|
|||
|
// if (m_ServerObstacleTestAgent[i].hasPath)
|
|||
|
// {
|
|||
|
// info.m_Value = m_nPath;
|
|||
|
// break;
|
|||
|
// }
|
|||
|
//}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
private List<string> _FileTitleStr = new List<string>();
|
|||
|
private void LoadFile(string filePath)
|
|||
|
{
|
|||
|
|
|||
|
m_dicNPCCache.Clear();
|
|||
|
if (File.Exists(filePath))
|
|||
|
{
|
|||
|
FileStream rfs = new FileStream(filePath, FileMode.Open);
|
|||
|
StreamReader sr = new StreamReader(rfs, Encoding.GetEncoding("GB2312"));
|
|||
|
_FileTitleStr.Clear();
|
|||
|
|
|||
|
int i = 0;
|
|||
|
bool startContentLine = false;
|
|||
|
while (!sr.EndOfStream)
|
|||
|
{
|
|||
|
string curLine = sr.ReadLine();
|
|||
|
LogModule.DebugLog(curLine);
|
|||
|
if (i++ < 2)
|
|||
|
{
|
|||
|
_FileTitleStr.Add(curLine);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (!startContentLine && curLine.StartsWith("#"))
|
|||
|
{
|
|||
|
_FileTitleStr.Add(curLine);
|
|||
|
continue;
|
|||
|
}
|
|||
|
startContentLine = true;
|
|||
|
|
|||
|
string[] values = curLine.Split('\t');
|
|||
|
if (values.Length !=8)
|
|||
|
{
|
|||
|
LogModule.ErrorLog("1");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
NPCData curData = new NPCData();
|
|||
|
int curID;
|
|||
|
if (!int.TryParse(values[0], out curID))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("0");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
curData.name = values[1];
|
|||
|
if (!int.TryParse(values[2], out curData.sceneID))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("2");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (!int.TryParse(values[3], out curData.dataID))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("3");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (!float.TryParse(values[4], out curData.xPos))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("4");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (!float.TryParse(values[5], out curData.yPos))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("5");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (!float.TryParse(values[6], out curData.rad))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("6");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (!int.TryParse(values[7], out curData.clientOnly))
|
|||
|
{
|
|||
|
LogModule.ErrorLog("7");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (!m_dicNPCCache.ContainsKey(curData.sceneID))
|
|||
|
{
|
|||
|
m_dicNPCCache.Add(curData.sceneID, new List<NPCData>());
|
|||
|
}
|
|||
|
|
|||
|
m_dicNPCCache[curData.sceneID].Add(curData);
|
|||
|
LogModule.DebugLog("get record");
|
|||
|
}
|
|||
|
|
|||
|
rfs.Close();
|
|||
|
sr.Close();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void WriteFile(string filePath)
|
|||
|
{
|
|||
|
if (File.Exists(filePath))
|
|||
|
{
|
|||
|
File.Delete(filePath);
|
|||
|
}
|
|||
|
FileStream wfs = new FileStream(filePath, FileMode.CreateNew);
|
|||
|
StreamWriter sw = new StreamWriter(wfs, Encoding.GetEncoding("GB2312"));
|
|||
|
for (int i = 0; i < _FileTitleStr.Count; ++i)
|
|||
|
{
|
|||
|
sw.WriteLine(_FileTitleStr[i]);
|
|||
|
}
|
|||
|
//sw.WriteLine("Id\tDesc\tSceneID\tDataID\tPosX\tPosZ\tFaceDirection\tClientShow");
|
|||
|
//sw.WriteLine("INT\tSTRING\tINT\tINT\tFLOAT\tFLOAT\tFLOAT\tINT");
|
|||
|
//sw.WriteLine("#MAX_ID=4999;MAX_RECORD=5000;TableType=Hash;ExportLua=1;\t\t\t\t\t\t\t");
|
|||
|
//sw.WriteLine("#唯一标示\t描述,策划维护,此列程序不读\t所属场景\tDataID\t位置X\t位置Z\t纯客户端显示用\t");
|
|||
|
|
|||
|
|
|||
|
int id = 0;
|
|||
|
foreach (List<NPCData> curList in m_dicNPCCache.Values)
|
|||
|
{
|
|||
|
foreach (NPCData curNPC in curList)
|
|||
|
{
|
|||
|
sw.WriteLine(id.ToString() + "\t" + curNPC.GetString());
|
|||
|
id++;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
wfs.Close();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void ConvertFile(string filePath)
|
|||
|
{
|
|||
|
#if UNITY_EDITOR
|
|||
|
FileStream rfs = new FileStream(filePath, FileMode.Open);
|
|||
|
StreamReader sr = new StreamReader(rfs);
|
|||
|
string curFile = sr.ReadToEnd();
|
|||
|
rfs.Close();
|
|||
|
sr.Close();
|
|||
|
|
|||
|
FileStream wfs = new FileStream(filePath, FileMode.OpenOrCreate);
|
|||
|
StreamWriter sw = new StreamWriter(wfs);
|
|||
|
Byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.ASCII, Encoding.UTF8.GetBytes(curFile));
|
|||
|
|
|||
|
|
|||
|
//Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(curFile.ToCharArray()));
|
|||
|
sw.Write(bytes);
|
|||
|
sw.Close();
|
|||
|
wfs.Close();
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|