【unity实战】MapMagic 2实战例子
本文分享了MapMagic 2插件的14个实战案例,涵盖地形生成、物体放置、区域锁定等实用功能。从基础的地形绘制、树木和石头随机分布,到进阶的南北雪地混合、岛屿制作、高度分层生成物体等操作均有详细图示说明。文章还介绍了道路渲染、路径物体分布、月球表面模拟等特殊效果实现方法,并针对地形锁定过渡时的黑块问题提出了解决方案。最后推荐了作者的相关Unity开发专栏,包含游戏开发各领域教程。所有案例均配有直
前言
之前介绍了MapMagic 2插件的基础使用,这次来分享一些使用的实战例子。
一、实战
1、绘制简单地形、草


2、放置树木


3、随机放置石头
首先从上面合并输出树的位置信息
放置石头
效果
4、锁定自定义区域
我们可以在生成的地形上放置自定义的物品,比如村庄,甚至还可以通过Terrain地形工具某个区域的修改地形样式
然后我们在MapMagic上添加一个LOCKS锁定区域,覆盖我们前面修改的自定义区域
这样无论我们如何重新修改地形变化,这个区域都不会改变
但是这样有个缺点,就是这里的地形高度也被固定了,有时就会显得很突兀,我们可以选择勾选这个Relative Height选项,然后将新增的预制体对象作为LockedObjects 自定义区域的子物体
5、实现3种地形平滑混合过渡变化

结果地形上会出现黑色区域,不知道是什么原因,不知道是不是MM的BUG,文档也没有给解决方案
6、几种节点集合,实现南北是雪地,中间石头和草地混合


7、制作岛屿
孤岛


悬崖和海滩:参考https://www.youtube.com/watch?v=vvaeatp9JCU&list=PL8fjbXLqBxvbsJ56kskwA2tWziQx3G05m&index=9
无限地形群岛


8、创建对象下的平坦土地

9、不同高度生成不同物品
根据对象的高度分割散布的对象:如果对象的高度在 0-125 之间,则输出为松树;如果高度在 120-200 之间,则输出为石头。如果对象的高度在 120-125 之间,则可能随机输出为树或石头
10、修改物体附近的地面

11、去除物体附近的草

12、Stamp实现月球表面

13、渲染道路路径


14、沿路径随机放置物品,如路灯、树木、护栏等。


15、村庄村落
参考:https://www.youtube.com/watch?v=lkVCoHzNxcw


放石头装饰
水里不生成
调节参数,优化斜坡

二、代码控制
1、动态修改随机值和生成地形
using UnityEngine;
using Den.Tools;
using MapMagic.Core;
using MapMagic.Terrains;
using MapMagic.Products;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class NewMonoBehaviourScript : MonoBehaviour
{
#if UNITY_EDITOR
[MenuItem("CONTEXT/NewMonoBehaviourScript/重新生成")]
#endif
public static void Create()
{
MapMagicObject mapMagic = FindFirstObjectByType<MapMagicObject>();
int seed = Random.Range(1, 99999);
// 更改随机种子 32768是MM噪声的初始排列数。为了与seed 12345兼容
mapMagic.graph.random = new Noise(seed, permutationCount: 32768);
//触发重新生成
mapMagic.Refresh(clearAll: true);
}
}
2、常用事件
using UnityEngine;
using Den.Tools;
using MapMagic.Core;
using MapMagic.Terrains;
using MapMagic.Products;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class NewMonoBehaviourScript : MonoBehaviour
{
public void OnEnable()
{
//特定瓦片生成完毕
TerrainTile.OnTileApplied -= DoSomething;
TerrainTile.OnTileApplied += DoSomething;
//所有瓦片生成完毕
TerrainTile.OnAllComplete += DoAllComplete;
}
public void OnDisable()
{
TerrainTile.OnTileApplied -= DoSomething;
TerrainTile.OnAllComplete -= DoAllComplete;
}
private void DoSomething(TerrainTile tile, TileData data, StopToken stop)
{
//isDraft布尔值可用于判断是草稿瓦片还是主瓦片。
if (data.isDraft)
{
Debug.Log("刚应用了草稿瓦片");
}
else
{
Debug.Log($"应用了主瓦片于坐标 {tile.coord.x}, {tile.coord.z}");
}
}
private void DoAllComplete(MapMagicObject @object)
{
Debug.Log("全部加载完成");
//渲染雪等等
}
}
能否砍伐树木?
这是可以实现的,但这属于游戏玩法层面的功能,略微超出了MapMagic的范畴。您需要编写自定义脚本并将其挂载到每个树木预制体上。请注意,要使这些脚本正常工作,您的树木必须设置为对象实例(而非Unity地形系统中的树木),因此请改用Objects输出端口而非Trees输出端口。同时请确保在输出属性中禁用Use Pool选项,否则被砍伐的树木将会在新地形中重新生成(实际上只是被移动至新地形)。
树木无法旋转/缩放
原因:若使用 Trees 输出端口,树木会作为Unity地形树实例放置,受限于引擎的广告牌/ impostor 系统,无法进行旋转和缩放。
解决方案:改用 Objects 输出端口,将树木作为标准游戏对象放置。但会失去Unity对树木的批处理和广告牌优化,性能可能下降。
如何将植被设置为预制体而非网格?
在Grass Output节点中:
将模式切换为 VertexLit。
在对象栏位分配您的预制体。
在高级设置中启用 Instancing。
重要:必须首先切换到 VertexLit 模式,使用 MeshUnlit 可能导致Unity崩溃。
5、我该如何保存我在游戏中所做的更改?
不要保存所有生成数据,仅序列化被更改的数据。
示例:玩家砍伐一棵树,只保存该树的位置/ID被砍伐的状态。待MapMagic重新生成瓦片后,在 OnTileApplied 事件中应用这些更改,移除被砍伐的树木。
5、动态放置角色
4、获取某个位置的材质是什么?
比如我们需要知道目前位置雪地的密度值,以调整降雪的强度。或者根据角色当前所在的地表纹理值修改脚本声
配置输出
using UnityEngine;
using Den.Tools;
using MapMagic.Core;
using MapMagic.Terrains;
using MapMagic.Products;
public class NewMonoBehaviourScript : MonoBehaviour
{
public Transform player;
void Start()
{
MapMagicObject mapMagicObject = GetComponent<MapMagicObject>();
float value = DirectMatricesHolder.FindValueAtPosition(mapMagicObject, "Snow", player.position.x, player.position.z);
// 0表示不在雪地上 1表示完全站在雪地上
Debug.Log("" + value);
}
}
专栏推荐
完结
好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!
更多推荐


所有评论(0)