/// 加载XML至路标点 <summary>
    /// 加载XML至路标点
    /// </summary>
    /// <param name="xmlFileName">xml文件名(不包含路径)</param>
    /// <param name="all">路标点集合(父物体)</param>
    public void LoadXmlToWaypoints(WaypointMessage all, string xmlPath = null, string xmlString = null)
    {
        WaypointsXML   temWaypointsXML = new WaypointsXML();
        WaypointsModel temWM           = new WaypointsModel();

        int number = 0;

        all.WaypointsModelAll.Clear();

        //销毁子物体
        DestroyChild(all.transform);

        //获取XML数据至集合
        temWaypointsXML.GetXmlData(all.WaypointsModelAll, xmlPath, xmlString);
        for (int i = 0; i < all.WaypointsModelAll.Count; i++)
        {
            number++;

            //在编辑器中则创建
            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
                GameObject go = new GameObject();
                go.transform.parent     = all.transform;
                go.name                 = all.WaypointsModelAll[i].Index.ToString();
                go.transform.position   = all.WaypointsModelAll[i].Position;
                go.transform.rotation   = all.WaypointsModelAll[i].Rotation;
                go.transform.localScale = all.WaypointsModelAll[i].Scale;
            }
        }

        if (Debug.isDebugBuild)
        {
            Debug.Log("【" + all.WaypointsModelAll.Count.ToString() + "】加载完成:" + all.curWaypointsXMLPath);
        }
    }
    /// 保存路标点至XML<summary>
    /// 保存路标点至XML
    /// </summary>
    /// <param name="xmlFileName">xml文件名(不包含路径)</param>
    /// <param name="all">路标点集合(父物体)</param>
    public void SaveWaypointsToXml(WaypointMessage all, string xmlPath)
    {
        WaypointsXML temWaypointsXML = new WaypointsXML();

        int number = 0;

        //xml是否存在,如果存在就删除
        //否则会叠加
        if (File.Exists(xmlPath))
        {
            File.Delete(xmlPath);
        }

        foreach (Transform child in all.transform)
        {
            number++;

            WaypointsModel temWM = new WaypointsModel();
            temWM.Index    = int.Parse(child.transform.name);
            temWM.Position = child.position;
            temWM.Rotation = child.rotation;
            temWM.Scale    = child.localScale;

            temWaypointsXML.AddXmlData(temWM, xmlPath);
        }

        //保存后刷新路标点
        LoadXmlToWaypoints(all, xmlPath);

        if (Debug.isDebugBuild)
        {
            Debug.Log("【" + all.WaypointsModelAll.Count.ToString() + "】保存完成:" + all.curWaypointsXMLPath);
        }
    }
Ejemplo n.º 3
0
        public async Task <ActionResult <WaypointsModel> > PostWaypoints(WaypointsModel model)
        {
            Level  lvlId = _context.Levels.Where(x => x.Name == model.LevelName).FirstOrDefault();
            Object enemy = _context.Objects.Where(x => x.Name.Contains("tank")).Where(x => x.LevelId == lvlId.Id).FirstOrDefault();

            if (enemy != null)
            {
                int id = (int)enemy.Id;
                foreach (Waypoint item in model.waypoints)
                {
                    item.ObjectId  = id;
                    item.LevelName = model.LevelName;
                    _context.Waypoints.Add(item);
                }
            }
            else
            {
                return(NotFound());
            }
            await _context.SaveChangesAsync();



            return(Ok());
        }
    /// 检测反向移动 <summary>
    /// 检测反向移动
    /// 思路如下:
    /// 通过Waypoint检测到离赛车最近的点
    /// 然后通过计算点的距离而得出是否反向
    /// </summary>
    private void isReverse()
    {
        WaypointsModel ClosestWP = GetClosestWP(WaypointsModelAll, transform.position);//获取距离最近的路径点

        //角度偏移 = 最近路径点的角度 - 赛车的角度
        float angleOffset = ClosestWP.Rotation.eulerAngles.y - transform.eulerAngles.y;

        /* 理论上来说
         * 完全可以只写成 if(Mathf.Abs(angleOffset) >= 90f)
         * 则判断为反向!但是实际运用时会出现问题
         * 因为赛道是围成圈形的(首尾相连)
         * 当赛车移动到下半圈的时候
         * 明明是正确的方向,但是却提示反向了
         * 所以为了避免这种情况发生,我们要用360-90=270
         * 如果还是不理解的话debug路径点角度和赛车的角度就会发现端倪了*/

        //角度偏移<=270f && 角度偏移>=90f && 刚体速度>8f
        if (Mathf.Abs(angleOffset) <= 270f && Mathf.Abs(angleOffset) >= 90f)
        {
            is_reverse = true;
        }
        else
        {
            is_reverse = false;
        }
    }
