文章目录

  • 一、前言
  • 二、制作场景
    • 1、制作针模型
    • 2、桌面制作
    • 3、平行线制作
  • 三、物理仿真
    • 1、桌面无反弹
    • 2、针掉落
    • 3、针滚动问题
    • 4、针架到平行线上的问题
    • 5、针与针相互影响的问题
  • 四、UI界面
  • 五、编写代码
    • 1、针脚本
    • 2、对象池
    • 3、入口脚本
  • 六、运行测试
  • 七、工程源码
  • 八、完毕

一、前言

嗨,大家好,我是新发。
我有个后端同事去面试的时候被问到了 蒲丰投针问题,可能有少部分同学没听过蒲丰投针问题,我这里简单科普一下。
假设桌面上画满间隔均为DDD的平行直线,向桌面任意投放一根长为LLL(L<DL<DL<D)的针,可以通过几何概型的计算得出:针与某直线相交的概率为:
P=2LπDP = \frac{2L}{πD} P=πD2L​
当L=0.5DL = 0.5DL=0.5D时,
P=2LπD=DπD=1πP = \frac{2L}{πD} = \frac{D}{πD} = \frac{1}{π} \quad\quad P=πD2L​=πDD​=π1​
也就是说,在L=0.5DL = 0.5DL=0.5D的情况下,我们总共投了MMM根针,有NNN根针与平行线相交,则
1P≈MN≈π\frac{1}{P} \approx \frac{M}{N} \approx π \quad\quad P1​≈NM​≈π
证明过程网上有很多,这里我就不展开了,我今天要做的,就是使用Unity来对这个实验进行仿真,看看实验结果是不是与理论一致,我在网上没有看到有人使用Unity做过蒲丰投针的仿真实验,那我就来做全网第一人吧~

二、制作场景

1、制作针模型

Unity创建一个工程,在Hiererchy面板空白处点击鼠标右键,点击菜单3D Object / Cylinder,创建一个圆柱体,

如下

调整Scale缩放,让它变成一个很细的圆柱体,

如下:

创建个材质球,调为红色,赋给它,这样看起来显眼一点,效果如下:

2、桌面制作

创建一个Cube

如下

调整Scalexz,让它成为一个大桌面,

3、平行线制作

也是使用圆柱体,拉长,然后等间距排列即可,确保间距是针的长度的两倍,效果如下:

三、物理仿真

1、桌面无反弹

我希望针掉落到桌面时不要有弹跳,我们制作一个物理材质,
Project面板空白处右键鼠标,点击菜单Create / Physic Material

设置动态阻力和静态阻力为100,弹性为0Friction CombineBounce Combine都设置为Minimum

把物理材质赋值给桌面的碰撞体组件的Material属性,如下,

2、针掉落

给针添加Rigidbody组件,

这样针就会收到重力作用而向下掉落,如下:

3、针滚动问题

我们看到针掉到桌面时,会滚动,

这是因为帧本身的角阻力太小,我们选中针物体,把它的Rigidbody的角阻力设置为100

可以看到掉到桌面后不会滚动了,不过躺平时也会受到角阻力作用,

没关系,我们确保阵掉落的姿势与桌面平行就好了,

4、针架到平行线上的问题

我们看到,当帧落到平行线上时,会架在平行线上,

只需要把平行线弄成触发器就可以了,

效果如下:

5、针与针相互影响的问题

当一根针掉落在另一根针上时,会相互影响,比如架在别的针身上,影响与平行线的检测,比如这样子,

这个问题怎么解决呢?我们给针单独做一个层,

添加一个needle层,

把针设置为needle层,

然后打开Project Settings,进入Physics,把碰撞矩阵里的needle勾选去掉,

可以看到,针与针可以相互穿透,互不影响了,

四、UI界面

使用UGUI简单做一下界面,如下

五、编写代码

1、针脚本

创建一个Needle.cs脚本,编写碰撞检测逻辑,逻辑很简单,我都写了注释,大家应该能看懂,

using UnityEngine;
using System;public class Needle : MonoBehaviour
{/// <summary>/// 碰撞到平行线回调/// </summary>public Action hitLineCb;/// <summary>/// 碰撞到地面回调/// </summary>public Action hitPlaneCb;private Rigidbody rig;/// <summary>/// 延迟回收/// </summary>private float delayHideTimer;/// <summary>/// 是否碰到了平行线/// </summary>private bool isHitedLine = false;private void Awake(){rig = GetComponent<Rigidbody>();}private void OnEnable(){delayHideTimer = 0f;rig.isKinematic = false;isHitedLine = false;}public void OnTriggerEnter(Collider collision){if (isHitedLine) return;// 碰到了平行线if("line" == collision.gameObject.tag){isHitedLine = true;hitLineCb?.Invoke();}}public void OnCollisionEnter(Collision collision){// 碰到了桌面if("plane" == collision.gameObject.tag){// 1秒后回收delayHideTimer = 1f;}}private void Update(){if (delayHideTimer > 0){delayHideTimer -= Time.deltaTime;if (delayHideTimer <= 0){hitPlaneCb?.Invoke();}}}
}

