Unity中的交互式2D地图

时间:2017-01-06 11:47:13

标签: c# unity3d shape interactive

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

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

What I get from QGIS. Still want the highlighting and selecting in Unity

现在我想在Unity中使用相同的功能,除了我不想突出显示它,我还希望它可以点击并且能够将该状态识别为蒙大拿州。

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

如果有人能帮助我,我会非常感激!再次,我是Unity的新手,所以如果你能牢记这一点我会非常感激。

1 个答案:

答案 0 :(得分:3)

enter image description here

下面的答案描述了如何实现这一目标。为了演示目的,仅使用 8 状态完成此操作。

4 步骤,但每个步骤可能还有另一个步骤。创建模型,导出模型并将其导入Unity,向每个模型添加Mesh Collider,使用OnPointerDown检测单击,然后更改单击的GameObject的颜色,。

您需要 Maya 2016 Unity 5.5

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

如果我说"(选项菜单)",我说的是右侧菜单旁边的方框。请查看下面的图片,了解菜单和选项菜单之间的区别:

enter image description here

请务必检查以下任何说明是否有"(选项菜单)"在它。

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

A 。获取参考地图图片。

查找美国各州的黑白图像参考。我将使用this一个下载它。

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

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

要执行此操作,请转到创建 - > 免费图像平面

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

enter image description here

C 。切换到前视图。

选择图像平面,将鼠标放在视图中间,然后按键盘上的SPACE键。您将看到四个摄像头视图。将鼠标移动到左下角视图(前视图),然后再次按 SPACE 键。 Maya将切换到Front View。您将在前视图中工作。

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

enter image description here

D 。将图像平面放入图层然后将其锁定。

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

现在,点击图层 - > 从选定的创建图层。创建的图层上有三个复选框

继续点击第三个(最后一个)复选框,直到它显示" R"。 " R"将锁定图像平面,以便在建模时无法再次选择或干扰它。

enter image description here

2.创建每个州的模型

A 。创建曲线 转到创建 - > 曲线工具 - > 铅笔曲线工具

通过按住鼠标左键并在所选状态周围跟踪来逐个绘制任何状态。在行的开头和结尾之间留一点空间。

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

enter image description here B 。关闭曲线。

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

enter image description here

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

选择曲线,然后转到修改 - > Center Pivot

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

转到创建 - > NURBS Primitives 然后确保选中/启用交互式创建退出完成

转到创建 - > NURBS原语 - > 平面

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

enter image description here

D 。将曲线投影到曲面

选择两者在步骤 2C 中创建的平面和在步骤 2A <中创建的曲线 / strong>即可。

您可以通过按住鼠标左键并将鼠标光标拖到它们上面然后释放来实现。

现在应该选择两个对象。

转到 Surfaces - &gt; 表面上的项目曲线

enter image description here

E 。修剪所选对象。

从步骤 D 中选择平面。

转到 Surfaces - &gt; 修剪工具

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

现在应该从平面上剪下曲线的形状,

enter image description here

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

选择在此过程中创建的所有内容(左键单击并按住然后将鼠标移动到所有内容然后释放)。

转到修改 - &gt; 按类型删除 - &gt; 历史

转到修改 - &gt; Center Pivot

enter image description here

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

从步骤 E 中选择平面。

转到修改 - &gt; 转换 - &gt; NURBS到多边形(选项菜单)

使用下面的设置:

类型:四元组

曲面细分方法:标准版

弦高比:0.54

分数容差:0.01

最小边长:0.001

3D delta:0.0461

单击“应用”。

现在,您有一个多边形,将其重命名为相应的州名(内布拉斯加州)。

enter image description here

H 。删除背后的对象

仍然选择了多边形。

转到修改 - &gt; 冻结转换

转到修改 - &gt; Center Pivot

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

再次选择多边形,然后转到修改 - &gt; 重置转换。这将使多边形回到原始位置。

转到修改 - &gt; Center Pivot

enter image description here

。添加状态创建的材料。

转到渲染标签。

点击圆形图标,这是一个 Blinn 材料。它将创建一个Blinn材料。将其命名为&#34; State_Material&#34;。如果您已经创建了&#34; State_Material&#34;,则无需创建新的。

进入渲染模式。

选择多边形。

转到照明/阴影 - &gt; 指定现有材料 - &gt; State_Material

目标是为所有State / polygon分配一个材质(State_Material)。这将防止必须将50种材料导出到Unity。

enter image description here

J 。自动映射UV。

转到 UV - &gt; 自动

enter image description here

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

转到修改 - &gt; 按类型删除 - &gt; 历史

转到修改 - &gt; Center Pivot

enter image description here

完成!跳回2.创建每个状态模型。并为州的其他地方做同样的事情。

3.Export为FBX

A .Export为Fbx。

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

转到文件 - &gt; 导出选择...(选项菜单)

文件类型更改为 FBX导出

单击导出选择按钮

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

enter image description here

4.在Unity中使用地图

A 。将Fbx导入Unity。

打开Unity,转到资产 - &gt; 导入新资产...

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

enter image description here

B 。将网格对撞机连接到每个州/飞机。

将地图拖动到层次结构。

选择所有州/模型,然后转到组件 - &gt; 物理 - &gt; 网格对撞机

enter image description here

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

必须在Y轴上将对象旋转到180度,然后将x和y轴缩放到100.如果您使用相同的图像参考完全像这样教程,那么您将必须旋转并缩放它同样的方式。

enter image description here

D .Setup Event System

转到 GameObject - &gt; 创建空然后将其命名为&#34; EventSystem&#34;。

转到组件 - &gt; 活动 - &gt; 活动系统

转到组件 - &gt; 活动 - &gt; 独立输入模块

选择&#34;主摄像头&#34;并转到组件 - &gt; 活动 - &gt; Physics Raycaster 。我说物理雷卡斯特不是物理2D雷卡斯特

enter image description here

E 。附录测试脚本

转到 GameObject - &gt; 创建空然后将其命名为#34; MapManager&#34;。

选择 MapManager GameObject并将MapManager脚本附加到其上。

选择除父对象以外的所有状态/模型,然后将MapClickDetector脚本附加到所有状态。做一次更容易。

enter image description here

脚本描述

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

要检测点击,IPointerDownHandler已实施,则OnPointerDown用于检测点击地图中的哪个州。您也可以使用Raycast,但IPointerDownHandler更好,因为它可以防止用户界面出现问题。

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;
    }
}

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);
    }
}