Ejemplo n.º 5
0
    /// 添加XML数据 <summary>
    /// 添加XML数据
    /// </summary>
    /// <param name="_path">欲添加路标点实体</param>
    /// <param name="wm">xml文件路径</param>
    public void AddXmlData(WaypointsModel wm, string xmlPath)
    {
        CheckXmlFile(xmlPath);//检测XML文件

        if (File.Exists(xmlPath))
        {
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.Load(xmlPath);

            XmlNode    root   = xmlDoc.SelectSingleNode("waypoints");
            XmlElement elmNew = xmlDoc.CreateElement("waypoint");
            elmNew.SetAttribute("index", wm.Index.ToString());

            XmlElement position = xmlDoc.CreateElement("position");
            position.InnerText = wm.Position.ToString();

            XmlElement rotation = xmlDoc.CreateElement("rotation");
            rotation.InnerText = wm.Rotation.ToString();
            XmlElement scale = xmlDoc.CreateElement("scale");
            scale.InnerText = wm.Scale.ToString();

            elmNew.AppendChild(position);
            elmNew.AppendChild(rotation);
            elmNew.AppendChild(scale);
            root.AppendChild(elmNew);
            xmlDoc.AppendChild(root);
            xmlDoc.Save(xmlPath);
        }
    }
    /// 绘制方向标识线 <summary>
    /// 绘制方向标识线
    /// </summary>
    /// <param name="wp1">路标点1</param>
    /// <param name="wp2">路标点2</param>
    /// <param name="_lineWidth">标识线宽度</param>
    private void DrawDirLine(WaypointsModel wm1, WaypointsModel wm2, float _lineWidth)
    {
        //计算方向标识线左边的点
        Vector3 dirLineLeft = wm1.Position + (wm1.Rotation * Vector3.right * (_lineWidth / 2f) * -1);

        //计算方向标识线右边的点
        Vector3 dirLineRight = wm1.Position + (wm1.Rotation * Vector3.right * (_lineWidth / 2f));

        //绘制一条连接左右两点的线
        Gizmos.DrawLine(dirLineLeft, dirLineRight);

        //绘制方向箭头(左右两点分别绘制一条连接下个路标点的线呈三角形)
        Gizmos.DrawLine(dirLineLeft, wm2.Position);
        Gizmos.DrawLine(dirLineRight, wm2.Position);
    }
    /// 获取距离最近的路径点 <summary>
    /// 获取距离最近的路径点
    /// </summary>
    /// <param name="DPs">路径点集合</param>
    /// <param name="myPosition">当前坐标</param>
    /// <returns>返回最近距离的路标点</returns>
    private WaypointsModel GetClosestWP(List <WaypointsModel> all, Vector3 myPosition)
    {
        WaypointsModel tMin    = null;
        float          minDist = Mathf.Infinity;//正无穷

        for (int i = 0; i < all.Count; i++)
        {
            float dist = Vector3.Distance(all[i].Position, myPosition);
            if (dist < minDist)
            {
                tMin    = all[i];
                minDist = dist;
            }
        }
        return(tMin);
    }
    /// 重置赛车 <summary>
    /// 重置赛车
    /// </summary>
    private void RecoverCarA()
    {
        //获取距离最近的路标点
        WaypointsModel ClosestWP = GetClosestWP(WaypointsModelAll, transform.position);

        //置赛车位置
        transform.position = ClosestWP.Position;

        //置车头朝向
        transform.rotation = Quaternion.LookRotation(ClosestWP.Rotation * Vector3.forward);

        //移动速度归零
        GetComponent <Rigidbody>().velocity = Vector3.zero;

        //角速度归零
        GetComponent <Rigidbody>().angularVelocity = Vector3.zero;
    }
    /// 圈数检测 <summary>
    /// 圈数检测
    /// 思路如下:
    /// 每一帧计算距离最近的检查点
    /// 检查点存在则不添加,不存在则添加
    /// 冲过终点线时取数量
    /// 大于最少数量则算通过一圈
    /// 然后清零 CheckPoints
    /// </summary>
    private void CircleNumberCheck()
    {
        WaypointsModel ClosestWP = GetClosestWP(WaypointsModelAll, transform.position);//获取距离最近的路径点

        //判断当前最近路标点是否已存在
        for (int i = 0; i < CheckPoints.Count; i++)
        {
            //存在则返回
            if (ClosestWP.Position == CheckPoints[i].Position)
            {
                return;
            }
        }

        //不存在则添加
        CheckPoints.Add(ClosestWP);
    }