Needle.cs脚本挂到针物体上,

设置桌面的tagplane

设置平行线的tagline

2、对象池

因为要很高频地丢针,如果每次都创建销毁会比较浪费CPU,所以我们写个对象池脚本:NeedlePool.cs,代码如下:

using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 对象池
/// </summary>
public class NeedlePool
{/// <summary>/// 入池/// </summary>public void Enqueue(GameObject obj){objPool.Enqueue(obj);}/// <summary>/// 出池/// </summary>public GameObject Dequeue(){if (objPool.Count == 0) return null; return objPool.Dequeue();}private Queue<GameObject> objPool = new Queue<GameObject>();
}

3、入口脚本

创建Main.cs作为入口脚本,实现交互和控制,代码如下:

using UnityEngine;
using UnityEngine.UI;public class Main : MonoBehaviour
{public Text totalCntText;public Text hitedCntText;public Text resultText;public GameObject needleObj;public Button startBtn;public Text btnStateText;private int totalCnt;private int hitedCnt;private float timer;private bool isStarted = false;// 对象池private NeedlePool pool = new NeedlePool();private void Awake(){needleObj.SetActive(false);}private void Start(){startBtn.onClick.AddListener(() => {isStarted = !isStarted;btnStateText.text = isStarted ? "停止" : "开始";});}void Update(){if (Input.GetMouseButtonDown(0)){// 鼠标点击,生成针GenNeedle();UpdateText();}if (isStarted){// 自动生成针timer += Time.deltaTime;if (timer > 0.03f){// 提高丢针数量,加快速度for (int i = 0; i < 7; ++i){GenNeedle();}UpdateText();timer = 0;}}}/// <summary>/// 生成针/// </summary>private void GenNeedle(){++totalCnt;var obj = pool.Dequeue();if(null == obj)obj = Instantiate(needleObj);var x = Random.Range(-100f, 100f);var y = 0.1f;var z = Random.Range(-60f, 60f);obj.transform.position = new Vector3(x, y, z);obj.transform.rotation = Quaternion.Euler(new Vector3(90, Random.Range(-360f, 360f), 0));obj.SetActive(true);var needle = obj.GetComponent<Needle>();needle.hitLineCb = () =>{++hitedCnt;UpdateText();};needle.hitPlaneCb = () => {obj.SetActive(false);pool.Enqueue(obj);};}/// <summary>/// 更新UI/// </summary>private void UpdateText(){totalCntText.text = totalCnt.ToString();hitedCntText.text = hitedCnt.ToString();if(0 != hitedCnt)resultText.text = ((float)totalCnt / hitedCnt).ToString("#0.00000");}
}

Main.cs脚本挂到MainPanel上,并赋值成员对象,如下:

六、运行测试

运行Unity,测试效果如下:

投了十万多针,

继续投针,投了一百万针,

π的理论值很接近啦,实验成功~

七、工程源码

本文工程我已上传到CODE CHINA,感兴趣的同学可自行下载学习,
地址:https://codechina.csdn.net/linxinfa/UnityBuffonNeedlesGame
注:我使用的Unity版本为Unity 2021.1.9f1c1 (64-bit)

八、完毕

好了,今天就到这里吧。

我是林新发:https://blog.csdn.net/linxinfa
原创不易,若转载请注明出处,感谢大家~
喜欢我的可以点赞、关注、收藏,如果有什么技术上的疑问,欢迎留言或私信,拜拜~

