Unity中的交互式2D地图

Jes*_*ano 0 c# interactive shape unity-game-engine

我对Unity相当陌生,但是我已经找到了解决方法。但是,我遇到了一个问题,无论我用多少谷歌搜索,我似乎都找不到有效的解决方案。我可能只是在做一些愚蠢的事情。任何帮助,将不胜感激。我发布到了Unity论坛,但是没有人回应,所以我想我也会给Stack Overflow一个机会。

所以我想做的是在Unity中创建2D地图。该地图将用于在3D世界中导航。该地图必须是可点击的,因为我将从世界地图开始,然后根据用户的点击,将地图更改为该国家/地区的地图。我曾与不同的人交谈过,我想使用的方式是使用shapefile,因为它们已经包含了有关国家和州边界的信息。另外,我知道将来我将不得不使用shapefile,所以我认为现在可以对它们进行一些练习。我想从小处着手,所以我下载了一个zip文件,其中包含美国的shapefile。我按照论坛的说明下载了QGIS,并在该软件中打开了shapefile。在QGIS中,我能够突出显示各个状态,如下图所示

我从QGIS得到的东西。 仍要在Unity中突出显示并选择

现在,我希望在Unity中具有相同的功能,除了我不仅要突出显示它,还希望它可以单击并能够将其标识为蒙大拿州。

因此,从这里我可以将该文件转换为DXF,然后将其转换为FBX。但是在那之后我迷路了。我不确定我是否必须进行这些转换。

如果有人可以帮助我,我将不胜感激!同样,我是Unity新手,所以如果您能牢记这一点,我将不胜感激。

Pro*_*mer 6

在此处输入图片说明

下面的答案描述了如何做到这一点。出于示范目的,只有八个国家完成了这项工作。

4个步骤可以执行此操作,但是每个步骤都可能包含另一个步骤。创建模型,将其导出并将其导入到Unity中,添加Mesh Collider到每个模型中,使用来检测单击,OnPointerDown然后更改所单击的GameObject的颜色。

为此,您需要Maya 2016Unity 5.5

首先要注意的是Maya具有简单的菜单和选项菜单。

如果我说“(选项菜单)”,则是说右侧菜单旁边的框。看下图,了解菜单和选项菜单之间的区别:

在此处输入图片说明

确保检查以下指令中是否包含“(选项菜单)”。

1.创建用于对状态建模的图像参考

。获取参考地图图像。

查找美国各州的黑白图像参考。我将使用这个,所以下载它。

B。用参考文件制作图像平面。

打开Maya并创建新项目,然后导入下载的状态图像。

为此,请转到“ 创建 -> 自由图像平面”

在“ 图像平面属性”下,选择“ 图像名称”中的图标,然后在此处放置您下载的图像地图参考的路径。

在此处输入图片说明

C切换到前视图。

选择“ 图像平面”,将鼠标置于视图的中间,然后按键盘上的SPACE键。您将看到四个相机视图。将鼠标移到左下视图(Front View),然后再次按SPACE键。Maya将切换到“前视图”。您将在前视图中工作。

现在,按F放大图像平面。

在此处输入图片说明

D。图像平面放置在一个层中,然后将其锁定。

相机在“ 图像平面”中放大后,如果未选择,请再次选择“ 图像平面”,然后单击“ 通道盒/图层编辑器”

现在,单击Layers- > 从Selected创建Layer。在创建的图层上有三个复选框

继续单击第三个(最后一个)复选框,直到显示“ R”。“ R”将锁定图像平面,以便在建模时不能再次选择它或干涉它。

在此处输入图片说明

2.创建每个状态模型

一个 .Create曲线进入创建 - > 曲线工具 - > 铅笔曲线工具

按住鼠标左键并在所选状态周围进行跟踪,以绘制一个状态。在行的开头和结尾之间留一点空间。

我将以内布拉斯加州为例。