Ejemplo n.º 10
0
    /// 获取XML数据 <summary>
    /// 获取XML数据
    /// </summary>
    /// <param name="_Waypoints">保存路标点集合</param>
    /// <param name="xmlPath">xml文件路径</param>
    /// <param name="xmlString">xml文本数据</param>
    public void GetXmlData(List <WaypointsModel> _Waypoints, string xmlPath = null, string xmlString = null)
    {
        if (File.Exists(xmlPath) || xmlPath == null)
        {
            XmlDocument xmlDoc = new XmlDocument();

            if (xmlPath == null)
            {
                xmlDoc.LoadXml(xmlString);
            }
            else
            {
                xmlDoc.Load(xmlPath);
            }

            XmlNodeList nodeList = xmlDoc.SelectSingleNode("waypoints").ChildNodes;

            foreach (XmlElement xml1 in nodeList)
            {
                WaypointsModel temWaypoint = new WaypointsModel();
                temWaypoint.Index = Convert.ToInt32(xml1.GetAttribute("index"));

                foreach (XmlElement xml2 in xml1.ChildNodes)
                {
                    switch (xml2.Name)
                    {
                    case "position":
                        temWaypoint.Position = StringToVector3(xml2.InnerText);
                        break;

                    case "rotation":
                        temWaypoint.Rotation = StringToQuaternion(xml2.InnerText);
                        break;

                    case "scale":
                        temWaypoint.Scale = StringToVector3(xml2.InnerText);
                        break;
                    }
                }

                //添加进路标点集合
                _Waypoints.Add(temWaypoint);
            }
        }
    }
    /// 添加路标点 <summary>
    /// 添加路标点
    /// </summary>
    /// <param name="all">路标点集合(父物体)</param>
    public void AddWaypoint(WaypointMessage all)
    {
        GameObject go = new GameObject();

        go.transform.parent = all.transform;
        Transform[] tt = all.transform.GetComponentsInChildren <Transform>();
        go.name = (tt.Length - 2).ToString();

        Selection.activeTransform = go.transform;
        //EditorApplication.ExecuteMenuItem("GameObject/Move To View");
        //go.transform.rotation = new Quaternion(0f, 0f, 0f, 0f);
        if (all.WaypointsModelAll != null)
        {
            if (all.WaypointsModelAll.Count <= 0)
            {
                //生成的路标点移动到视窗内
                EditorApplication.ExecuteMenuItem("GameObject/Move To View");
            }
            else
            {
                Vector3    pos  = all.WaypointsModelAll[all.WaypointsModelAll.Count - 1].Position + Vector3.up * 50f;
                Quaternion rota = all.WaypointsModelAll[all.WaypointsModelAll.Count - 1].Rotation;

                //生成的路标点在最后一个路标点的前方
                //当前位置 = 上个路标点位置 + 上个路标点旋转 * 世界位置前 * (最大两点距离 - 3f)
                go.transform.position = pos + rota * Vector3.forward * (maxWaypointDis - 3f);
                go.transform.rotation = all.WaypointsModelAll[all.WaypointsModelAll.Count - 1].Rotation;
            }
        }

        WaypointsModel wm = new WaypointsModel();

        wm.Index    = int.Parse(go.name);
        wm.Position = go.transform.position;
        wm.Rotation = go.transform.rotation;
        wm.Scale    = go.transform.localScale;
        WaypointsModelAll.Add(wm);
    }
    void OnDrawGizmos()
    {
        //不在编辑器中则返回
        if (Application.platform != RuntimePlatform.WindowsEditor)
        {
            return;
        }

        myTransform = transform;

        #region 对齐地面&更新数据

        //当前选择的如果是Waypoint时
        if (Selection.activeTransform != null)
        {
            if (Selection.activeTransform.parent == transform)
            {
                int temIndex = int.Parse(Selection.activeTransform.name);
                for (int i = 0; i < WaypointsModelAll.Count; i++)
                {
                    if (temIndex == WaypointsModelAll[i].Index)
                    {
                        //当路标点被移动时更新数据
                        if (i != 0)
                        {
                            //限制两点间最大距离
                            if (Mathf.Abs(Vector3.Distance(WaypointsModelAll[i - 1].Position, Selection.activeTransform.position)) < maxWaypointDis)
                            {
                                WaypointsModelAll[i].Position = Selection.activeTransform.position;
                            }
                        }
                        else
                        {
                            //最后一个路标点和第一个路标点不计算最大距离
                            WaypointsModelAll[i].Position = Selection.activeTransform.position;
                        }

                        WaypointsModelAll[i].Rotation = Selection.activeTransform.rotation;
                        WaypointsModelAll[i].Scale    = Selection.activeTransform.localScale;

                        /*
                         * if (i != WaypointsModelAll.Count - 1)
                         * {
                         *  Selection.activeTransform.LookAt(WaypointsModelAll[i + 1].Position);
                         * }
                         * else if (isAroundCircle)
                         * {
                         *  //如果绕圈则注视起点
                         *  Selection.activeTransform.LookAt(WaypointsModelAll[0].Position);
                         * }*/


                        //对齐地面
                        if (alignGround)
                        {
                            RaycastHit[] hit;
                            hit = Physics.RaycastAll(WaypointsModelAll[i].Position, WaypointsModelAll[i].Rotation * -Vector3.up, 100f);//起始位置、方向、距离

                            #region 获取碰撞到的所有物体

                            for (int i1 = 0; i1 < hit.Length; i1++)
                            {
                                //当碰撞到的物体为地面时
                                if (hit[i1].transform.tag == "Map_ground")
                                {
                                    //计算当前路标点与地面之间的距离
                                    float temDis = Vector3.Distance(WaypointsModelAll[i].Position, hit[i1].point);

                                    //调整距离
                                    Selection.activeTransform.position = new Vector3(
                                        WaypointsModelAll[i].Position.x,
                                        WaypointsModelAll[i].Position.y - (temDis - disGround),
                                        WaypointsModelAll[i].Position.z);

                                    //Debug.Log(temDis);

                                    //绘制高度线
                                    Debug.DrawRay(WaypointsModelAll[i].Position, WaypointsModelAll[i].Rotation * -Vector3.up * temDis, Color.red);
                                    break;
                                }
                            }

                            #endregion
                        }
                        break;
                    }
                }
            }
        }

        #endregion

        WaypointsModelAll.Clear();

        Transform lastTransform = null;//上次路标点

        foreach (Transform child in transform)
        {
            //上次路标点不为null时注视本次路标点
            if (lastTransform != null)
            {
                lastTransform.LookAt(child.position);
            }

            lastTransform = child;
            WaypointsModel temWM = new WaypointsModel();
            temWM.Index    = int.Parse(child.transform.name);
            temWM.Position = child.position;
            temWM.Rotation = child.rotation;
            temWM.Scale    = child.localScale;
            WaypointsModelAll.Add(temWM);
        }

        Gizmos.color = lineColor;
        for (int i = 0; i < WaypointsModelAll.Count; i++)
        {
            //Gizmos.DrawIcon(wayPointAll[i].position, "Waypoint.png");
            //Gizmos.DrawCube(wayPointAll[i].position, new Vector3(1f, 1f, 1f));

            if (i != 0)
            {
                //绘制一条从当前路标点到下个路标点的线
                if (showWaypoint)
                {
                    Gizmos.DrawLine(WaypointsModelAll[i - 1].Position, WaypointsModelAll[i].Position);
                }

                //是否绘制方向标识线
                if (showWaypointDir)
                {
                    DrawDirLine(WaypointsModelAll[i - 1], WaypointsModelAll[i], lineWidth);
                }
            }
            else if (isAroundCircle)
            {
                //如果绕圈则首尾相连(多圈和单圈区分)

                //路标点尾首相连
                if (showWaypoint)
                {
                    Gizmos.DrawLine(WaypointsModelAll[WaypointsModelAll.Count - 1].Position, WaypointsModelAll[0].Position);
                }

                //是否绘制方向标识线
                if (showWaypointDir)
                {
                    DrawDirLine(WaypointsModelAll[WaypointsModelAll.Count - 1], WaypointsModelAll[0], lineWidth);
                }
            }
        }
    }
    /// 重置赛车 <summary>
    /// 重置赛车
    /// </summary>
    private void RecoverCar()
    {
        //获取距离最近的路标点
        WaypointsModel ClosestWP = GetClosestWP(WaypointsModelAll, transform.position);

        //下个路标点索引
        int nextIndex = ClosestWP.Index + 1;

        //最近路标点
        Vector3 nearestPoint;

        //下一个复位点索引 小于 路标点数量 - 1
        if (nextIndex < WaypointsModelAll.Count - 1)
        {
            //获取两个路标点间离赛车最近的点
            nearestPoint = NearestPoint(
                ClosestWP.Position,
                WaypointsModelAll[nextIndex].Position,
                transform.position);
        }
        else
        {
            //最后一个点和起点之间时取最后一个点的位置
            nearestPoint = WaypointsModelAll[WaypointsModelAll.Count - 1].Position;
        }


        #region 新添加

        RaycastHit[] hit;

        //是否碰撞到地面
        bool isColliderGround = false;

        //向下发送射线
        hit = Physics.RaycastAll(nearestPoint, ClosestWP.Rotation * -Vector3.up, 100f);

        for (int i1 = 0; i1 < hit.Length; i1++)
        {
            //当碰撞到的物体为地面时
            if (hit[i1].transform.tag == "Map_ground")
            {
                isColliderGround = true;

                //计算当前路标点与地面之间的距离
                float temDis = Vector3.Distance(nearestPoint, hit[i1].point);

                //调整距离
                nearestPoint.y = nearestPoint.y - (temDis - 0.5f);

                //Debug.Log(temDis);

                //绘制高度线
                //Debug.DrawRay(WaypointsModelAll[i].Position, WaypointsModelAll[i].Rotation * -Vector3.up * temDis, Color.red);
                break;
            }
        }

        //如果没有碰撞到地面
        //则说明赛车下面没有地面,处于悬空状态
        //取最近路标点为复位点
        if (!isColliderGround)
        {
            nearestPoint = WaypointsModelAll[ClosestWP.Index].Position;
        }

        #endregion


        transform.position = nearestPoint;
        transform.rotation = Quaternion.LookRotation(ClosestWP.Rotation * Vector3.forward);
        GetComponent <Rigidbody>().velocity        = Vector3.zero;
        GetComponent <Rigidbody>().angularVelocity = Vector3.zero;
    }