[Godot] C#简单实现2D节点图生成

我需要做一个随机的2D节点图,用来作为游戏的大地图,对于我这种简单的需求,完全可以在划定地图长宽和最小距离后,直接全随机生成,当然,这样就显得不够"优雅",在某些情况下还会有空洞或不均匀等问题,这里我就给大家分享一下两个简单的实现方法

实现过程

泊松盘采样

简单来说,泊松盘采样就是通过现有点来生成点集,规范的还会有网格加速活跃点列表来进行生成优化,对于我要实现的效果,这些优化暂时是不需要的

特性
  • 从一个随机起点开始,逐步生成新点。

  • 新点基于已有点,随机选择一个方向和距离(在某个范围内),并检查是否满足最小距离约束。

  • 如果新点满足约束(不与其他点太近且在边界内),则加入点集;否则放弃并重新尝试。

代码实现

代码部分

简单泊松盘采样
cs 复制代码
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;

public partial class PointGenerate : Node2D
{
    //大地图点生成

    [Export] public int mapX;       //长
    [Export] public int mapY;       //宽
    [Export] public int pointCount;     //数量
    [Export] public int tryCount;       //尝试次数
    [Export] public float mixLength;        //最小距离

    private List<PointScript> points = new();       //地图节点集

    [ExportCategory("Node")]
    [Export] public PackedScene testPoint;      //测试节点
    [Export] public Node2D mapPoints;       //挂载节点

    public override void _Ready()
    {
        PointMap();
    }

    public override void _Process(double delta)
    {
        if (Input.IsKeyPressed(Key.Space))        //为了方便调试用空格生成
            PointMap();
    }

    private void PointMap()         //点生成
    {
        mapPoints.GetChildren().ToList().ForEach(child => child.QueueFree());
        points.Clear();
        
        var firstPoint = testPoint.Instantiate() as PointScript;
        float pointX = GD.RandRange(0, mapX);
        float pointY = GD.RandRange(0, mapY);
        firstPoint.Position = new Vector2(pointX, pointY);
        points.Add(firstPoint);
        mapPoints.AddChild(firstPoint);

        int attempts = 0;
        while (points.Count < pointCount && attempts < tryCount * points.Count){
            attempts++;

            var basePoint = points[GD.RandRange(0, points.Count - 1)];

            float angle = GD.Randf() * MathF.Tau;
            float dist = (float)GD.RandRange(mixLength, mixLength * 2f);
            Vector2 newPoint = basePoint.Position + new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * dist;

            //边界检查
            if (newPoint.X < 0 || newPoint.Y < 0 || newPoint.X > mapX || newPoint.Y > mapY)
                continue;

            //点距离检查
            bool isDist = false;
            foreach (var p in points)
            {
                if (p.Position.DistanceTo(newPoint) < mixLength)
                {
                    isDist = true;
                    break;
                }
            }
            if (isDist)
                continue;

            var point = testPoint.Instantiate() as PointScript;
            point.Position = newPoint;
            points.Add(point);
            mapPoints.AddChild(point);
        }
    }

}
简单随机
cs 复制代码
private void PointMap()
    {
        mapPoints.GetChildren().ToList().ForEach(child => child.QueueFree());
        points.Clear();

        int attempts = 0;
        while (points.Count < pointCount && attempts < tryCount)
        {
            attempts++;

            float pointX = GD.RandRange(0, mapX);
            float pointY = GD.RandRange(0, mapY);
            Vector2 newPoint = new Vector2(pointX, pointY);

            //点距离检查
            bool isDist = false;
            foreach (var p in points)
            {
                if (p.Position.DistanceTo(newPoint) < mixLength)
                {
                    isDist = true;
                    break;
                }
            }
            if (isDist)
                continue;

            var point = testPoint.Instantiate() as PointScript;
            point.Position = newPoint;
            points.Add(point);
            mapPoints.AddChild(point);
        }
    }

效果展示

总结

还有很多问题,比如形状和分布问题,还可能会有点生成缺失问题(可以将边界检查去掉),大家可以根据自己的需要进行修改

相关推荐
沉默金鱼1 小时前
Unity实用技能-UI进度条
ui·unity·游戏引擎
老朱佩琪!8 小时前
Unity离线开发经验分享
unity·游戏引擎
Sator110 小时前
unity的GPUInstance和GPU动画
unity·游戏引擎
沉默金鱼1 天前
Unity实用技能-模型
unity·游戏引擎
阿里云云原生1 天前
AgentRun:如何利用 AI Agent 构建现代化的舆情分析解决方案?
人工智能·unity·游戏引擎
老朱佩琪!1 天前
Unity代理模式
unity·游戏引擎·代理模式
技术小甜甜1 天前
【Godot】【入门】GDScript 快速上手(只讲游戏里最常用的 20% 语法)
android·游戏·编辑器·游戏引擎·godot
老朱佩琪!1 天前
Unity命令模式
unity·游戏引擎·命令模式
世洋Blog1 天前
Unity编辑器基础
unity·c#·编辑器·游戏引擎
WarPigs1 天前
Unity NetCode for GameObject笔记
笔记·unity·游戏引擎