在此处输入图片说明 B。关闭曲线。

选择曲线,然后转到曲线 -> 打开/关闭

在此处输入图片说明

C。创建一个Nurbs平面以覆盖您绘制的曲线的整个形状。

选择曲线,然后转到“ 修改 -> 中心枢轴”

您将使用此曲线从Nurbs Plane中剪切出其形状。

转到“ 创建 -> NURBS基本体”,然后确保已选中/启用了“ 交互创建”“完成时退出”

转到创建 -> NURBS基本体 -> 平面

按住鼠标左键,然后拖动并移动鼠标以创建一个平面。确保“平面”的大小覆盖步骤2A中绘制的状态的形状。

在此处输入图片说明

D。将曲线投影到曲面

选择这两个平面步骤创建2C曲线步骤创建2A

为此,请按住鼠标左键,然后将鼠标指针拖到两个鼠标上,然后松开。

现在应该选择两个对象。

转到曲面 -> 曲面上的投影曲线

在此处输入图片说明

E。修剪所选对象。

从步骤D中选择平面。

转到表面 -> 修剪工具

单击曲线的内部(中间),然后按Enter

现在应该从平面上切出曲线的形状,

在此处输入图片说明

F。删除历史记录,然后将枢轴居中。

选择在此过程中创建的所有内容(按住并在所有内容上移动鼠标,然后释放)。

转到编辑 -> 按类型删除 -> 历史记录

转到修改 -> 中心枢轴

在此处输入图片说明

G。将NubSurface平面转换为多边形,因为Unity和其他游戏引擎使用多边形。

从步骤E中选择平面。

转到“ 修改” ->“ 转换” ->“将NURBS 转换为多边形”(选项菜单)

使用以下设置:

类型:四边形

镶嵌方法:标准拟合

弦高比:0.54

分数公差:0.01

最小边长:0.001

3D增量:0.0461

单击应用。

现在,您有了一个多边形,将其重命名为适当的状态名称(内布拉斯加州)。

在此处输入图片说明

H。删除后面的对象

仍选择多边形。

转到修改 -> 冻结转换

转到修改 -> 中心枢轴

将多边形移开。之后,删除其后面的所有其他对象(NubSurface和曲线)。

再次选择多边形,然后转到“ 修改 -> 重置变换”。这将使多边形回到其原始位置。

转到修改 -> 中心枢轴

在此处输入图片说明

。添加材料创建的状态。

转到“ 渲染”选项卡。

单击圆形图标,它是Blinn材质。它将创建一个Blinn材料。将其命名为“ State_Material”。如果您已经创建了“ State_Material”,则不必创建新的。

转到渲染模式。

选择多边形。

转到“ 照明/阴影” ->“ 分配现有材料” ->“ State_Material”

目标是将一种材料(状态_材料)分配给所有状态/多边形。这样可以避免将50种材料导出到Unity。

在此处输入图片说明

J。自动绘制UV。

转到UV- > 自动

在此处输入图片说明

然后,K。删除历史记录将转换后的对象的枢轴居中。

转到编辑 -> 按类型删除 -> 历史记录

转到修改 -> 中心枢轴

在此处输入图片说明

做完了!跳回到2.创建每个状态模型。并为其余州做相同的事情。

3.导出为FBX

。出口作为FBX。

选择所有状态。我的场景中有8个。

转到文件 -> 导出选择...(选项菜单)

文件类型更改为FBX导出

单击导出选择按钮

选择目录和文件名,然后再次单击导出选择

在此处输入图片说明

4.在Unity中使用地图

一个 .IMPORT的FBX到Unity。

打开Unity,转到资产 -> 导入新资产...

选择通过Maya保存的目录和FBX文件。

在此处输入图片说明

B。将网格碰撞器附加到每个状态/平面。

将地图拖动到层次结构。

选择所有状态/模型,然后转到组件 -> 物理 -> 网格碰撞器