【游戏仿真实验】Unity仿真蒲丰投针实验,丢针计算圆周率,丢了一百万次针得出的结果是...相关推荐

  1. 蒲丰投针计算机模拟ppt,蒲丰投针实验模课件.doc

    概率论与数理统计实验 蒲丰投针与蒙特卡罗法 班级 应数12级01班 学号 2012444086 姓名 张旭东 蒲丰投针与蒙特卡罗法 张旭东 2012444086 (重庆科技学院 数学与应用数学 ,重庆 ...

  2. 蒲丰投针问题的matlab仿真

    吃饭的时候突然想到蒲丰投针问题. 在许多地方都遇到过此针,高中概统,大学概统,随机过程的概率部分,今天读Shannon的传记,他女儿不小心把针洒地上了. 问题描述: 在平面中有一组间隔为a的平行线,随 ...

  3. Matlab模拟蒲丰投针实验计算Π值

    文章目录 1.前言 2.实验目的 3.实验原理 (1)问题描述 (2)问题求解 4.实验过程 5.实验结果 6.实验结论 7.Matlab代码 1.前言 学习了概率论,决定自己动手编程实现蒲丰投针实验 ...

  4. 蒲丰投针结果_只能用纸笔才能计算圆周率?蒲丰告诉你,投针游戏也可以

    自从很久以前人们发现了存在圆周率π这个神奇的数字之后,便费尽一切心力来计算这个值.在那个数学工具比较匮乏的时代,人们能够做的就是根据圆周率的定义来计算.历史上,东西方几乎在同时发现了割圆术,虽然细节上 ...

  5. 强化学习 蒲丰投针实验 蒙特卡洛算法

    目录 一.蒲丰投针实验 1.1背景故事 1.2原理介绍 二.蒙特卡洛方法 2.1方法介绍 2.2经验轨迹 2.3在线学习与离线学习 2.4数学原理 一.蒲丰投针实验 1.1背景故事 1777年,蒲丰请 ...

  6. 一文读懂蒲丰投针实验

    这个博客源于概率论复习期间,蒙特卡罗方法的思想起源,这种求π\piπ的思路非常的巧妙 附:历史上用蒲丰投针实验估计圆周率的实验记录,来源 蒲丰投针 蒲丰投针实验是法国数学家.自然科学家"乔治 ...

  7. 蒲丰投针实验的一些理解

    由于要做ppt这里把自己的代码先暂时放上来,不当之处请多指正! 实验过程: 1)取一张白纸,在上面画上许多条间距为a的平行线. 2) 取一根长度为l(l≤a) 的针,随机地向画有平行直线的纸上掷n次, ...

  8. 蒲丰投针计算机模拟ppt,蒙特卡罗模拟课件.ppt

    <蒙特卡罗模拟课件.ppt>由会员分享,提供在线免费全文阅读可下载,此文档格式为ppt,更多相关<蒙特卡罗模拟课件.ppt>文档请在天天文库搜索. 1.蒙特卡洛模拟数学实验之前 ...

  9. R语言-蒲丰投针问题(向量化)

    蒲丰投针问题的具体过程及推导可参考百科,此处不再赘述,这里仅给出模拟步骤和实现代码. 蒲丰投针试验的模拟步骤 设定试验总次数 NNN,成功次数m=0m = 0m=0,针的长度为hhh,平行线间的距离为 ...

最新文章

  1. 【73套】Epic Stock Media配乐音效素材合集包
  2. SharePoint 检测页面编辑模式
  3. 五年引用量最高的10大论文:Adam第一,Transfromer上榜!竟然没有ResNet?
  4. Shadow of Survival
  5. java socket聊天工具_java+socket 简易聊天工具
  6. 在web项目中发布jaxws
  7. 使用 Maven 执行 java main class(java应用程序)
  8. DevExpress.XtraBars.Ribbon控件使用系列 (1)创建Ribbon窗体
  9. TCP/IP数据包结构分析
  10. Tree Recovery(二叉树递归遍历+求后序遍历模板)
  11. object.prototype.call
  12. python设置tk退出_退出tkinter gui
  13. CSS 文本转换 text-transform属性
  14. 微博抽奖贴为什么到时间了不开奖_热搜第一!微博闹剧,锦鲤“信小呆”被这样处罚...
  15. 随想录(学校作业和工程代码)
  16. clickhouse算术函数
  17. 数据库宿舍管理系统MySQL表_数据库课程设计报告—宿舍管理系统.doc
  18. Mixgo CE初体验
  19. 局域网传输/共享大文件
  20. 小学计算机面试说课稿,小学信息技术面试说课稿(模板)

热门文章

  1. 修改MySQL数据库的密码
  2. docker容器创建
  3. NCBI:美国国立生物技术信息中心大型数据库
  4. vue 一键复制粘贴文字功能
  5. the daily 发布了
  6. 金融IT 行业常见术语
  7. 上海高中计算机知识点总结,上海高中高考数学知识点总结(大全)
  8. 应用程序无法正常启动(0xc000007b)解决办法
  9. 关于对信号归一化后的频谱“消失”问题
  10. 关于音频工作站的一些事儿