在此处输入图片说明

C。将模型定位到摄像机视图。

必须将对象在y轴上旋转到180度,然后将x和y轴缩放到100。如果按照相同的图像参考完全按照本教程进行操作,则必须将其旋转并缩放道路。

在此处输入图片说明

D.设置事件系统

转到GameObject- > 创建空,然后将其命名为“ EventSystem”。

转到组件 -> 事件 -> 事件系统

转到组件 -> 事件 -> 独立输入模块

选择“主摄像机”,然后转到“ 组件 -> 事件 -> 物理Raycaster”。我说Physics Raycaster不是Physics 2D Raycaster

在此处输入图片说明

E。附加测试脚本

进入游戏对象 - > 创建空,然后将其命名为“MapManager”。

选择MapManager GameObject并将MapManager脚本附加到该对象。

选择除父对象之外的所有状态/模型,然后将MapClickDetector脚本附加到所有状态/模型。一次执行比较容易。

在此处输入图片说明

脚本说明

MapClickDetector脚本将检测鼠标单击,鼠标悬停和其他鼠标操作,然后将其发送到MapManager脚本。然后,您可以在MapManager脚本中执行所需的任何操作。它还发送被单击的Map GameObject,以便您可以获得州的名称。

为了检测点击, IPointerDownHandler实现,然后OnPointerDown用于检测地图中哪个状态被点击。您也可以使用Raycast,IPointerDownHandler效果更好,因为它可以防止UI出现问题。

MapManager脚本:

using UnityEngine;

public class MapManager : MonoBehaviour
{
    Color normalColor = Color.red;

    Color mouseDownColor = Color.green;
    Color mouseEnterColor = Color.yellow;

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    public void mapclick(GameObject objClicked)
    {
        Debug.Log("Clicked: " + objClicked.name);
    }

    public void mapMouseDown(GameObject objClicked)
    {
        Debug.Log("Pointer Down: " + objClicked.name);

        MeshRenderer mr = objClicked.GetComponent<MeshRenderer>();
        mr.material.color = mouseDownColor;
    }

    public void mapMouseUp(GameObject objClicked)
    {
        Debug.Log("Pointer Up: " + objClicked.name);

        MeshRenderer mr = objClicked.GetComponent<MeshRenderer>();
        mr.material.color = normalColor; ;
    }

    public void mapMouseEnter(GameObject objClicked)
    {
        Debug.Log("Pointer Enter: " + objClicked.name);

        MeshRenderer mr = objClicked.GetComponent<MeshRenderer>();
        mr.material.color = mouseEnterColor;
    }

    public void mapMouseExit(GameObject objClicked)
    {
        Debug.Log("Pointer Exit: " + objClicked.name);

        MeshRenderer mr = objClicked.GetComponent<MeshRenderer>();
        mr.material.color = normalColor;
    }
}
Run Code Online (Sandbox Code Playgroud)

MapClickDetector脚本:

using UnityEngine;
using UnityEngine.EventSystems;

public class MapClickDetector : MonoBehaviour, IPointerClickHandler, IPointerDownHandler,
    IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler
{
    MapManager mapManager;

    void Start()
    {
        addPhysicsRaycaster();

        mapManager = GameObject.Find("MapManager").GetComponent<MapManager>();
    }

    void addPhysicsRaycaster()
    {
        PhysicsRaycaster physicsRaycaster = GameObject.FindObjectOfType<PhysicsRaycaster>();
        if (physicsRaycaster == null)
        {
            Camera.main.gameObject.AddComponent<PhysicsRaycaster>();
        }
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        mapManager.mapclick(gameObject);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        mapManager.mapMouseDown(gameObject);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        mapManager.mapMouseUp(gameObject);
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        mapManager.mapMouseEnter(gameObject);
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        mapManager.mapMouseExit(gameObject);
    }
}
Run Code Online (Sandbox Code Playgroud)